6

即使 some_field 属性没有更改(如果其他字段已更改), validates_uniqueness_of :some_field 似乎也会在“保存”时运行。这似乎很浪费,因为每个 validates_uniqueness_of 都需要一个数据库调用。我知道我可以将 Proc 传递给 validates_uniqueness_of 以检查 some_field 是否已更改,并且我正在考虑通过所有验证并尽可能地执行此操作。我想知道的是:

1) 这就是对性能感兴趣的人通常对他们的验证所做的事情吗?

2)为什么不是validates_uniqueness_of的默认行为先检查属性是否发生变化?

3) 是否有充分的理由对未更改的属性进行此类验证?

我正在使用 Rails 2.3(目前——我们正在努力升级)。我不知道这与 Rails 3 中的情况相同。

4

2 回答 2

4

如果有人直接更改数据库中的值怎么办?

如果其他一些(非 Rails 应用程序)应用程序也访问数据库怎么办?

在上述所有场景中,您仍然希望您的数据有效,以便您的 Rails 应用程序按预期运行。如果数据被篡改(被其他应用程序或直接在数据库中),您的 rails 应用程序会抛出错误,因为它不期望该数据。

话虽如此,这是默认行为。默认行为通常更具限制性,以保持数据有效性并最大限度地减少错误、遗漏和偶然失误的范围。如果您担心您的情况下的性能,也许您的对象更新非常频繁,并且您对一个不经常更新的字段进行了冗长的自定义验证,并且您不想每个都运行该验证时间,那么按照您在问题中描述的那样自定义默认行为是非常有意义的。

于 2012-05-01T21:01:49.477 回答
0

我刚刚在 Rails 3.0 应用程序中遇到了同样的问题。我通过检查用户是否编辑了唯一属性来解决它。这是我的用户对象的相关代码摘录。

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
于 2013-06-04T23:19:18.133 回答