Проверка уникальности Rails 3 с областью действия в полиморфной таблице

#ruby-on-rails-3 #validation #unique

#ruby-on-rails-3 #проверка #уникальный

Вопрос:

У меня есть следующая настройка:

 class Vote < ActiveRecord::Base
  belongs_to :voteable, :polymorphic => :true, :counter_cache => true
end

class Proposition < ActiveRecord::Base
  has_many :votes, :as => :voteable
end

class Winner < ActiveRecord::Base
  has_many :votes, :as => :voteable
end
  

Таблица голосования выглядит следующим образом:

 t.string   "ip_address"
t.integer  "voteable_id"
t.string   "voteable_type"
  

Я хочу проверить следующее. Пользователь с заданным ip_address может проголосовать только за 1 предложение. Таким образом, комбинация ip_address, voteable_id и voteable_type должна быть уникальной.

Как я могу добиться этого с помощью «простого» правила проверки?

Ответ №1:

Чтобы гарантировать уникальность, вы должны добавить уникальный индекс в свою базу данных

Если у вас еще нет важных данных, вы можете сделать это внутри миграции с помощью add_index

 add_index(:votes, [:ip_address, :voteable_id, voteable_type], :unique => true, :name => 'allowed_one_vote')
  

если у вас уже есть какие-то данные, это можно сделать с помощью SQL, и это зависит от вашей СУБД

Комментарии:

1. это зависит от вас, если производительность в порядке, вы можете оставить все как есть

2. Это не отвечает на вопрос. Спрашивающий хотел получить проверку. Если для этой ситуации действительно нет конкретной проверки, ответ заключается в том, чтобы просто выполнить пользовательскую проверку. Это может быть или не быть «лучшим» способом (что зависит от ситуации), но выполнение ограничения DB по сравнению с проверкой — это яблоки и апельсины.

Ответ №2:

Добавьте область действия к :ip_address проверке уникальности

 class Vote < ActiveRecord::Base
  # ...
  validates :ip_address, uniqueness: { scope: [:voteable_type, :voteable_id]}
end