In view we are uing Presenter like this:
# app/views/galleries/show.html
<% present(object: @gallery, shop: @shop, gallery_items: @gallery_items) do |presenter| %>
<div class="shop-name"><%= presenter.shop_name %></div>
<div class="post-filter btn-filter d-inline-block">
<div class="dropdown">
<a class="filter-dropdown dropdown-toggle" href="#" role="button" id="postFilter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<%= presenter.active_filter.present? ? presenter.active_filter[:name] : 'All Photos' %> <%= embedded_svg 'icon-down-arrow.svg', class: 'icon' %>
</a>
<div class="dropdown-menu" aria-labelledby="postFilter">
<a class="dropdown-item <%= 'active' unless params[:view] %>" href="<%= gallery_path(@gallery, channel: params[:channel]) %>">All Photos</a>
<% presenter.view_filters.each do |filter| %>
<%= link_to(filter.path, class: filter.css_classes) do %>
<%= filter.name %>
<% end %>
<% end %>
</div>
</div>
</div>
<% end %>And we are accessing presenter, through helper module:
# app/helpers/application_helper.rb
def present(klass = nil, object:, **objects)
klass ||= "#{object.class}Presenter".constantize
presenter = klass.new(object, self) # we are passing application helper object, so view context goes along with it
presenter.define_objects(objects)
yield(presenter) if block_given? # passing ruby code block and yielding modifying it with `presenter` object
presenter
endAnd gallery presenter look like this:
# app/presenters/application_presenter.rb
# frozen_string_literal: true
class ApplicationPresenter
def initialize(object, template)
@object = object
@template = template # view templete
end
def define_objects(objects_hash)
objects_hash.each do |name, obj|
define_singleton_method(name) do
obj
end
end
end
private
def self.presents(name)
define_method(name) do
@object
end
end
def h
@template
end
end
# app/presenters/gallery_presenter.rb
class GalleryPresenter < ApplicationPresenter
presents :gallery
def view_filters
@filters = VIEW_FILTERS
@filters.map do |filter|
filter = filter.dup
css_classes = 'dropdown-item'
css_classes += ' active' if h.params[:view] == filter[:param]
filter.store(:css_classes, css_classes)
filter.store(:path, h.gallery_path(gallery, view: filter[:param], channel: h.params[:channel])) # using view template object
Hashie::Mash.new(filter)
end
end
def active_filter
view_filters.find { |filter| h.params[:view] == filter[:param] }
end
def newest_gallery
@newest_gallery ||= shop.galleries.order(:updated_at).last # using other object like `shop` which passed from view (from controller).
end
def shop_name
shop.name
end
end