rails 3 has_many :through record save error
I'm not exactly sure what my problem is, so this question may require some more clarification, but here's what seems to be most relevant:
I have a has_many :through
and the join model has some fields that aren't foreign keys. When I build the models up and try to save I get a validation error on the non-foreign key fields from the join model.
My files look like:
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 a 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 wedd开发者_如何学Cing manually, but I get a validation error if I don't
assignment.wedding = wedding
end
end
end
the params that come back look like:
{"first_name"=>"", "last_name"=>"", "weddings_attributes"=>{"0"=>{"wedding_assignments_attributes"=>{"0"=>{"role"=>"Bride's Maid", "budget"=>""}}, "date"=>"", "ceremony_notes"=>""}}}
And the exact error is:
ActiveRecord::RecordInvalid in PeopleController#create
Validation failed: Role can't be blank
Which is clearly not correct, since you can see it in params[]
What am I doing wrong?
This is rails 3.0.0
Right, this is a bit of a guess, so apologies if I wind up wasting your time here...
It looks to me like in your create method, you're creating the 'wedding' relationship (which is only a 'pretend' relationship really, has it's using :through => :wedding_assignments), and then returning this. You're then asking rails to re-create these objects in your call to Person.new. My guess is that rails is getting confused by trying to create an object at the far side of a has_many :through without the intermediate object being present.
I would be tempted to restructure this a little (untested 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've got a feeling this'll work until the last line. I suspect to get that to work you might need to use transactions:
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 ought to ensure that everything is created in the right order and IDs are available at the right times etc. Unfortunately though, it's a bit more complicated than your example, and does mean that you'll struggle to support multiple weddings.
Hope this helps, and doesn't wind up being a blind alley.
Try changing "Person.new" to "Person.create", maybe creating the record in the db right away will help with the associations.
精彩评论