开发者

Nested Model Forms -- How do you create an object through an association if it doesn't already exist?

From Ryan Bates's episode about nested model forms, I was able to create a project with concerts, bands and performances that they play. I can add performances to a new concert or when I edit a concert. That's fairly simple and straightforward when I follow his tutorial.

performances belongs to bands and performances belongs to concerts. A performance will list the band playing and the time starting/ending. Bands only have a string column for its name.

When I create a new concert and add a whole slew of performances, I'd like to, at the same time, be able to create the band objects if they don't already exist. Otherwise, the user has the added step(s) of creating those objects, which would be tedious.

How, through accepts_nested_attributes_for or some other useful Rails feature, can I do this? I am using Rails 2.3.8

Here are my associations:

class Band < ActiveRecord::Base
  has_many :performances
  has_many :concerts, :through => :performances
end

class Concert < ActiveRecord::Base
  has_many :performances
  has_many :bands, :through => :performances
  accepts_nested_attributes_for :performances, :reject_if => lambda { |a| a[:content].blank? }, :allow_dest开发者_如何学JAVAroy => true
end

class Performance < ActiveRecord::Base
  belongs_to :band
  belongs_to :concert
end


Rails can handle this for you, you just need to make sure you pass in the params the right way (which multiple nested forms should do for you)

class Concert < ActiveRecord::Base
  has_many :performances
  has_many :bands, :through => :performances

  accepts_nested_attributes_for :performances
end


class Performance < ActiveRecord::Base
  belongs_to :concert
  has_many :bands

  accepts_nested_attributes_for :bands
end


class Band < ActiveRecord::Base
  belongs_to :performance
end

Your params hash should look like this:

{
  :concert => {
    :performances_attributes => [
      {
        :bands_attributes => [
          {
            :name => "test u"
          }],
        :name=>"test p"
      }], 
    :name=>"test"
  }
}


You build new blank instances of the association that you want to create. In the case of a belongs_to, the method to build the association instance is "build_#{association_name}" so if you wanted to create a new band via a performance that accepts_nested_attributes_for :band you would initialize a blank band in your controller method:

class PerformancesController < ApplicationController
  def new
    @performance = Performance.new       # You're building 
                                         # the performance to create
    @performance.build_band              # You're building
                                         # the band to create
  end
end

The build method for has_many associations is "#{association_name}.build, so for a band that accepts_nested_attributes_for :performances:

class BandsController < ApplicationController
  def new
    @band = Band.new
    3.times { @band.performances.build }
  end
end


You have to use the build method noted above for the fields to show up in your form. Following is how you'd set up your form.

<%= form_for @concert do |cf| %>  
  <%= cf.label :name %>  
  <%= cf.text_field :name %>  
  <%= cf.fields_for :performances do |pf| do %>  
     <%= pf.label :some_attr %>  
     ...  
     <%= pf.fields_for :bands do |bf| %>  
          <%= bf.label ... %>  
     <%end>  
  <% end %>  
<% end %>  
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜