Бизнес-логика такова: пользователи находятся в лодке через таблицу соединений, я думаю, давайте назовем эту модель Билетом. Но когда пользовательский экземпляр хочет проверить, кто еще находится на лодке, возникает условие, которое спрашивает, имеет ли этот пользователь разрешение видеть всех на лодке или только определенных людей на лодке. Если пользователь может видеть всех, нормальная сделка в порядке: some_user.boats.first.users
возвращает всех пользователей с билетом на эту лодку. Но для некоторых пользователей единственными людьми, которые находятся на лодке (насколько они обеспокоены), являются люди, скажем, в столовой. Поэтому, если билет пользователя «помечен» (с использованием системы в стиле acts_as_taggable
) с «Столовая», единственными пользователями, которые вернулись из some_user.boats.first.users
, должны быть пользователи с билетами, помеченными «Столовая».
Просто для протокола: я не пытаюсь придумать что-то безумное с точки зрения getgo - я пытаюсь втиснуть эту произвольную группировку в (в основном) существующую систему.
Итак, мы получили:
class User
has_many :tickets
has_many :boats, :through => :tickets
end
class Ticket
belongs_to :user
belongs_to :boat
end
class Boat
has_many :tickets
has_many :users, :through => :tickets
end
Изначально я думал, что могу условно изменить виртуальный класс, например:
singleton = class << a_user_instance ; self ; end
singleton.class_eval(<<-code
has_many :tickets, :include => :tags, :conditions => ['tags.id in (?)', [#{tag_ids.to_s(:db)}]]
code
)
Это все сводится к генерации SQL, но при генерации генерирует SQL, заканчивающийся на:
LEFT OUTER JOIN "tags" ON ("tags"."id" = "taggings"."tag_id") WHERE ("tickets"._id = 1069416589 AND (tags.id in (5001,4502)))
Я пробовал копаться в коде ActiveRecord, но я не могу найти нигде, где бы префикс этого 'id' в SQL выше был с подчеркиванием. Я знаю, что ассоциации загружаются при загрузке класса ActiveRecord, и я предполагаю то же самое с одноэлементным классом. пожав плечами .
Я также использовал alias_method_chain
как:
singleton = class << a_user_instance ; self ; end
singleton.class_eval(<<-code
def tickets_with_tag_filtering
tags = Tag.find(etc, etc)
tickets_without_tag_filtering.scoped(:include => :tags, :conditions => {:'tags.id' => tags})
end
alias_method_chain :tickets, :tag_filtering
code
)
Но в то время как при таком подходе создаются желаемые Билеты, любые объединения в этих билетах используют условия в классе, а не в виртуальном классе. some_user.boats.first.users
возвращает всех пользователей.
Любой тип комментария будет оценен, особенно если я использую неправильное дерево с таким подходом. Спасибо!