Ответ 1
Просто исправлено (как и многие проблемы с Rails), как указал Дэнни выше, хотя и не в своем собственном ответе, поэтому я не могу его принять:), изменение before_save
до before_validation
прекрасно исправляет его.
Аэропорты имеют четырехбуквенные коды ИКАО. По соглашению, они всегда имеют верхний регистр. Я создаю форму для ввода пользовательского ввода, но эта форма должна быть способна принимать пользовательский ввод в смешанном случае и препятствовать им создавать обманки.
По умолчанию :uniqueness
зависит от регистра, конечно. Я понял, как преобразовать пользовательский ввод в верхний регистр, прежде чем он будет сохранен, но проблема в том, что это скорее пост-валидация, а не предварительная проверка.
Например, если уже есть аэропорт с ИКАО KLAX
, пользователь может ввести KLAX
, он будет проверен как уникальный, а затем преобразован в верхний регистр и сохранен, что приведет к дублированию.
Вот мой код модели в настоящее время.
class Airport < ActiveRecord::Base
validates :icao, :name, :lat, :lon, :presence => true
validates :icao, :uniqueness => true
before_save :uppercase_icao
def uppercase_icao
icao.upcase!
end
end
Просто исправлено (как и многие проблемы с Rails), как указал Дэнни выше, хотя и не в своем собственном ответе, поэтому я не могу его принять:), изменение before_save
до before_validation
прекрасно исправляет его.
Или немного другое: запишите setter для icao
, который преобразует все, что было в него, в верхний регистр:
def icao=(val)
self[:icao] = val.upcase
end
И тогда вы можете использовать регулярную проверку уникальности (создать резервную копию с уникальным индексом в вашей базе данных). Может даже немного облегчить работу БД во время находок, потому что больше не нужно беспокоиться о безразличных сравнениях.
Надеюсь, это поможет!
попробуйте следующее:
validates :icao, :uniqueness => { :case_sensitive => false }
Обновлен ответ для Rails 4.
class Airport < ActiveRecord::Base
validates :icao, :name, :lat, :lon, :presence => true
validates :icao, :uniqueness => { case_sensitive: false }
def icao=(val)
write_attribute :icao, val.upcase
end
end