似乎validates_uniqueness_of:some_field将在" save"上运行。即使some_field属性没有改变(如果其他字段已经改变)。这似乎很浪费,因为每个validates_uniqueness_of都需要数据库调用。我知道我可以将Proc传递给validates_uniqueness_of以检查some_field是否已更改,并且我正在考虑进行所有验证并尽可能地执行此操作。我想知道的是:
1)那些对表现感兴趣的人通常会对他们的验证做些什么吗?
2)为什么检查属性是否先改变是不是validates_uniqueness_of的默认行为?
3)是否有充分的理由对尚未改变的属性进行此类验证?
我正在使用Rails 2.3(暂时 - 我们正在进行升级)。我不知道这与Rails 3中的情况相同。
答案 0 :(得分:3)
如果有人直接更改了数据库中的值,该怎么办?
如果其他(非rails应用)应用也访问数据库怎么办?
在上述所有场景中,您仍然希望数据有效,以便您的rails应用程序按预期运行。如果数据被篡改(由其他应用程序或直接在数据库中),您的rails应用程序会抛出错误,因为它不期望该数据。
话虽如此,这是默认行为。默认行为通常更具限制性,以便保持数据有效性并最大限度地减少错误,遗漏和偶然滑动的范围。如果你担心你的情况下的性能,可能你的对象正在经常更新,并且你经常在没有更新的字段上进行冗长的自定义验证,并且你不想每次运行验证时间,那么按照你在问题中描述的那样自定义默认行为是完全合理的。
答案 1 :(得分:0)
我刚刚使用Rails 3.0应用程序遇到了同样的问题。我通过检查用户是否编辑了唯一属性来解决它。这是我的User对象的相关代码摘录。
class User < ActiveRecord::Base
attr_accessible :email, :password, :ha1, :ha1b, :sip_username, :domain
validates :sip_username, :presence => true, :uniqueness => true,
:unless => :update_username?,
:exclusion => {:in => %w(9196),
:message => "9196 is reserved, please choose another"}
def update_username?
# check to see if we are updating a sip_username for an existing user
stored_user = User.find_by_sip_username self.sip_username
# the id of the user is the same as me and sip_username hasn't been changed. skip validations.
if (stored_user.present?)
stored_user.id == self.id && stored_user.sip_username == self.sip_username
end
end