Я открываю шаблон презентатора (или декоратора) благодаря учебнику Райана Бейтса и внедряю его в учебный проект.
Мне интересно, есть ли способ использовать ActiveSupport delegate
методы между пользовательскими объектами? После рефакторинга моей первой модели (Product) я хотел бы использовать некоторые ProductPresenter
методы экземпляра внутри CartPresenter
экземпляра. Если нет, может, мне следует использовать проблемы докладчика?
В настоящее время я создаю экземпляры презентаторов внутри представлений и обращаюсь к методам помощников, перенаправляя отсутствующие методы в шаблон, но, возможно, мне нужно создать экземпляры презентаторов внутри контроллеров (чтобы доступ к обоим CartPresenter
& ProductPresenter
) и определение метода получения для шаблона (чтобы он не запутывал метод method_missing
)?
РЕДАКТИРОВАТЬ
Благодаря ответу jvillian, :product_presenter
теперь относится к экземпляру ProductPresenter.
Поскольку у меня могут возникнуть другие ситуации, когда мне нужно делегировать методы докладчиков, я добавил :delegated_presenter
к своим BasePresenter
Class BasePresenter
def initialize(object, template)
@object = object
@template = template
end
def self.delegated_presenter(name)
define_method("#{name}_presenter") do
klass = "#{name.capitalize}Presenter".constantize
@delegator ||= klass.new(@object.send(name), @template)
end
end
end
Теперь внутри подклассов докладчика:
class CartPresenter < BasePresenter
delegated_presenter :product
delegate :product_presenter_instance_method, to: :product_presenter
end
Я думаю о том, чтобы сгруппировать их в один метод класса BasePresenter, который будет выполнять всю работу.
Вот как он используется внутри представления:
<% present product do |product_presenter| %>
<div class="card" style="width: 14rem;">
<%= product_presenter.display_card_image %>
<div class="card-body">
<%= product_presenter.display_link_to_product_name(class: 'card-title text-dark') %>
<%= product_presenter.display_link_to_product_supplier(class: 'small text-right') %>
<%= product_presenter.display_truncated_description(class: 'card-text') %>
<%= render partial: 'product_buttons', locals: { product: product } %>
<%= product_presenter.display_tags(class: 'badge badge-pill badge-secondary') %>
</div>
</div>
<% end %>
present
вспомогательный метод, который возвращает объект презентатора.