对更新中的accepts_nested_attributes_for和habtm关联进行rails验证会重置关联

时间:2010-08-29 17:31:03

标签: ruby-on-rails validation has-and-belongs-to-many update-attributes

在rails 2.3.8中,如果我在验证中循环甚至检查habtm关联,加载课程并且任何更新都丢失,我在accept_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>

基本上是这样的:
最后一课以29的activity_id开头 在lesson_set上调用update_attributes以尝试将activity_id设置为3
它返回true,但是当我们查看最后一课时它没有改变 然后将活动ID设置为29即。相同并调用update_attributes
activity_id仍然是29
但然后再次打电话尝试将其设置为3
这次它更新了课程。???

我的代码是否有问题这对我来说似乎很奇怪,我无法在网上找到类似的东西。

我认为我正准备迎接一记耳光!

1 个答案:

答案 0 :(得分:1)

上面的模型
课程has_and_belongs_to_many Lesson_sets
参加者属于Lesson_set

尝试进行验证,不应该是更多的与会者而不是限制意味着在保存新关联之前验证期间正在重置课程和lesson_sets之间的关联。

将验证逻辑从lesson_set移动到参加者,使验证工作正常。

因此,如果你有类似的东西,请尝试将验证逻辑从连接模型移动到它加入的模型之一