porthole 0 Rubygems

Ignore this project. It has no value for the rest of the world. *sob*


You ended up here by mistake. This project is stupid and is only valuable if you need (not “want”) to use “%%foo%%” for your templates, rather than “{{foo}}”.


Inspired by ctemplate and et, Porthole is a framework-agnostic way to render logic-free views.

As ctemplates says, “It emphasizes separating logic from presentation: it is impossible to embed application logic in this template language.”

For a list of implementations (other than Ruby) and tips, see http://porthole.github.com/.


Think of Porthole as a replacement for your views. Instead of views consisting of ERB or HAML with random helpers and arbitrary logic, your views are broken into two parts: a Ruby class and an HTML template.

We call the Ruby class the “view” and the HTML template the “template.”

All your logic, decisions, and code is contained in your view. All your markup is contained in your template. The template does nothing but reference methods in your view.

This strict separation makes it easier to write clean templates, easier to test your views, and more fun to work on your app’s front end.


I like writing Ruby. I like writing HTML. I like writing JavaScript.

I don’t like writing ERB, Haml, Liquid, Django Templates, putting Ruby in my HTML, or putting JavaScript in my HTML.


Quick example:

>> require 'porthole'
=> true
>> Porthole.render("Hello %%planet%%", :planet => "World!")
=> "Hello World!"

We’ve got an examples folder but here’s the canonical one:

class Simple < Porthole
  def name

  def value

  def taxed_value
    value * 0.6

  def in_ca

We simply create a normal Ruby class and define methods. Some methods reference others, some return values, some return only booleans.

Now let’s write the template:

Hello %%name%%
You have just won %%value%% dollars!
Well, %%taxed_value%% dollars, after taxes.

This template references our view methods. To bring it all together, here’s the code to render actual HTML;


Which returns the following:

Hello Chris
You have just won 10000 dollars!
Well, 6000.0 dollars, after taxes.


Tag Types

For a language-agnostic overview of Porthole’s template syntax, see the porthole(5) manpage or http://porthole.github.com/porthole.5.html.


Porthole does escape all values when using the standard double Porthole syntax. Characters which will be escaped: & \ " < >. To disable escaping, simply use triple portholes like %%%unescaped_variable%%%.

Example: Using %%variable%% inside a template for 5 > 2 will result in 5 &gt; 2, where as the usage of %%%variable%%% will result in 5 > 2.

Dict-Style Views

ctemplate and friends want you to hand a dictionary to the template processor. Porthole supports a similar concept. Feel free to mix the class-based and this more procedural style at your leisure.

Given this template (winner.porthole):

Hello %%name%%
You have just won %%value%% bucks!

We can fill in the values at will:

view = Winner.new
view[:name] = 'George'
view[:value] = 100

Which returns:

Hello George
You have just won 100 bucks!

We can re-use the same object, too:

view[:name] = 'Tony'
Hello Tony
You have just won 100 bucks!


A word on templates. By default, a view will try to find its template on disk by searching for an HTML file in the current directory that follows the classic Ruby naming convention.

TemplatePartial => ./template_partial.porthole

You can set the search path using Porthole.template_path. It can be set on a class by class basis:

class Simple < Porthole
  self.template_path = File.dirname(__FILE__)
  ... etc ...

Now Simple will look for simple.porthole in the directory it resides in, no matter the cwd.

If you want to just change what template is used you can set Porthole.template_file directly:

Simple.template_file = './blah.porthole'

Porthole also allows you to define the extension it’ll use.

Simple.template_extension = 'xml'

Given all other defaults, the above line will cause Porthole to look for ‘./blah.xml’

Feel free to set the template directly:

Simple.template = 'Hi %%person%%!'

Or set a different template for a single instance:

Simple.new.template = 'Hi %%person%%!'

Whatever works.


Porthole supports a bit of magic when it comes to views. If you’re authoring a plugin or extension for a web framework (Sinatra, Rails, etc), check out the view_namespace and view_path settings on the Porthole class. They will surely provide needed assistance.


What about global helpers? Maybe you have a nifty gravatar function you want to use in all your views? No problem.

This is just Ruby, after all.

module ViewHelpers
  def gravatar
    gravatar_id = Digest::MD5.hexdigest(self[:email].to_s.strip.downcase)

  def gravatar_for_id(gid, size = 30)

  def gravatar_host
    @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'

Then just include it:

class Simple < Porthole
  include ViewHelpers

  def name

  def value

  def taxed_value
    value * 0.6

  def in_ca

  def users

Great, but what about that @ssl ivar in gravatar_host? There are many ways we can go about setting it.

Here’s on example which illustrates a key feature of Porthole: you are free to use the initialize method just as you would in any normal class.

class Simple < Porthole
  include ViewHelpers

  def initialize(ssl = false)
    @ssl = ssl

  ... etc ...



Finally, our template might look like this:

  %%# users%%
    <li><img src="%% gravatar %%"> %% login %%</li>
  %%/ users%%


Porthole ships with Sinatra integration. Please see lib/porthole/sinatra.rb or http://github.com/defunkt/porthole/blob/master/lib/porthole/sinatra.rb for complete documentation.

An example Sinatra application is also provided: http://github.com/defunkt/porthole-sinatra-example

If you are upgrading to Sinatra 1.0 and Porthole 0.9.0+ from Porthole 0.7.0 or lower, the settings have changed. But not that much.

See this diff for what you need to do. Basically, things are named properly now and all should be contained in a hash set using set :porthole, hash.


Porthole also ships with a Rack::Bug panel. In your config.ru add the following code:

require 'rack/bug/panels/porthole_panel'
use Rack::Bug::PortholePanel

Using Rails? Add this to your initializer or environment file:

require 'rack/bug/panels/porthole_panel'
config.middleware.use "Rack::Bug::PortholePanel"



Thanks to Juvenn Woo for porthole.vim. It is included under the contrib/ directory.

See http://gist.github.com/323622 for installation instructions.


porthole-mode.el is available at https://github.com/porthole/emacs



See http://gist.github.com/323624 for installation instructions.

Command Line

See porthole(1) man page or http://porthole.github.com/porthole.1.html for command line docs.



$ gem install porthole


Thanks to Tom Preston-Werner for showing me ctemplate and Leah Culver for the name “Porthole.”

Special thanks to Magnus Holm for all his awesome work on Porthole’s parser.


Once you’ve made your great commits:

  1. Fork Porthole
  2. Create a topic branch - git checkout -b my_branch
  3. Push to your branch - git push origin my_branch
  4. Create an Issue with a link to your branch
  5. That’s it!

You might want to checkout Resque’s Contributing wiki page for information on coding standards, new features, etc.

Mailing List

To join the list simply send an email to [email protected]. This will subscribe you and send you information about your subscription, including unsubscribe information.

The archive can be found at http://librelist.com/browser/.


You can also find us in #{ on irc.freenode.net.

Related Repositories



A proxy to safely communicate to cross-domain iframes in javascript ...



A proxy to safely communicate to cross-domain iframes in javascript ...



Simply and fast viewport plugin ...



A proxy to safely communicate to cross-domain iframes in javascript ...



A wrapping module for Porthole.js to better manage the communication between frames, and provide marshalling of data for calling methods between frames. ...

Top Contributors

defunkt pvande judofyr josh foca nex3 lawrencepit badboy mdaines adamnbowen tenderlove eric vangberg mchung mmmurf telemachus rafacv lenary aumgn technoweenie


-   v0.99.4 zip tar
-   v0.99.3 zip tar
-   v0.99.2 zip tar
-   v0.99.1 zip tar
-   v0.99.0 zip tar
-   v0.98.0 zip tar
-   v0.13.0 zip tar
-   v0.12.1 zip tar
-   v0.12.0 zip tar
-   v0.11.2 zip tar
-   v0.11.1 zip tar
-   v0.11.0 zip tar
-   v0.10.0 zip tar
-   v0.9.2 zip tar
-   v0.9.1 zip tar
-   v0.9.0 zip tar
-   v0.7.0 zip tar
-   v0.6.0 zip tar
-   v0.5.1 zip tar
-   v0.5.0 zip tar
-   v0.4.2 zip tar
-   v0.4.1 zip tar
-   v0.4.0 zip tar
-   v0.3.2 zip tar
-   v0.3.1 zip tar
-   v0.3.0 zip tar
-   v0.2.2 zip tar
-   v0.2.1 zip tar
-   v0.2.0 zip tar
-   v0.1.4 zip tar