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