Ответ 1
По возможности, проверяйте как на уровне базы данных, так и на уровне модели.
Почему? Для начала активная запись не применяет проверку во всех контекстах. Следующие методы пропускают проверки и сохраняют объект в базе данных независимо от его действительности:
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_counters
Если вы пройдете :validate => false
до save
, он также пропустит проверку. Подробнее см. В разделе Руководство по проведению проверок и обратных вызовов в разделе "Пропуск проверки". (Если это вас беспокоит, существует даже драгоценный камень для отключения этих методов.)
Итак, причина # 1 заключается в том, что проверки Rails не являются полноправными средствами: полагаться на них исключительно рискованно, особенно для критических критических проверок, таких как уникальность.
Говоря об этом, причина # 2 (с моей точки зрения): валидации activerecord подвержены условиям гонки, а проверка достоверности уникальности Rails, в частности, не может гарантировать уникальность. Здесь одна статья среди многих документов, почему это так.
Хотя это может быть редкое явление, нарушения ограничений уникальности могут повредить весь набор данных. В редком случае, когда Rails вот-вот сделает это, вы хотите любой ценой остановить его, в котором возникает ограничение уникальности DB: базы данных построены для обработки этой ситуации и будут последовательно применять уникальность, даже если Rails этого не делает.
И причина # 3: почему бы не проверить как в модели, так и в БД? Конечно, вы дублируете немного, но в целом это довольно незначительная проблема по сравнению с выигрышем, если Rails пропускает что-то вроде проверки проверки уникальности. Это действительно не одно и/или предложение: всегда лучше дублировать валидацию в БД, где бы вы ни находились, особенно для критически важных ограничений, таких как уникальность.
В любом случае, это мои мысли, надеюсь, что это поможет.
Ссылка: Где исправлена правильность (скринкаст Гэри Бернхардта, нужна подписка для просмотра)