Ruby on rails Rails-具有空数组的强参数
我正在向我的控制器发送一个关联ID数组,比如Ruby on rails Rails-具有空数组的强参数,ruby-on-rails,strong-parameters,Ruby On Rails,Strong Parameters,我正在向我的控制器发送一个关联ID数组,比如foo\u id。要允许值数组,我使用: params.permit(foo_ids: []) 现在的问题是,如果我发送一个空的foo\u id数组,那么该参数将被忽略。没有像空数组那样清除所有foo,而是将关联放在一边,因为不允许使用foo\u id 这可能是因为,当强参数查找的是标量值数组而不是单个标量值时,nil值被忽略 有人能提出一个解决这个问题的好办法吗?谢谢 其他信息 在更新控制器操作中,我需要能够处理两种情况。我需要能够将foo_id设
foo\u id
。要允许值数组,我使用:
params.permit(foo_ids: [])
现在的问题是,如果我发送一个空的foo\u id数组
,那么该参数将被忽略。没有像空数组那样清除所有foo
,而是将关联放在一边,因为不允许使用foo\u id
这可能是因为,当强参数查找的是标量值数组而不是单个标量值时,nil值被忽略
有人能提出一个解决这个问题的好办法吗?谢谢
其他信息
在更新控制器操作中,我需要能够处理两种情况。我需要能够将
foo_id
设置为空数组。如果我只想更新另一个字段,我还需要能够忽略foo_id
。如果nil不适用于第二种情况,则将foo\u id设置为空数组。我得出的临时解决方案是:
params[:foo_ids] ||= [] if params.has_key?(:foo_ids)
params.permit(foo_ids: [])
在这里,foo\u id
仅在传递时设置为空数组。如果未在请求中传递,则忽略它
我仍然希望找到一个更好的解决方案,因为这类事情在我正在进行的项目中很常见-如果你有更好的想法,请一定提出建议。这已经很晚了,但我自己也遇到了这个问题。我通过在permit语句中同时包含标量版本和数组版本来解决它,如下所示:
params.require(:photo).permit(:tags, tags: [])
仅供参考-必须将两者放在同一许可证声明中-如果你将它们链接起来,它将因某种原因被丢弃
编辑:我刚刚注意到通过这个方法提交的一个空数组将变成nil——我现在得到了一堆应该是空数组的字段,它们是nil。所以我发布的解决方案实际上对我不起作用
编辑第二个:我想我已经添加了这个,但是这个问题与Rails在params散列上执行deep_munge有关。这条评论解释了如何修复它:我最近也遇到了同样的问题,但这里的答案对我都不起作用。这是我的解决方案。如果您有javascript处理HTTP请求,这可能也适用于您
在客户端:
if (photo.tags.length === 0){
photo.tags = ["null"]
}
在你的photocontroller上
def photo_params
p = params.require(:photo).permit(tags: [])
p["tags"].reject! { |tag| tag == "null" }
p
end
此解决方案不适用于所有情况:
params.require(:photo).permit(:tags, tags: [])
例如,如果您正在使用MongoDB,并且您有一个tag_ID数组,它将ID存储在一个has_many集合中,那么如果您在模型中为属性指定“type:array”,则tag_ID属性必须是一个数组。因此,即使您执行以下操作,也无法发送具有nil值的tag_id:
params.require(:photo).permit(:tag_ids, tag_ids: [])
MongoDB的官方Ruby适配器Mongoid会抱怨tag_ID的值必须是数组
解决方案是您确实可以通过表单发送一个空数组!它不需要是json请求。您只需在表单上使用remote:true并通过type::js发送即可。怎么做?简单。只需在表单中添加一个隐藏输入,并将其值设置为空字符串:
<%= form_for @user, remote: true, html: { class: 'form' } do |f| %>
<%= select_tag("#{f.object_name}[tag_ids][]", options_for_select(Tag.all.collect {|t| [t.name, c.id]}, selected: f.object.tag_ids), { class: 'form-control', multiple: 'multiple' }) %>
<%= hidden_field_tag "#{f.object_name}[tag_ids][]", '' %>
<%= f.submit class: 'btn ink-reaction btn-raised btn-primary' %>
<% end %>
这是关键:
<%= hidden_field_tag "#{f.object_name}[tag_ids][]", '' %>
属性将作为空数组存储在数据库中。注意:我只使用Mongoid进行了测试,但我认为它在ActiveRecord中具有相同的功能。我遇到了相同的问题,并找到了与Donato类似的解决方案,尽管是在JS中构建多部分FormData时。诀窍是在数组中放入一个空字符串
const formData = new FormData()
formData.append('dish[tag_ids][]', '')
在控制器端,params带有“dish”=>{“tag_ids”=>[“”]}
,dish.update将其解释为“删除所有标记”。我正在考虑在_filter之前安装一个猴子补丁,我将对所有以“_ids”结尾的密钥做一些处理。想法?那会有用的。在一些情况下,我需要对散列中嵌套的参数执行此操作,因此您可能也希望根据自己的使用情况来处理这些参数。