为什么Rails会验证未更改的属性?

时间:2012-05-01 18:04:24

标签: ruby-on-rails validation

似乎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中的情况相同。

2 个答案:

答案 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