Как передать аргумент методу делегата в Rails - PullRequest
13 голосов
/ 24 сентября 2011

Я хотел бы иметь панель инструментов для отображения сводной информации о нескольких моделях, и я реализовал ее с помощью 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, и делегат работал бы автоматически (т. Е. Account знал бы, что должен вернуть атрибут адреса из учетной записи с user_id равно to user_id в экземпляре Dashboard).

Но Dashboard не является классом ActiveRecord, поэтому я не могу объявить belongs_to.Мне нужен другой способ сообщить учетной записи, чтобы найти нужную запись.

Есть ли способ преодолеть эту проблему?(Я знаю, что могу подделать Dashboard, чтобы иметь пустую таблицу, или я могу переписать методы экземпляра пользователя в методы класса, которые принимают аргументы. Но все эти решения - хаки).

Спасибо.

1 Ответ

13 голосов
/ 24 сентября 2011

Когда вы пишете 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
...