У меня есть следующие модели.У пользователей есть UserActions, и одним из возможных UserAction может быть ContactAction (UserAction - это полиморфизм).Существуют и другие действия, такие как LoginAction и т. Д. Так
class User < AR::Base
has_many :contact_requests, :class_name => "ContactAction"
has_many :user_actions
has_many_polymorphs :user_actionables, :from => [:contact_actions, ...], :through => :user_actions
end
class UserAction < AR::Base
belongs_to :user
belongs_to :user_actionable, :polymorphic => true
end
class ContactAction < AR::Base
belongs_to :user
named_scope :pending, ...
named_scope :active, ...
end
Идея состоит в том, что ContactAction объединяет двух пользователей (с другими последствиями в приложении) и всегда имеет принимающую и отправляющую стороны.В то же время у ContactAction могут быть разные состояния, например, истек срок действия, ожидается и т. Д.
Я могу сказать @user.contact_actions.pending
или @user.contact_requests.expired
, чтобы перечислить все ожидающие / просроченные запросы, которые пользователь отправил или получил.Это прекрасно работает.
Теперь мне нужен способ присоединить к обоим типам ContactAction.Т.е. @user.contact_actions_or_requests
.Я попробовал следующее:
class User
def contact_actions_or_requests
self.contact_actions + self.contact_requests
end
# or
has_many :contact_actions_or_requests, :finder_sql => ..., :counter_sql => ...
end
, но у всех них есть проблема в том, что невозможно использовать дополнительные искатели или named_scopes поверх ассоциации, например, @user.contact_actions_or_requests.find(...)
или @user.contact_actions_or_requests.expired
.
По сути, мне нужен способ выразить связь 1: n, которая имеет два разных пути.Один User -> ContactAction.user_id
, другой User -> UserAction.user_id -> UserAction.user_actionable_id -> ContactAction.id
.А затем объедините результаты (ContactActions) в один список для дальнейшей обработки с named_scopes и / или искателями.
Поскольку мне нужна эта связь буквально в десятках мест, было бы очень сложно написать (и поддерживать!) пользовательский SQL для каждого случая.
Я бы предпочел решить эту проблему в Rails, но я также открыт для других предложений (например, процедура PostgreSQL 8.3 или что-то подобное).Важно то, что, в конце концов, я могу использовать удобные функции Rails, как с любой другой ассоциацией, и, что более важно, также вкладывать их.
Любые идеи будут очень признательны.
Спасибо!
Чтобы дать своего рода ответ на мой собственный вопрос:
Я, вероятно, решу это, используя представление базы данных и добавив соответствующие ассоциации по мере необходимости.Для вышеизложенного я могу
- использовать SQL в finder_sql для создания представления,
- назвать его "contact_actions_or_requests",
- изменить предложение SELECT, чтобы добавитьстолбец user_id,
- добавить приложение / models / ContactActionsOrRequests.rb,
- , а затем добавить "has_many: contact_actions_or_requests" в user.rb.
Я не знаюПока не знаю, как я буду справляться с обновлением записей - кажется, это невозможно сделать с помощью представления - но, возможно, это первый запуск.