开发者

Rails 3 Data Modeling Help - Has Many, Belongs to, Nested Atrributes

I am working on a project involving three models (recipient, award, announcer) and need to have a nested attributes when issuing an award by an announcer to multiple recipients. For an example, award form need to have the ability to do 3 things:

  1. Can add multiple-recipients (i.e. "add 开发者_运维问答recipient", "remove recipient") - nested attributes
  2. After creating a new award, the award will be posted into recipient's profile.
  3. Enables future polling of @recipient.awards and @announcer.awards

Really struggle in terms of how to smartly solve this problem. The following data structure kind of made sense, however can not do "accepts_nested_attributes_for :recipients" in the award form. Can you help? Many thanks in advance.

class Recipient < ActiveRecord::Base

  • has_many :awards
  • has_many :announcers, :through => :awards

end

class Announcer < ActiveRecord::Base

  • has_many :awards
  • has_many :recipients, :through => :awards

end

class Award < ActiveRecord::Base

  • belongs_to :announcer
  • belongs_to :recipient

end


You're just about there. The main issue is that you're trying to create recipient objects in the form rather than just creating a relationship between the award and another object (user). You could do something like this:

class User < ActiveRecord::Base
  has_many :recipients
  has_many :awards, :through => :recipients
end

# this is your relationship between an award and a user
class Recipient < ActiveRecord::Base
  belongs_to :user
  belongs_to :award
end

class Award < ActiveRecord::Base
  has_many :recipients
  has_many :users, :through => :recipients
  belongs_to :announcer

  accepts_nested_attributes_for :recipients, :allow_destroy => true
end

class Announcer < ActiveRecord::Base
  has_many :awards
  has_many :recipients, :through => :awards
end

Then you would just do a nested form that would build the recipients_attributes array:

<%= form_for @award do |f| %>

  <%= f.text_field :name %>

  <div id="recipients">
    <% @award.recipients.each do |recipient| %>

     <%= render :partial => '/recipients/new', :locals => {:recipient => recipient, :f => f} %>

    <% end %>
  </div>
  <%= link_to_function 'add recipient', "jQuery('#recipients').append(#{render(:partial => '/recipients/new').to_json})" %>

<% end %>

And, to keep it DRY just push the nested part into a partial:

# app/views/recipients/_new.html.erb
<% recipient ||= Recipient.new %>
<%= f.fields_for 'recipients_attributes[]', recipient do |rf| %>
  <%= rf.select :user_id, User.all %>
  <%= fr.check_box '_delete' %>
  <%= fr.label '_delete', 'remove' %>
<% end %>

Obviously the User.all call isn't ideal so maybe make that an autocomplete.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜