第一项
我希望在将字段保存到数据库之前验证字段以确保它是唯一的(在过去6个月内)。
我在想我应该使用validates_uniqueness_of:field,case_sensitive => false,Scope => ...
对于我的应用程序,它只需要是唯一的,如果它在6个月前使用过。
想把它与created_at进行比较,但实际上并不知道怎么做。
第二项
我想我应该以某种方式使用.strip来删除在使用可能意外放入的文本之前或之后的任何空格(我知道这些额外的空格默认在rails中使用,如果它们在那里可以使字段唯一。)
如果有人对如何正确完成这一点有任何暗示,我真的很感激。
答案 0 :(得分:10)
validates_uniqueness_of
通过检查记录是否已存在,并且给定范围内的给定字段的值相同。 :scope
允许您定义唯一性的范围(显然);例如,如果我正在创建博客软件,并希望每个博客只允许使用一次帖子标题,我可以说validates_uniqueness_of :title, :scope => :blog_id
- 没有范围,我只允许每个标题使用一次整个系统。 :scope
不会让你做一个复杂的检查,就像你想要的那样。
您可能需要做的是创建自己的验证函数,以在给定的时间范围内检查相关字段的唯一性(代码在模型中):
validate :field_must_be_unique_within_six_months
def field_must_be_unique_within_six_months
return if field.blank?
num_duplicates = self.class.count(:conditions => ["field = ? AND created_at < ?", self.field, 6.months.ago])
if num_duplicates > 0
errors.add(:field, :taken)
end
end
field_must_be_unique_within_six_months
方法与validates_uniqueness_of
的工作方式类似,因为如果已存在具有相同给定字段的记录,则会添加错误消息,但添加的条件是它还会检查日期。保存记录时,validate :field_must_be_unique_within_six_months
会将方法添加到验证过程中。
要在不违反DRY的情况下同时验证多个字段,您可以使用validates_each执行以下操作:
validates_each :field1, :field2 do |record, attr, value|
if record.class.exists?(["#{attr.to_s} = ? AND created_at < ?", value, 6.months.ago])
errors.add(attr, :taken)
end
end
在上面的区块中,record
是要验证的记录,attr
是属性(因此field1
,field2
等)和value
是该属性的值。
答案 1 :(得分:3)
你可以这样做:
def validate
errors.add(:field, 'blah blah') if is_used_recently && !has_unique_field?
end
def has_unique_field?
Model.exists?(['field = ? and created_at > ?', self.field, 6.months.ago])
end
def is_used_recently
self.created_at < 6.months.ago || self.new? # i don't know if created_at would be set by this point
end
或者你可能想要创建一个新的验证处理程序,或者扩展现有的验证处理程序以传入:within选项,如果那是你经常要做的事情。
要摆脱前导和尾随空格,您想要的方法是“剥离”。您可以通过执行以下操作在所有字段上运行此操作:
before_validation :clean_up_whitespace
def clean_up_whitespace
self.some_field.strip! # this does the strip in place
end
我希望这会有所帮助,如果我犯了任何错误,请告诉我!