【问题标题】:How to check if value unique for a certain period如何检查某个时期的值是否唯一
【发布时间】:2014-01-20 20:01:32
【问题描述】:
我有一个带有 phone_id 属性的 Ratings 模型。在创建新的评级对象之前,我想检查 phone_id 在过去一周内是否唯一。
在我的模型中,我想在 before_save 回调中做这样的事情:
self.all(:conditions => {:created_at => (1.week.ago..Date.today)}).include? self.phone_id
【问题讨论】:
标签:
ruby-on-rails
ruby-on-rails-3.2
rails-activerecord
【解决方案1】:
我会用干净的 sql 来做(性能)
select count(phone_id) from ratings where created_at < DATE_SUB(NOW(), INTERVAL 1 MONTH)
【解决方案2】:
您可以使用带有约束的 ActiveRecord 验证。
class Rating < ActiveRecord::Base
validates_uniqueness_of :phone_id, conditions: -> { where(:created_at => (1.week.ago..Date.today)) }
end
【解决方案3】:
您可以在创建时使用验证:
class Rating < ActiveRecord::Base
validate :unique_phone_within_last_week?, on: :create
private
def unique_phone_within_last_week?
self.class.where("created_at > ?", 1.week.ago.to_date)
.where(phone_id: phone_id).empty? ||
errors.add(:phone_id, 'is not unique within last week') && false
end
end
在 Rails 4 中,您可以将 validates_uniqueness_of 与条件 proc 一起使用:
class Rating < ActiveRecord::Base
validates_uniqueness_of :phone_id,
conditions: -> { where('created_at > ?', 1.week.ago.to_date) }
end
阅读有关validates_uniqueness_of 的更多信息。
检查 SQL 将是最佳的:
SELECT COUNT(*) FROM "ratings"
WHERE "ratings"."phone_id" = 2 AND ("created_at" > '2014-01-14');
还要注意
使用区间1.week.ago..Date.today 似乎是个坏主意,
因为今天(检查日)创建的记录超出了范围。
'2014-01-21 09:10:21' BETWEEN '2014-01-14 11:23:30' AND '2014-01-21' 为假