Rails Strong Parameters: How to accept both model and non-model attributes?

大城市里の小女人 提交于 2019-12-10 17:27:15

问题


I have a form to create a user model with all its usual attributes, but I am also passing a lot of non-model attributes that based on which I will create further stuff in my controller action.

My question is how I can tell Strong Parameters to accept both the user data, AND this other data that is not related to the user db wise?

To illustrate, my form could like this (submit button deleted for brievity):

<%= form_for @user do |f| %>
  <%= f.text_field 'attribute1' %>
  <%= f.text_field 'attribute2' %>
  <%= f.text_field 'attribute3' %>

  <%= text_field_tag 'attribute_not_on_user_model1' %>
  <%= text_field_tag 'attribute_not_on_user_model2' %>
<% end %>

How can I use strong parameters to do this? I tried this:

params.require(:user).permit(:attribute1, :attribute2 , :attribute3, :attribute_not_on_user_model1, 
  attribute_not_on_user_model2)

And also this:

params.require(:user).permit(:attribute1, :attribute2 ,     
  :attribute3).require(:attribute_not_on_user_model1, 
  attribute_not_on_user_model2)

Both did not work. I am aware that I could do attr_accessor in the user, but I have a growing list of attributes in this form that are not related to the user model per se (but are nonetheless essential to the creation of the user model and its subsequent related models). We could debate that this is not the best way to do this (A form object comes to mind), but for the moment I want to see if Strong Parameters can help me here.


回答1:


user model attributes are stored inside the :user hash, whereas the non-user attributes are accessible directly at the params level.

If you inspect your params Hash, you will notice that it is constructed in the following way

{ user: { attribute1: "value", attribute2: value, ... }, attribute_not_on_user_model1: "value", attribute_not_on_user_model2: "value" }

Consequently, the call

params.require(:user)

will automatically ignore any other param that is not part of the user node. If you want to include also the other params, you either compose the hash, or update the view to inject the params in the form.

Injecting the parameter on the form will cause the params to be part of the same :user node. This approach normally works very well with virtual attributes (despite the concepts are not linked each other).

<%= form_for @user do |f| %>
  <%= f.text_field 'attribute1' %>
  <%= f.text_field 'attribute2' %>
  <%= f.text_field 'attribute3' %>

  <%= text_field_tag 'user[attribute_not_on_user_model1]' %>
  <%= text_field_tag 'user[attribute_not_on_user_model2]' %>
<% end %>

The other solution would be something like

def some_params
  hash = {}
  hash.merge! params.require(:user).slice(:attribute1, :attribute2, :attribute3)
  hash.merge! params.slice(:attribute_not_on_user_model1, 
  attribute_not_on_user_model2)
  hash
end

The solution, however, really depends on how you will user those params later. If all these params are sent as a single Hash, then you may want to compose the single hash, but in that case you may also want virtual attributes.

The point is that, without a real use case, the question itself is quite non-sense. StrongParameters is designed to filter a group of parameters passed to a bulk-create or bulk-update action. Generally, this means you have a model.

If you design a custom method, or if you have non-model methods, StrongParameters whitelisting may not have any sense, given you have control over the method you are writing and invoking.




回答2:


There are many ways to do this and one way is with accecpts_nested_attributes_for: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html



来源:https://stackoverflow.com/questions/26703770/rails-strong-parameters-how-to-accept-both-model-and-non-model-attributes

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