В Rails, как мне проверить поле validates_uniqueness_of: с областью действия последних 6 месяцев - PullRequest
4 голосов
/ 09 июня 2009

Первый товар
Я хочу проверить поле, чтобы убедиться, что оно уникально (за последние 6 месяцев), прежде чем сохранять его в базе данных.

Я думаю, что я должен использовать validates_uniqueness_of: field, case_sensitive => false, Scope => ...

Для моего приложения оно должно быть уникальным, только если оно использовалось <6 месяцев назад. </p>

Подумал, чтобы сравнить его с созданным_, но на самом деле не знаю, как это сделать.

Второй предмет
Я думаю, что я должен каким-то образом использовать .strip, чтобы удалить любые пробелы до или после текста, который использование могло вставить случайно (я знаю, что эти дополнительные пробелы используются по умолчанию в рельсах, и если они есть, это может сделать поле уникальным).

Если у кого-нибудь есть какие-либо подсказки о том, как это должно быть сделано правильно, я был бы очень признателен.

Ответы [ 2 ]

10 голосов
/ 09 июня 2009

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 - это значение этого атрибута.

3 голосов
/ 09 июня 2009

Вы, вероятно, можете сделать что-то вроде этого:

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, если вы часто будете этим заниматься.

Чтобы избавиться от начальных и конечных пробелов, вам нужен метод 'strip'. Вы можете запустить это на всех ваших полях, выполнив что-то вроде:

before_validation :clean_up_whitespace

def clean_up_whitespace
    self.some_field.strip!    # this does the strip in place
end

Надеюсь, это поможет, дайте мне знать, если я допустил какие-либо ошибки!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...