Подтвердить что ты не робот

Rails: проверка уникальной комбинации из 3 столбцов

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

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

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

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

Все должны быть действительными. Но другой рекорд с "Audi, A6, Gas" НЕ должен быть действительным.

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

    validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
4b9b3361

Ответ 1

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

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

или даже короче в рубине 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]

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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