Рельсы: Проверьте уникальную комбинацию из 3 столбцов


Привет я не хочу, чтобы проверить уникальную комбинацию из 3 столбцов в моей таблице.

допустим, у меня есть таблица под названием cars со значениями :brand, :model_name и :fuel_type.

затем я хочу проверить, является ли запись уникальной на основе комбинации этих 3. Пример:

    brand    model_name    fuel_type
    Audi     A4            Gas
    Audi     A4            Diesel
    Audi     A6            Gas

все должны быть действительны. Но другая запись с "Audi, A6, газ" не должна быть действительной.

Я знаю об этой проверке, но я сомневаюсь, что это действительно так то, что я хочу.

    validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
5   51   2011-09-15 13:43:10

5 ответов:

есть синтаксическая ошибка в вашем фрагменте кода. Правильная проверка :

validates_uniqueness_of :car_model_name, :scope => [:brand_id, :fuel_type_id]

или даже короче в ruby 1.9.x:

validates_uniqueness_of :car_model_name, scope: [:brand_id, :fuel_type_id]

С рельсы 4 вы можете использовать:

validates :car_model_name, uniqueness: { scope: [:brand_id, :fuel_type_id] }

С рельсы 5 можно использовать

validates_uniqueness_of :car_model_name, scope: %i[brand_id fuel_type_id]

зависит от ваших потребностей вы также можете добавить ограничение (как часть миграции создания таблицы или как отдельный) вместо проверки модели:

add_index :the_table_name, [:brand, :model_name, :fuel_type], :unique => true

добавление уникального ограничения на уровне базы данных имеет смысл, если несколько подключений к базе данных выполняют операции записи одновременно.

Я бы сделал это так:

validates_uniqueness_of :model_name, :scope => {:brand_id, :fuel_type_id}

потому что это имеет больше смысла для меня:

  • не следует дублировать " названия моделей "для комбинации" Марка "и" тип топлива", vs
  • не должно быть дублированных " брендов "для комбинации" название модели "и"тип топлива"

но это субъективное мнение.

конечно, если бренд и fuel_type являются отношениями к другим моделям (если нет, то просто отбросьте часть "_id"). С проверкой уникальности вы не можете проверить столбцы, отличные от db, поэтому вам нужно проверить внешние ключи в модели.

вам нужно определить, какой атрибут проверяется - вы не проверяете все сразу, если хотите, вам нужно создать отдельную проверку для каждого атрибута, поэтому, когда пользователь ошибается и пытается создать дублированную запись, вы показываете ему ошибки в форме рядом с недопустимым полем.

к рельсам 4 правильный код с новым хэш-шаблоном

validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]}

использование этого метода проверки в сочетании с ActiveRecord::Validations#save не гарантирует отсутствие повторяющихся вставок записей, поскольку проверки уникальности на уровне приложения по своей сути подвержены условиям гонки.

Это может даже произойти, если вы используете транзакции с сериализуемым уровнем изоляции. Лучший способ обойти эту проблему-добавить уникальный индекс в таблице базы данных с помощью ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. В редких случаях, когда возникает состояние гонки, база данных гарантия уникальности поля.