Rails - Strong parameters with empty arrays

余生颓废 提交于 2019-12-20 09:27:34

问题


I'm sending an array of association ids, say foo_ids to my controller. To permit an array of values, I use:

params.permit(foo_ids: [])

Now, the problem is that if I send an empty array of foo_ids, the parameter is ignored. Instead of clearing all foos as an empty array should do, the association is left alone, because foo_ids isn't permitted.

This may be because an empty array is converted to nil in rails, and that nil value is ignored as strong parameters is looking for an array of scalar values, not a single scalar value.

Can anyone suggest a good way to solve this? Thanks!

Additional info

In an update controller action, I need to be able to handle two cases. I need to be able to set foo_ids to an empty array. I also need to be able to ignore foo_ids if I merely want to update another field. Setting foo_ids to an empty array if nil does not work for this second case.


回答1:


This is quite late, but I just had this problem myself. I solved it by including both the scalar version and array version in the permit statement, like so:

params.require(:photo).permit(:tags, tags: [])

FYI - it has to have both in the same permit statement - if you chain them it'll get thrown out for some reason.

EDIT: I just noticed that an empty array submitted via this method will be turned into nil - I've now got a bunch of fields that should be empty arrays that are nil. So the solution I posted doesn't actually work for me.

EDIT the second: Thought I had already added this, but this problem is related to Rails performing deep_munge on params hashes. This comment explains how to fix it: https://stackoverflow.com/a/25428800/130592




回答2:


The temporary solution I've come down to is:

params[:foo_ids] ||= [] if params.has_key?(:foo_ids)
params.permit(foo_ids: [])

Here, foo_ids is set to an empty array only if is passed. If it is not passed in the request, it is ignored.

I'm still hoping to find a better solution to this, as this sort of thing will be quite common in the project I'm working on - please do suggest better ideas if you have any.




回答3:


I had the same problem recently, but none of the answers here worked for me. This is my solution. If you have javascript handling HTTP requests, this may work for you, too.

In your client side:

if (photo.tags.length === 0){
  photo.tags = ["null"]
}

And on your PhotosController

def photo_params
  p = params.require(:photo).permit(tags: [])
  p["tags"].reject! { |tag| tag == "null" }
  p
end



回答4:


This solution won't work for all cases:

params.require(:photo).permit(:tags, tags: [])

For example, if you are using MongoDB and you have a tag_ids array, which stores the ids in a has_many collection, your tag_ids attribute MUST be an array if you specify "type: Array" for the attribute in your model. Consequently, it won't work to send tag_ids with a nil value even if you do this:

 params.require(:photo).permit(:tag_ids, tag_ids: [])

Mongoid, the official Ruby adapter for MongoDB, will complain the value of tag_ids must be an array.

The solution is you can indeed send an empty array via your form! And it doesn't need to be a json request. You can simply use remote: true on your form and send it via type: :js. How to do it? Simple. Just add a hidden input in your form and set its value to an empty string:

<%= 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 %>

This here is the key:

<%= hidden_field_tag "#{f.object_name}[tag_ids][]", '' %>

Your attribute will be stored as an empty array in your database. Note I only tested this with Mongoid, but I assume it carries the same functionality in ActiveRecord.



来源:https://stackoverflow.com/questions/20164354/rails-strong-parameters-with-empty-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!