开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜