Rails 3 has_many: via write save error

I’m not quite sure what my problem is, therefore this question may require a more detailed explanation, but here is what seems most relevant:

I have has_many :through , and in the join model there are several fields that are not foreign keys. When I create models and try to save, I get a validation error for non-external key fields from the join model.

My files look like this:

 Person.rb has_many :wedding_assignments, :dependent => :destroy has_many :weddings, :through=>:wedding_assignments accepts_nested_attributes_for :weddings accepts_nested_attributes_for :wedding_assignments Wedding.rb has_many :wedding_assignments, :dependent => :destroy has_many :people, :through=>:wedding_assignments accepts_nested_attributes_for :people accepts_nested_attributes_for :wedding_assignments WeddingAssignment.rb belongs_to :person belongs_to :wedding validates_presence_of :role, :person, :wedding 

(role is string)

 people_controller.rb def new @person = Person.new 1.times do wedding = @person.weddings.build 1.times do assignment = wedding.wedding_assignments.build assignment.person = @person assignment.wedding = wedding end end end def create @person = Person.new(params[:person]) @person.weddings.each do |wedding| wedding.wedding_assignments.each do |assignment| assignment.person = @person #i don't think I should need to set person and wedding manually, but I get a validation error if I don't assignment.wedding = wedding end end end 

the returned parameters are as follows:

 {"first_name"=>"", "last_name"=>"", "weddings_attributes"=>{"0"=>{"wedding_assignments_attributes"=>{"0"=>{"role"=>"Bride Maid", "budget"=>""}}, "date"=>"", "ceremony_notes"=>""}}} 

And the exact error:

 ActiveRecord::RecordInvalid in PeopleController#create Validation failed: Role can't be blank 

This is clearly wrong, as you can see it in params[]

What am I doing wrong?

This is rails 3.0.0

+6
ruby-on-rails ruby-on-rails-3 has-many-through
source share
2 answers

That's right, this is a little hunch, so I apologize if I am mistaken in spending your time here ...

It seems to me that in your creation method you create a "wedding" relationship (this is only a "pretending" relationship, it uses: via =>: wedding_assignments), and then returns it. Then you ask the rails to recreate these objects when calling Person.new. I assume that the rails get confused trying to create an object on the opposite side of has_many: without an intermediate object.

I will be tempted to change the structure a bit (unverified code!):

 def new @person = Person.new @wedding = Wedding.new @wedding_assignment = WeddingAssignment.new end def create @person = Person.new(params[:person]) @wedding = Wedding.new(params[:person]) @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) end 

I have a feeling that this will work to the last line. I suspect you will need to use transactions to do this:

 def create @person = Person.new(params[:person]) @wedding = Wedding.new(params[:person]) ActiveRecord::Base.transaction do if @person.valid? && @wedding.valid? [@person,@wedding].each.save! @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) @assignment.save! end end end 

This should ensure that everything is created in the correct order, and the identifiers are available at the right time, etc. Unfortunately, this is a little more complicated than your example, and this means that you will struggle to support several weddings.

Hope this helps, and does not end the dead end.

+1
source share

Try changing "Person.new" to "Person.create", maybe creating an entry in db will help with associations right away.

0
source share

All Articles