Rails 在更新中对 Accepts_nested_attributes_for 和 habtm 关联进行验证会重置关联
在 Rails 2.3.8 中,如果我在验证中循环或什至检查 habtm 关联,则我在对 Accepts_nested_attributes_for 关联进行验证时遇到问题,课程将被加载,并且任何更新都会丢失。例如,我有以下架构:
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
和以下模型:
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
如果我调用以下内容:
>> 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>
这基本上是:
最后一课以 Activity_id 29 开始
在 Lesson_set 上调用 update_attributes 来尝试将 Activity_id 设置为 3
它返回 true,但是当我们看上一课时它并没有改变
然后将活动ID设置为29,即。相同并调用 update_attributes
Activity_id 仍然是 29
但随后再次致电尝试将其设置为 3
这次更新了课程。???
我的代码有问题吗,这对我来说似乎很奇怪,而且我在网上找不到任何类似的东西。
我想我即将迎来被打头的时刻了!
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 returns 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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
与以上型号
课程 has_and_belongs_to_many Lesson_sets
参加者属于Lesson_set
尝试验证参加者人数不应超过限制,这意味着在保存新关联之前,课程和Lesson_sets之间的关联在验证过程中被重置。
将验证逻辑从lesson_set移动到Attendee使验证能够工作。
因此,如果您遇到类似的情况,请尝试将验证逻辑从加入模型移动到它加入的模型之一
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