Associating (has_one) multiple models in form
I'm unable to associate the foreign key before saving the data (the field 'user_id' for the Network model is blank when stored in the database). I'm new to RoR so please excuse me if my code is sloppy :-)
Models:
class Network < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :network, :foreign_key => "user_id",
:dependent => :destroy
Controller:
class UsersController < ApplicationController
def new
@user = User.new
@network = @user.build_network
@title = "Sign Up"
end
def create
@user = User.new(params[:user])
if (@user.save)
@network = Network.new(params[:network])
if (@network.save)
sign_in @user
flash[:success] = "Welcome!"
redirect_to @user
else
@title = "Sign up"
render 'new'
end
else
@title = "Sign up"
render 'new'
end
end
I'm able to get all of the user input from the view without issues (using form_for and fields_for). Do I have to explicitly define the has_one association in addition to using @user.build_network ?
Per the suggestion of using accepts_nested_attributes_for
, I cleaned up my controller to be
def new
@user = User.new
@user.build_network
@title = "Sign Up"
end
def create
@user = User.new(params[:user])
if (@user.save)
sign_in @user
flash[:success] 开发者_如何学Python= "Welcome!"
redirect_to @user
else
@title = "Sign up"
render 'new'
end
end
The updated association in the User Model:
has_one :network, :class_name => 'Network',
:foreign_key => "user_id",
:dependent => :destroy
accepts_nested_attributes_for :network,
:reject_if => :all_blank,
:allow_destroy => true
However, the network_attributes are all blank when I submit the form. I have followed the directions in the links provided as well as http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes (and many more)
I don't think it's an issue with the view/form since I'm able to access the attributes using Network.new(params[:network]
Any thoughts/suggestions ?
This is a perfect situation for using accepts_nested_attributes_for
Have a look at http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html as well as http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for to see how you can easily implement it using form_for
(post-question update)
If you can access the attributes for Network
through params[:network]
, then you have (unfortunately!) missed one of the more subtle parts of nested attributes, which is the invocation of fields_for
I'm assuming you have something along the lines of the following (using HAML syntax for speed):
= form_for @user do |f|
= f.text_field :name
= f.text_field :email_address
- fields_for @network do |n|
= n.text_field :name
The problem with this is that Rails isn't seeing any explicit connection in the form between your User
and Network
fields. (It's smart, but not that smart)
The way you explicitly state that Network
is nested within User
(for the sake of updating nested attributes is to make sure you call the fields_for @network
function on the User
form builder, not by itself:
= form_for @user do |f|
= f.text_field :name
= f.text_field :email_address
- f.fields_for @network do |n|
= n.text_field :name
That way, when you submit your form and inspect params
, you'll notice that you've got both params[:user]
and params[:user][:network]
- which Rails will recognise as nested attributtes and should then save them and link them together.
It's possible you need to set network as attr_accessible, along with other attributes of User model, like this:
attr_accessible :name, :age, :network_attributes, ...
Please note you'll also need to put all attributes you want to 'mass assign' in the list, just like :name and :age in the above example.
精彩评论