Обычно такие вещи обрабатываются с помощью вспомогательных методов, таких как:
def profile_link(profile)
profile.link ? content_tag(:a, h(profile.name), :href => profile.link) : 'No profile'
end
К сожалению, вы не можете наложить слой на вспомогательные методы в стиле Presenter, которые расширяют модель во время просмотра. Их нужно вызывать процедурным способом с параметром, своего рода анти-OO.
Подход Presenter не полностью поддерживается в области Rails MVC, поскольку он должен привязываться к представлению, чтобы иметь доступ к различным вспомогательным методам, необходимым для правильной визуализации содержимого, а также информации о сеансе, который может повлиять на представление.
Более надежный подход может заключаться в следующем:
class ProfilePresenter
def initialize(view, profile)
@profile = profile
@view = view
yield(self) if (block_given?)
end
def link
@profile.link ? @view.content_tag(:a, @view.h(profile.name), :href => @profile.link) : 'No profile'
end
def method_missing(*args)
@profile.send(*args)
end
end
По вашему мнению, это будет выглядеть примерно так:
<% ProfilePresenter.new(self, @profile) do |profile| %>
<div><%= profile.link %>
<% end %>
Вы можете упростить вызов этого, создав вспомогательный метод, который делает что-то безумное, например:
def presenter_for(model)
"#{model.class}Presenter".constantize.new(self, model) do |presenter|
yield(presenter) if (block_given?)
end
end
Это означает, что у вас гораздо более простой вызов:
<% presenter_for(@profile) do |profile| %>
<div><%= profile.link %>
<% end %>