Rails: проверка уникальности двух столбцов (вместе)


130

У меня есть Releaseмодель с mediumи countryстолбцов (среди прочих). Не должно быть releasesобщих одинаковых medium/ countryкомбинаций.

Как мне написать это как проверку рельсов?


Ответы:


230

Вы можете использовать проверку уникальности с scopeопцией.

Кроме того, вы должны добавить уникальный индекс в БД, чтобы новые записи не проходили проверки при одновременной проверке перед записью:

class AddUniqueIndexToReleases < ActiveRecord::Migration
  def change
    add_index :releases, [:country, :medium], unique: true
  end
end



class Release < ActiveRecord::Base
  validates :country, uniqueness: { scope: :medium }
end

+1 за индекс, но -1 за то, uniqueчто он не распознается. Для этой части я использовал ответ ниже.
Aleks

7
Да, извините, ключ проверки должен быть uniqueness, а не unique. См. Связанную документацию. Исправляем ответ.
Tompave

1
Хм, приятно, спасибо :) Повторюсь - добавление индекса выводит решение на новый уровень, а не просто как другие решения "кодирования", с которыми я сталкивался, прежде чем нашел этот ответ. +1 за это
Aleks

70

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

validates :country, uniqueness: { scope: [:medium, :another_medium] }

Он проверяет уникальность countryво всех строках со значениями mediumиanother_medium .

Примечание. Не забудьте добавить индекс в столбец выше, это обеспечивает быстрое извлечение и добавляет проверку уровня БД для уникальных записей.

Обновление: для добавления индекса при создании таблицы

t.index [:medium, :another_medium], unique: true

41

Вы можете передать :scopeпараметр своему валидатору следующим образом:

validates_uniqueness_of :medium, scope: :country

Смотрите в документации еще несколько примеров.


8
@DennisBest Это «работает», но не защищает от условий гонки. Если два клиента делают одновременные запросы, они оба могут пройти проверку, если ни один из них не зафиксирован в базе данных до проверки другого. Вам также понадобится уникальное ограничение базы данных, как в ответе tompave.
soupdog
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.