public
Description: A Rails plugin leveraging Ruby blocks to DRY up and modularize views using wrapper classes.
Homepage: http://killswitchcollective.com/articles/22
Clone URL: git://github.com/chrisjpowers/giftwrap.git
name age message
file MIT-LICENSE Loading commit data...
file README.rdoc
file init.rb
directory lib/

GiftWrap

Developed by Chris Powers, The Killswitch Collective (killswitchcollective.com) 06/01/2008

The GiftWrap class is meant to be subclassed by the developer to allow for the easy creation and implementation of Helper Wrapper classes. Here’s the three steps to creating your own wrapper classes.

  1. Create a class that subclasses GiftWrap
  2. You may pass a partial’s name as a string to the use_partial method. The block will be available as the ‘body’ local variable within your partial. The instance of GiftWrap will be available as the :object in the partial.
  3. You may pass a list of method names (or Proc objects, or simply strings) to the before_yield and after_yield class methods to determine what will be called at the beginning and end of your block. These methods can be used instead of, or in conjunction with, the use_partial method.
  4. Use the dynamically created wrapper helper method in your views to initialize and use your class. For example, if your class is named RoundCornerBox, the method round_corner_box will be dynamically created and will accept the same parameters as your class’ initialize method.

ActionView helper methods can be used within a GiftWrap subclass transparently.

Example of subclassing GiftWrap with use_partial:

  class RoundCornerBox < GiftWrap
    use_partial 'shared/round_corner_box'

    attr_reader :name, :header

    # A new instance of RoundCornerBox will be instantiated each time the
    # dynamic round_corner_box is called in the view. The arguments passed into
    # the helper method are passed on directly to the initialize method.
    def initialize(name, options={})
      @name = name
      @header = options[:header]
    end

    # # # These methods can be used within your wrapper block and partial. # # #

    def subheader(text)
      "<h4 class='subheader'>#{text}</h4>"
    end

    def more_button(text, url)
      "<p class='more_button'>#{link_to text, url}</p>"
    end
  end

Example of the shared/_round_corner_box.html.erb partial file:

  <pre>
  <% if round_corner_box.header %>
    <h3 class='round_corner_box_header'><%= round_corner_box.header %></h3>
  <% end %>
  <div class="round_corner_box_top">
    <div class="round_corner_box_bottom" id="<%= round_corner_box.name %>_round_corner_box">
      <%= body %>
    </div>
  </div>
  </pre>

Example of subclassing GiftWrap with before_yield and after_yield:

  class RoundCornerBox < GiftWrap
    before_yield :header, :open_divs
    after_yield :close_divs

    # A new instance of RoundCornerBox will be instantiated each time the
    # dynamic round_corner_box is called in the view. The arguments passed into
    # the helper method are passed on directly to the initialize method.
    def initialize(name, options={})
      @name = name
      @header = options[:header]
    end

    # # # These methods can be used within your wrapper block. # # #

    def subheader(text)
      "<h4 class='subheader'>#{text}</h4>"
    end

    def more_button(text, url)
      "<p class='more_button'>#{link_to text, url}</p>"
    end

    private

    # # # These methods will only be used internally for creating the wrapper markup. # # #

    def header
      @header ? "<h3 class='round_corner_box_header'>#{@header}</h3>" : ''
    end

    def open_divs
      %Q{
        <div class="round_corner_box_top">
          <div class="round_corner_box_bottom" id="#{@name}_round_corner_box">
      }
    end

    def close_divs
      "</div>\n</div>"
    end
  end

Example of using this GiftWrap subclass in the view:

  <% round_corner_box :news, :header => "Today's News" do |b| %>
    <%= b.subheader "Top Story" %>
    <p>Today was a very exciting day in the news...</p>
    <%= b.more_button "Full Story", top_story_path %>

    <%= b.subheader "Lesser Story" %>
    <p>This story is definitely less important than the top story...</p>
    <%= b.more_button "Full Story", bottom_story_path %>
  <% end %>