Я хотел бы ограничить количество элементов в ассоциации. Я хочу, чтобы у Пользователя не было больше X Вещей. Этот вопрос был задан до, и у решения была логика у ребенка:
Предлагаемое решение (для аналогичной проблемы):
class User < ActiveRecord::Base
has_many :things, :dependent => :destroy
end
class Thing <ActiveRecord::Base
belongs_to :user
validate :thing_count_within_limit, :on => :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
Но, это много пользовательских интроспекций от Thing. Несколько вызовов пользователю и, особенно, что (:reload)
являются красными флагами для меня.
Мысли о более подходящем решении:
Я думал, что has_many :things, :before_add => :limit_things
будет работать, но мы должны сделать исключение для остановить цепочку. Это заставляет меня обновлять thing_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, но не смог найти.
Я думал о переносе проверки на пользователя, но это происходит только при сохранении/обновлении пользователя. Я не вижу способа использовать его, чтобы остановить добавление Thing.
Я предпочитаю решение для Rails 3 (если это имеет значение для этой проблемы).