1

如何使用自定义或虚拟范围验证属性的唯一性?我想过使用虚拟属性,但它一直试图在数据库中查询 audit_year。我不想仅仅为了这个唯一性约束而创建另一个数据库列。

每个位置每年只能安排一次审核,因此我需要从预定属性中提取年份并验证该范围内的唯一性。

class Audit
    attr_accessible :location_name, :scheduled_date, :completion_date ...

    validates :location_name, :presence => true, :uniqueness => { :scope => :audit_year }

    ...

    def audit_year
        scheduled_date.year
    end

end

我的虚拟属性尝试甚至可能不在正确的路径上。在 Rails 中执行此操作的“正确”方法是什么?

4

1 回答 1

0

我知道这有点晚了,但我想我会参与进来。我是凭记忆做的,所以你可能需要稍微搞砸。

我的第一个想法是在您的 audit_year 方法中,您可以查询所有年份的数据库。就像是:

def audit_year
  !self.class.select('selected_date').map{ |a| a.selected_date.year }.include?(selected_date.year)
  # or using Rails 3.2 and Ruby 1.9.3:
  # !self.class.pluck('created_at').map(&:year).include?(selected_date.year)
end

我对唯一方法的假设是,如果它返回 false,它将无法通过验证。此代码仅从您的类中选择一列(我使用 self.class 而不是 Audit,因此它更可重用),然后将年份映射到一个数组。如果包含 (true),则返回相反的 (!)。您可能可以使用 uniq 优化查询,但这取决于表的大小是否有必要。

另一种选择是为属性滚动您自己的验证器,这真的不会那么困难。selected_date.present?唯一的区别是除了上述内容之外,您还需要添加一条有条件检查的行。如果你不知道怎么做,一个很好的资源是用于回调和错误的 Rails 指南:http: //guides.rubyonrails.org/active_record_validations_callbacks.html

希望有帮助。

于 2012-05-15T21:58:27.663 回答