rails validation on accepts_nested_attributes_for and habtm association in an update resets the association
In rails 2.3.8 I am having trouble with validations on a accepts_nested_attributes_for association if I loop through or even inspect the habtm association in validation the lessons are loaded and any updates are lost. For example, I have the following schema:
ActiveRecord::Schema.define(:version => 20100829151836) do
create_table "attendees", :force => true do |t|
t.integer "lesson_set_id"
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "lesson_sets", :force => true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "lesson_sets_lessons", :id => false, :force => true do |t|
t.integer "lesson_id"
t.integer "lesson_set_id"
end
create_table "lessons", :force => true do |t|
t.integer "activity_id"
t.integer "limit"
t.datetime "created_at"
t.datetime "updated_at"
end
end
and the following models:
class Attendee < ActiveRecord::Base
belongs_to :lesson_sets
end
class Lesson < ActiveRecord::Base
has_and_belongs_to_many :lesson_sets
end
class LessonSet < ActiveRecord::Base
has_and_belongs_to_many :lessons
has_many :attendees
accepts_nested_attributes_for :lessons
validate do |lesson_set|
lesson_set.lessons.each do |l|
if l.limit < attendees.count
self.errors.add_to_base("Sorry only #{l.limit} people allowed on lesson")
end
end
end
end
If I call the following:
>> ls = LessonSet.first
=> #<LessonSet id: 1, created_at: "2010-08-29 07:50:23", updated_
at: "2010-08-29 07:50:23">
>> Lesson.last
=> #<Lesson id: 1, activity_id: 29, created_at: "2010-08-29 07:57:13", updated_a
t: "2010-08-29 17:04:34", limit: 5>
params = {"lessons_attributes"=>{"0"=>{"activity_id"=>"3", "id"=>"1", "_destroy"=>""}}, "id"=>"1"}
=> {"id"=>"1", "lessons_attributes"=>{"0"=>{"activity_id"=>"3", "id"=>"1", "_des
troy"=>""}}}
>> ls.update_attributes(params)
=> true
>> Lesson.last
=> #<Lesson id: 1, activity_id: 29, created_at: "2010-08-29 07:57:13", updated_a
t: "2010-08-29 17:04:34", limit: 5>
>> params = {"lessons_attributes"=>{"0"=>{"activity_id"=>"29", "id"=>"1", "_de>
=> {"id"=>"1", "lessons_attributes"=>{"0"=>{"activity_id"=>"29", "id"=>"1", "_de
stroy"=>""}}}
>> ls.update_attributes(params)
=> true
<y_id"=>"3", "id"=>"1", "_destroy"=>""}}, "id"=>"1"}
=> {"id"=>"1", "lessons_attributes"=>{"0"=>{"activity_id"=>"3", "id"=>"1", "_des
troy"=>""}}}
>> Lesson.last
=> #<Lesson id: 1, activity_id: 29, created_at: "2010-08-29 07:57:13", updated_a
t: "2010-08-29 17:04:34", limit: 5>
>> ls.update_attributes(params)
=> true
>> Lesson.last
=> #<Lesson id: 1, activity_id: 3, created_at: "2010-08-29 07:57:13", updated_at
: "2010-08-29 17:13:36", limit: 5>
Which is basically:
the last lesson starts with an activity_id of 29 call update_attributes on the lesson_set to try and set the activity_id to 3 it re开发者_开发知识库turns true but when we look at the last lesson it has not changed then set the activity id to be 29 ie. the same and call update_attributes activity_id is still 29 but then call again to try and set it to 3 and this time it updates the lesson.???Is there something wrong with my code this seems really odd behaviour to me and I cant find anything on the net similar.
think I am heading for a head slap moment!
With the models above
Lesson has_and_belongs_to_many Lesson_sets
Attendee belongs_to Lesson_set
trying to put the validation that the should not be more attendees than the limit meant that the association between the lessons and the lesson_sets was being reset during the validation before the new association was saved.
Moving the validation logic from the lesson_set to the Attendee enabled the validation to work.
So if you are having something similar try moving your validation logic from the joining model to one of the models that it joins
精彩评论