Я хотел бы ограничить количество предметов в ассоциации. Я хочу убедиться, что у пользователя нет более 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
Чтобы сделать это, я должен обновить родительскую модель, дочерний контроллер, И я не могу следовать конвенции? Я что-то упускаю? Я неправильно использую has_many, :before_add
? Я искал пример использования :before_add, но не смог найти.
Я думал перенести валидацию на User, но это происходит только при сохранении/обновлении User. Я не вижу способа использовать ее для остановки добавления вещи.
Я предпочитаю решение для Rails 3 (если это имеет значение для данной проблемы).