Как передать аргумент методу делегирования в Rails
Я бы хотел, чтобы панель инструментов отображала резюме нескольких моделей, и я реализовал ее с помощью Presenter без собственных данных. Я использую класс ActiveModel (без таблицы данных):
class Dashboard
attr_accessor :user_id
def initialize(id)
self.user_id = id
end
delegate :username, :password, :to => :user
delegate :address, :to => :account
delegate :friends, :to => :friendship
end
Делегатом я хочу позвонить Dashboard.address
и вернуться Account.find_by_user_id(Dashboard.user_id).address
.
Если Dashboard была классом ActiveRecord, тогда я мог бы объявить Dashboard#belongs_to :account
, и делегат будет работать автоматически (т.е. учетная запись будет знать, что она должна возвращать атрибут адреса из учетной записи с user_id
equals to user_id
в экземпляре Dashboard).
Но Dashboard не является классом ActiveRecord, поэтому я не могу объявить belongs_to
. Мне нужно еще один способ сообщить Учетной записи для правильной записи.
Есть ли способ преодолеть эту проблему? (Я знаю, что могу подделать Dashboard, чтобы иметь пустую таблицу, или я могу переписать методы экземпляра пользователя методам класса, которые принимают аргумент. Но эти решения - все хаки).
Спасибо.
Ответы
Ответ 1
Когда вы пишете delegate :address, :to => :account
, это создает новый метод address
на Dashboard, который в основном вызывает метод account
на одном и том же объекте, а затем вызывает address
в результате этого метода account
. Это (очень грубо) сродни написанию:
class Dashboard
...
def address
self.account.address
end
...
end
С вашим текущим классом все, что вам нужно сделать, это создать метод account
, который возвращает учетную запись с правильным user_id
:
class Dashboard
attr_accessor :user_id
def initialize(id)
self.user_id = id
end
delegate :username, :password, :to => :user
delegate :address, :to => :account
delegate :friends, :to => :friendship
def account
@account ||= Account.find_by_user_id(self.user_id)
end
end
Это позволит вам получить доступ к адресу, подобному этому:
dashboard = Dashboard.new(1)
# the following returns Account.find_by_user_id(1).address
address = dashboard.address