假设我有一个ActiveRecord关联,比如:
class City < ActiveRecord::Base
belongs_to :state
end
一个没有州的城市应该是无效的。似乎这两种都是可能的验证:
validates :state, presence: true
# OR
validates :state_id, presence: true
我猜它们是相同的,因为:
belongs_to
创建方法state
和state=
state=
设置state_id
然而,我刚刚修复了一个失败的规范,将其更改为检查id而不是对象。
这两种验证方式都可以接受吗?如果是,你什么时候会使用其中一个?
validates :state
将使用从城市到州的关系(belongs_to)以及外键,而validates :state_id
单独使用列state_id并查看它是否有任何值。
我的首选方法是验证state
(关系),因为这需要同时存在密钥和关系。
验证state_id将起作用,因为它将确保状态id存在,但不会检查代码的有效性,即对于City中的任何给定状态密钥,状态实际上"存在"。
基本上,如果City中使用的外键(用于state_id)都作为state中的实际记录存在,则效果相同。如果状态中有一个无效的状态代码,则会显示差异。
如果你做了类似的事情会怎么样
s = State.new
c = City.new
c.state = s
c.valid?
我还没有尝试过,但我猜,如果你检查c.state_id的存在,它会丢失,即使c确实有状态(因为id还没有生成,因为状态还没有保存)。
也就是说,如果你关心的是国家的存在,你应该验证国家的存在。
就我个人而言,我更喜欢让模型更健壮,并接受非此即彼。因此,在您的特定情况下,City可以接受State
对象或state_id
对象,但需要发送其中一个。
class City < ActiveRecord::Base
attr_accessible :state, :state_id
validates :state, presence: true, if: proc{|c| c.state_id.blank? }
validates :state_id, presence: true, if: proc{|c| c.state.blank? }
belongs_to :state
end
编辑:删除validate语句中的双负数。最初有unless: proc{|c| !c.state_id.blank? }
根据Obie Fernandez的Rails 4 Way:
当您试图确保关联存在时,通过外键属性,而不是关联变量本身
validates :region_id, :presence => true
validate :region_exists
def region_exists
errors.add(:region_id, "does not exist") unless Region.exists?(region_id)
end
这本书没有解释为什么你应该使用这个而不是
validates :region, :presence => true
但我知道这些家伙知道他们的东西。