I have often seen pattern 1 used the most for Rails presenters.
1) Why does the presenter need a view context?
2) Between pattern 1 and 2, pattern 2 seems easier, since you don't need to wrap the entire code with a block. Why isn't this used more often? Is there a downside to using this? vs pattern 1?
3) With pattern 3, why don't people use this pattern at all?
Presenter
module ApplicationHelper
def present(model, presenter_class=nil)
klass = presenter_class || "#{model.class}Presenter".constantize
presenter = klass.new(model, self)
yield(presenter) if block_given?
end
end
class UserPresenter < ApplicationPresenter
def full_name
"#{@model.first_name} #{@model.last_name}"
end
def birth_year
return nil unless @model.birthdate
@model.birthdate.year
end
def nickel_per_year
return nil unless @model.birthdate
difference = Date.today.year - birth_year
@view.number_to_currency(difference * 0.05)
end
end
class ApplicationPresenter < SimpleDelegator
def initialize(model, view)
@model, @view = model, view
super(@model)
end
end
Pattern 1
Using a presenter helper in the view with a block
View
<% @users.each do |u| %>
<% present(u) do |user| %>
<tr>
<td><%= user.full_name %></td>
<td><%= user.email %></td>
<td><%= user.birthdate %></td>
<td><%= user.birth_year %></td>
<td><%= user.nickel_per_year %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<% end %>
Pattern 2
Using a presenter in the view and setting variable
View
<% @users.each do |u| %>
<% user = UserPresenter.new(user, self) %>
<tr>
<td><%= user.full_name %></td>
<td><%= user.email %></td>
<td><%= user.birthdate %></td>
<td><%= user.birth_year %></td>
<td><%= user.nickel_per_year %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Pattern 3
Using the presenter in the controller, assuming you can pass the view context in using a solution like so. https://github.com/endofunky/oprah
UserController
def show
@user = UserPresenter.new(User.find(params[:id]), view_context)
end
def index
@users = Users.all.map {|user| UserPresenter.new(user, view_context) }
end