Rails: Как ограничить количество элементов в ассоциации has_many (от Parent)

Я хотел бы ограничить количество предметов в ассоциации. Я хочу убедиться, что у пользователя нет более X вещей. Этот вопрос был задан ранее и решение имело логику в дочерней теме:

Предложенное решение (для аналогичной проблемы):

class User < ActiveRecord::Base
  has_many :things, :dependent => :destroy
end

class Thing  :create

  def thing_count_within_limit
    if self.user.things(:reload).count >= 5
      errors.add(:base, "Exceeded thing limit")
    end
  end
end

Жестко закодированное "5" является проблемой. Мой лимит меняется в зависимости от родителя. Коллекция Вещей знает свой лимит относительно Пользователя. В нашем случае менеджер может регулировать лимит (вещей) для каждого пользователя, поэтому пользователь должен ограничить свою коллекцию вещей. Мы могли бы заставить thing_count_within_limit запрашивать лимит у своего пользователя:

if self.user.things(:reload).count >= self.user.thing_limit

Но это много пользовательских интроспекций от Вещи. Многочисленные обращения к пользователю и, особенно, этот (:reload) являются для меня тревожными сигналами.

Мысли по поводу более подходящего решения:

Я думал, что has_many :things, :before_add => :limit_things будет работать, но мы должны поднять исключение, чтобы остановить цепочку. Это вынуждает меня обновить things_controller для обработки исключений вместо принятого в rails соглашения if valid? или if save.

class User
  has_many :things, :before_add => limit_things

  private
  def limit_things
    if things.size >= thing_limit
      fail "Limited to #{thing_limit} things")
    end
  end
end

Это Rails. Если мне приходится так много работать, то, вероятно, я делаю что-то не так.

Чтобы сделать это, я должен обновить родительскую модель, дочерний контроллер, И я не могу следовать конвенции? Я что-то упускаю? Я неправильно использую has_many, :before_add? Я искал пример использования :before_add, но не смог найти.

Я думал перенести валидацию на User, но это происходит только при сохранении/обновлении User. Я не вижу способа использовать ее для остановки добавления вещи.

Я предпочитаю решение для Rails 3 (если это имеет значение для данной проблемы).

18
задан Community 23 May 2017 в 12:09
поделиться