Как я могу остановить коллекцию << (объект, ...) от добавления дубликатов? - PullRequest
1 голос
/ 30 августа 2011

Учитывая модель Обеда, у которой есть много Овощных моделей, я предпочел бы, чтобы

dinner.vegetables << carrot

не добавлять морковь, если

dinner.vegetables.exists? carrot

Тем не менее, это так. Он будет добавлять дубликаты записи каждый раз, когда << вызывается. </p>

Существует опция: uniq, которую вы можете установить для ассоциации, но она только ВЫБИРАЕТ И ВОЗВРАЩАЕТ один результат, если есть кратные значения, она НЕ УКАЗЫВАЕТ уникальные значения.

Я могу проверить, существует ли? каждый раз, когда я добавляю объект obj в коллекцию, но это утомительно и подвержено ошибкам.

Как я могу использовать << свободно и не беспокоиться об ошибках и не проверять уже существующие члены коллекции каждый раз? </p>

Ответы [ 4 ]

2 голосов
/ 30 августа 2011

Лучше всего использовать Set вместо Array:

set = Set.new
set << "a"
set << "a"
set.count  -> returns 1
1 голос
/ 30 августа 2011

Вы можете добавить уникальное ограничение ActiveRecord, если у вас есть модель соединения, представляющая отношение «многие ко многим» между обедами и овощами.Это одна из причин, по которой я использую модели соединения и has_many :through вместо has_and_belongs_to_many.По возможности важно добавить ограничение уникальности на уровне базы данных.

ОБНОВЛЕНИЕ:

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

class Dinner
  has_many :dinner_vegetables
  has_many :vegetables, :through => :dinner_vegetables
end

class Vegetable
  has_many :dinner_vegetables
  has_many :dinners, :through => :dinner_vegetables
end

class DinnerVegetable
  belongs_to :dinner
  belongs_to :vegetable

  validates :dinner_id, :uniqueness => {:scope => :vegetable_id} # You should also set up a matching DB constraint
end
0 голосов
/ 31 августа 2011

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

  has_many :vegetables, :before_add => :enforce_unique

  def enforce_unique(assoc)
    if exists? assoc
    ...
  end

Делать это на уровне БД - это отличная идея, если вам ДЕЙСТВИТЕЛЬНО НУЖНО, чтобы это было уникально, но в случае, если это не является критически важным, вышеуказанного решения достаточнодля меня.

Это в основном, чтобы избежать неприятного ощущения, когда в БД лежат лишние записи ...

0 голосов
/ 30 августа 2011

Идеи других авторов хороши, но в качестве другого варианта вы также можете применить это на уровне базы данных, используя, например, ограничение UNIQUE в MySQL .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...