Rails: manipulating a join table in a nested form

I have two models connected by a connection table:

class Publication < ActiveRecord::Base attr_accessible :title, :author_attributes, :translator_attributes has_many :publication_contributors has_many :authors, :through => :publication_contributors, :source => :contributor, :conditions => {:publication_contributors => {:contributor_type => "Author"}} has_many :translators, :through => :publication_contributors, :source => :contributor, :conditions => {:publication_contributors => {:contributor_type => "Translator"}} accepts_nested_attributes_for :authors, :translators end class Contributor < ActiveRecord::Base attr_accessible :name has_many :publications, :through => :publication_contributors has_many :publication_contributors end class PublicationContributor < ActiveRecord::Base attr_accessible :contributor_type belongs_to :publication belongs_to :contributor end 

Note that the join table has a third attribute (besides publ_id and contributor_id), which is called contributor_type. This attribute may contain a role such as Author, Translator, Editor, or something else. In my publishing model, I created a couple of associations for the two most common contributor_types types: Author and Translator. These associations work well when retrieving relevant data, for example using @publication.authors . However, when creating these associations through a nested form, it is sprayed.

My form looks something like this:

 <%= form_for @publication, :remote => true do |f| %> <%= f.label :title %>: <%= f.text_field :title %> <%= f.fields_for :authors do |builder| %> <%= builder.label :name, "Author" %>: <%= builder.text_field :name %> <% end %> <%= f.fields_for :translators do |builder| %> <%= builder.label :name, "Translator" %>: <%= builder.text_field :name %> <% end %> <%= f.submit %> <% end %> 

In my controller:

 def create publication = Publication.create(params[:publication]) end 

The form displays as expected, but it is sprayed during the create action. I was hoping Rails would know how to magically assign the correct contributor_type based on conditions in publication associations, such as:

 has_many :authors, :through => :publication_contributors, :source => :contributor, :conditions => {:publication_contributors => {:contributor_type => "Author"}} 

Unfortunately, this is not the case. I get this error at creation time:

 Mysql2::Error: Column 'contributor_type' cannot be null 

This makes me think that my only regression is to manually assign contributor_type in the before_create , but if so, how do I determine which type to assign? Parameters have the correct type in the name, for example:

 publication[authors_attributes][0][name] 

Is there a way to access this information at the model level?

UPDATE:

My new action:

 def new @publication = Publication.new publication_contributor = @publication.publication_contributors.build contributor = publication_contributor.contributor.build end 

It throws this error in the last line (one contributor setting):

 undefined method `build' for nil:NilClass 
+4
source share
1 answer

Can you try the following?

 class Publication < ActiveRecord::Base attr_accessible :title, :publication_contributors_attributes has_many :publication_contributors has_many :authors, through: :publication_contributors, source: :contributor, conditions: { publication_contributors: { contributor_type: 'Author' } } has_many :translators, through: :publication_contributors, source: :contributor, conditions: { publication_contributors: { contributor_type: 'Translator' } } accepts_nested_attributes_for :publication_contributors end class Contributor < ActiveRecord::Base attr_accessible :name has_many :publications, through: :publication_contributors has_many :publication_contributors end class PublicationContributor < ActiveRecord::Base attr_accessible :contributor_type belongs_to :publication belongs_to :contributor accepts_nested_attributes_for :contributor end <%= form_for @publication, :remote => true do |f| %> <%= f.label :title %>: <%= f.text_field :title %> <%= f.fields_for :publication_contributors do |pc_form| %> <%= pc_form.hidden_field :contributor_type %> <%= pc_form.fields_for :contributor do |c_form| %> <%= c_form.label :name, "Author" %>: <%= c_form.text_field :name %> <% end %> <% end %> <%= f.submit %> <% end %> 

UPDATE: controller code

 @publication.publication_contributors.build @publication.publication_contributors.each do |pc| pc.build_contributor end 
+6
source

All Articles