简体   繁体   中英

Separating multiple models in Rails form submission

Specifically, I have a form for creating a User . One of the fields is Group , which is a separate model. During the User#create action I call Group.find_or_create_by_name to check and see if the Group already exists by pulling out params[:user][:group] , and create the Group if it doesn't exist.

But, when I create the User , I can't pass params[:user] , because params[:user][:group] is not a group, it's a String . This would be a lot easier if I could supply params[:user] and params[:group] to my controller, instead of everything bundled under a single variable, but I don't know how to do that.

Relevant code:

User#create

@group = Group.find_or_create_by_name(params[:user][:group])
@group.save!
@user = @group.users.build(params[:user])

Partial User Schema

create_table "users", :force => true do |t|
  t.string   "name",                :default => "",    :null => false
  t.string   "email",                                  :null => false
  t.integer  "group_id"

Partial Group Schema

create_table "groups", :force => true do |t|
  t.string   "name"
  t.text     "description"
  t.datetime "created_at"
  t.datetime "updated_at"

Params Dump from form submission

{"commit"=>"Register",
 "authenticity_token"=>"x1KgPdpJop5H2NldsPtk0+mBDtrmpM/oNABOxjpabIU=",
  "utf8"=>"✓",
  "user"=>{"name"=>"aName",
  "group"=>"aGroupName",
  "password_confirmation"=>"[FILTERED]",
  "password"=>"[FILTERED]",
  "email"=>"anEmail"}}

The best explanation I've run across is this question.

I don't really want to start rearranging the params has inside of my controller as that really makes me queasy, and seems like terrible programming. Which really makes me question whether I've got a bigger problem.

If it goes against Rails conventions to do this, what then is the best way to do it, and why should I not?

I don't think the proper way to do this here is to build the user off the group. That'd be appropriate if you were in an action of the GroupsController that, for example, added new users to a group. I think the best approach here would be to do the following:

@group = Group.find_or_create_by_name(params[:user][:group])
@group.save!
@user = User.new(params[:user])
@user.group_id = @group.id
@user.save

Since you're in the new action of the UsersController , it seems more fitting to be creating a new user instead of building it off an association and then adding that user to the group that either already existed or was just created.

Does that make sense?

So, I'm going to spell out everything I've learned, in case other people are having trouble understanding this like I did. Also, if I get anything wrong here, please correct me.

If you're using a form that creates multiple model instances at once (preferably associated ones), you first need to use the helper accepts_nested_attributes_for in your model definition (probably right underneath your declared associations). The reason for this is it creates a setter method that knows how to write that type of associated model. (Note: you can also define this method yourself in your main model). Once you've done that you can nest a fields_for inside of a form_for , and Rails will know how to make the proper assignments.

I initially thought that accepts_nested_attributes_for was referring to nested resources, which is definitely not the case. If you're looking for more information, refer to section 11.8.3 (pp 343-347) of The Rails 3 Way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM