为什么我的模型在错误的时间触发验证?

时间:2010-05-09 04:37:50

标签: ruby-on-rails validation associations polymorphic-associations rails-models

在我edit的{​​{1}}行动中,我有这行代码:

employees_controller

如果没有,则应添加空白#Employee#edit 69: if @employee.user.person.addresses.length == 0 70: @employee.user.person.addresses << Address.new 71: end ,以便它显示在我的编辑erb文件中。这样,如果没有与该员工关联的地址,则他们在编辑此记录时被迫添加一个。

这样的多态关联:AddressPerson <- User <- EmployeePerson有多对多的关系。该声明如下:

Address

代码在#class Person has_many :address_person_links, :dependent => :destroy has_many :addresses, :through => :address_person_links, :uniq => true, :validate => false, # I thought this would fix it but doesn't :dependent => :destroy 的第70行失败:

employees_controller.rb

请注意其调用/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/validations.rb:1090:in `save_without_dirty!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/dirty.rb:87:in `save_without_transactions!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:200:in `save!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:182:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:200:in `save!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:208:in `rollback_active_record_state!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:200:in `save!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/has_many_through_association.rb:63:in `insert_record' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:119:in `<<' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:433:in `add_record_to_target_with_callbacks' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:118:in `<<' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:116:in `each' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:116:in `<<' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:141:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/transactions.rb:182:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:140:in `transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:115:in `<<' /home/aaron/NetBeansProjects/onlinescheduler/app/controllers/employees_controller.rb:70:in `edit' 的方式?为什么要这样做?

2 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为无论何时将AR对象添加到关联数组,它都会保存对象并尝试将其id添加到关联表中(如果它是many_to_many)

您可以尝试以下

#Employee#edit
69: if @employee.user.person.addresses.length == 0
70:   @employee.user.person.addresses = [Address.new]
71: end

此外,如果您使用accepts_nested_attributes_for执行此操作,则惯例是使用build方法

#Employee#edit
69: if @employee.user.person.addresses.length == 0
70:   @employee.user.person.addresses.build
71: end

有关详细信息,请参阅http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

答案 1 :(得分:1)

首先,为了语义清晰,我建议你检查如下:

if @employee.user.person.addresses.empty?

接下来,如果您检查日志,您将看到地址(以及相应的address_person_link)被“&lt;&lt;”添加到数据库中方法,这反过来调用验证,这就是你的保存失败的原因(因为新创建的地址不验证)。

您可以修改地址验证,以避免在新创建的记录中运行它们(例如当您刚将其添加到使用“&lt;&lt;”的人时。就像这样:

validates_presence_of :name, :unless => Proc.new{|a|a.new_record?}

你必须添加:除非阻止你在地址验证上的每一个。