如何在虚拟属性范围内验证Rails模型属性唯一性

时间:2012-04-19 16:35:43

标签: ruby-on-rails-3

如何使用自定义或虚拟范围验证属性的唯一性?我想过使用虚拟属性,但它一直试图在数据库中查询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中执行此操作的“正确”方法是什么?

1 个答案:

答案 0 :(得分: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?的行。如果您不知道如何:http://guides.rubyonrails.org/active_record_validations_callbacks.html

,那么Rails指南可以提供回调和错误,这是一个很好的资源。

希望有所帮助。