Skip to content

Instantly share code, notes, and snippets.

@jhbabon
Created May 10, 2012 09:27
Show Gist options
  • Save jhbabon/2652106 to your computer and use it in GitHub Desktop.
Save jhbabon/2652106 to your computer and use it in GitHub Desktop.
Presenter pattern for Rails 2 apps
# -*- encoding: utf-8 -*-
# app/helpers/application_helper.rb
module ApplicationHelper
# code...
def present(object, klass = nil)
presenter = ::BasePresenter.build(object, self, klass)
yield presenter if block_given?
presenter
end
end
# -*- encoding: utf-8 -*-
# app/presenters/base_presenter.rb
class BasePresenter
class << self
def presents(name)
define_method(name) do
@object
end
end
def build(object, view, klass = nil)
klass ||= "#{object.class.name}Presenter".constantize
klass.new(object, view)
end
end
def initialize(object, view)
@object = object
@view = view
end
def h
@view
end
protected :h
end
# -*- encoding: utf-8 -*-
# test/unit/presenters/base_presenter_test.rb
require 'test_helper'
require File.expand_path(File.dirname(__FILE__) + "/presenter_test_case")
class Example; end
class ExamplePresenter < BasePresenter
presents :example
end
class BasePresenterTest < PresenterTestCase
setup :prepare_presenter
test "should build the associated presenter" do
assert @presenter.is_a?(ExamplePresenter)
end
test "should access the presented object by its name" do
assert @presenter.respond_to?(:example)
assert_equal @example, @presenter.example
end
private
def prepare_presenter
@example = Example.new
@presenter = BasePresenter.build(@example, view)
end
end
# -*- encoding: utf-8 -*-
# app/presenters/post_presenter.rb
# Example Presenter for the Post model.
class PostPresenter < BasePresenter
presents :post
delegate :title, :to => :post
def linked_title
h.link_to post.title, post
end
# code ...
end
# -*- encoding: utf-8 -*-
# test/unit/presenters/presenter_test_case.rb
require 'test_helper'
class PresenterTestCase < ActiveSupport::TestCase
private
def view
@view ||= build_view
end
def build_view
klass = Class.new do
class << self
def helpers_dir
"#{Rails.root}/app/helpers"
end
def all_application_helpers
extract = /^#{Regexp.quote(helpers_dir)}\/?(.*)_helper.rb$/
Dir["#{helpers_dir}/**/*_helper.rb"].map { |file| file.sub extract, '\1' }
end
end
all_application_helpers.each do |helper|
file_name = helper.to_s.underscore + '_helper'
class_name = file_name.camelize
require_dependency file_name
include class_name.constantize
end
end
klass.new
end
end
<%# app/views/posts/show.html.erb %>
<% present @post do |presenter| %>
<h2><%= presenter.linked_title %></h2>
<% end %>
@jhbabon
Copy link
Author

jhbabon commented May 10, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment