Skip to content

Instantly share code, notes, and snippets.

@saturnflyer
Created October 9, 2013 19:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saturnflyer/6906478 to your computer and use it in GitHub Desktop.
Save saturnflyer/6906478 to your computer and use it in GitHub Desktop.
require 'delegate'
# Public: This class initializes a presenter object.
# The presenter wraps a given object and a view object and will forward
# method calls to each. By default, any unknown method will be passed
# to the first object.
# Any methods that need to be sent to the view, may be done explicitly.
#
# Examples:
#
# # Inside a controller you create a helper method to access this object
#
# def presenter
# @presenter ||= ProfilePresenter.new(@profile, view_context)
# end
# helper_method :presenter
#
# # Inside the view, the "presenter" helper method may be accessed
#
# <% presenter.with_military_branch do %>
# <p><strong>Military Branch:</strong> <%= presenter.branch %></p>
# <% end %>
#
class Presenter < SimpleDelegator
# Private: Creates aliased method names for __getobj__ and __setobj__
# which better reflect the wrapped object.
#
# Examples:
#
# class ThingPresenter < Presenter; end
# presenter = ThingPresenter.new(thing, view)
#
# presenter.respond_to?(:thing) #=> true
# presenter.respond_to?(:thing=) #=> true
#
def self.inherited(base)
wrapped_object_name = base.name.split('::').last.sub('Presenter','').underscore
base.send(:alias_method, wrapped_object_name, :__getobj__)
base.send(:alias_method, "#{wrapped_object_name}=", :__setobj__)
end
# Private: This overrides the initialize method in SimpleDelegator and
# calls super to wrap the given object. Then it sets the second argument
# as the view.
def initialize(object, view)
super(object)
@view = view
end
private
attr_reader :view
# Private: Enumerate a collection with the given block
# wrapping each object with an instance of the given class
#
# Examples:
#
def wrapped_enum(wrapper_class, enumerable, &block)
wrapper = wrapper_class.new(nil, view)
enumerable.each do |slot|
wrapper.__setobj__(slot)
block.call(wrapper)
end
end
delegate :current_page, :paginate, :link_to, to: :view
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment