Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Ruby views without a templating language

branch: master

Use ammeter instead of aruba to test generators

* Tests are much faster
* Failures are improved
* Don't generate a Rails app inside each test
* Don't boot up Rails several times
latest commit 366ad3571b
Joe Ferris authored
Octocat-spinner-32 features Use ammeter instead of aruba to test generators April 30, 2013
Octocat-spinner-32 lib Modernize April 30, 2013
Octocat-spinner-32 spec Use ammeter instead of aruba to test generators April 30, 2013
Octocat-spinner-32 .gitignore Modernize April 30, 2013
Octocat-spinner-32 Gemfile Modernize April 30, 2013
Octocat-spinner-32 LICENSE Added initial documentation November 03, 2009
Octocat-spinner-32 README.textile fix empty/any bug re #no-comments August 09, 2012
Octocat-spinner-32 Rakefile Modernize April 30, 2013
Octocat-spinner-32 TODO.textile Updated the TODO December 01, 2009
Octocat-spinner-32 VERSION Version bump to 0.4.0 March 30, 2010
Octocat-spinner-32 effigy.gemspec Use ammeter instead of aruba to test generators April 30, 2013
README.textile

Effigy

Create usable views in Ruby with HTML and CSS selectors.

Synopsis

In Effigy, your view is a Ruby class that performs transformation on an HTML template. The template is passed to a render method, which calls a private #transform method to apply the transformations. The transformed template is then returned as a string of HTML.

template = %{
  <html>
    <head>
      <title></title>
    </head>
    <body>
      <h1></h1>
      <p class="body"></p>
      <div class="comment">
        <h2></h2>
        <p></p>
        <a>View more</a>
      </div>
      <p id="no-comments">There aren't any comments for this post.</p>
    </body>
  </html>
}

class PostView < Effigy::View
  attr_reader :post

  def initialize(post)
    @post = post
  end

  def transform
    text('h1', post.title)
    text('title', "#{post.title} - Site title")
    text('p.body', post.body)
    replace_each('.comment', post.comments) do |comment|
      text('h2', comment.title)
      text('p', comment.summary)
      attr('a', :href => url_for(comment))
    end
    remove('#no-comments') if post.comments.any?
  end
end

view = PostView.new(post)
document = view.render_html_document(template)

# Result document:
# <html>
#   <head>
#     <title>Post title - Site title</title>
#   </head>
#   <body>
#     <h1>Post title</h1>
#     <p class="body">Post body</p>
#     <div class="comment">
#       <h2>First comment title</h2>
#       <p>First comment body</p>
#       <a href="/comments/1">View more</a>
#     </div>
#     <div class="comment">
#       <h2>Second comment title</h2>
#       <p>Second comment body</p>
#       <a href="/comments/2">View more</a>
#     </div>
#   </body>
# </html>

See the documentation for more information on available transformations.

Chaining

If you prefer, you can select elements and then apply tranformations in a chain. The previous example could have been written like this:

class PostView < Effigy::View
  attr_reader :post

  def initialize(post)
    @post = post
  end

  def transform
    find('h1').text(post.title)
    find('title').text("#{post.title} - Site title")
    find('p.body').text(post.body)
    find('.comment').replace_each(post.comments) do |comment|
      find('h2').text(comment.title)
      find('p').text(comment.summary)
      find('a').attr(:href => url_for(comment))
    end
    find('#no-comments').remove if post.comments.any?
  end
end

#find is also aliased as #f for brevity, if you’re into that sort of thing.

Rails

Effigy integrates with Rails. It provides a view subclass that copies instance variables from the controller, a template handler to find Effigy views and templates, and a generator to create skeleton view files.

Example:

# app/controllers/magic_controller.rb
class MagicController < ApplicationController
  def index
    @spell = 'hocus pocus'
  end
end
# app/views/magic/index.html.effigy
class MagicIndexView < Effigy::Rails::View
  def transform
    text('h1', @spell)
  end
end
# app/templates/magic/index.html
<h1>Spell name goes here</h1>

View this example in your browser and you’ll see “hocus pocus.”

Install

Effigy is distributed as a gem through gemcutter:

sudo gem install effigy -s http://gemcutter.org

Effigy requires Nokogiri.

Why?

Effigy is based on the idea that putting behavior in your templates is confusing and makes them difficult to maintain, and that the closer an ERB template gets to 50% Ruby, 50% HTML, the closer it gets to total chaos. Complicated views require unintuitive concepts (ERB buffers, capture blocks, etc). ERB also has the constant threat of unescaped user input slipping into a view.

Effigy was created because I have never liked interpolation-based templating languages like ERB and because XSLT requires introducing another language (and I like Ruby just fine).

Author

Effigy was written by Joe Ferris. See LICENSE for license info.

Something went wrong with that request. Please try again.