Create Sinatra Partials The Rails Way

Posted by ben on September 25, 2009

This is just a quick post. I’ve been playing around with the Sinatra micro web framework, and have to say that it is excellent. It really is the perfect tool for rapidly creating small and useful Ruby micro-sites.

Being small and lightweight it doesn’t have many of the features of larger frameworks like Ruby on Rails. One of the features I’ve begun to need is the handling of Rails like partials.

Notably I need to pass both local variables and collections to the partial code and have the partials rendered accordingly. I started implementing my own version, and then came across a nice little Github project: Sinatra-Helpers by sbfaulkner.

Anyway here is the code he uses for Sinatra partials:

def haml_partial(name, options = {})
  item_name = name.to_sym
  counter_name = "#{name}_counter".to_sym
  if collection = options.delete(:collection)
    collection.enum_for(:each_with_index).collect do |item,index|
      haml_partial name, options.merge(:locals => {item_name => item, counter_name => index+1})
    end.join
  elsif object = options.delete(:object)
    haml_partial name, options.merge(:locals => {item_name => object, counter_name => nil})
  else
    haml "_#{name}".to_sym, options.merge(:layout => false)
  end
end

You can use his project or if you just need this feature just pop this code into your Sinatra helpers file application_helper.rb:

helpers do

  def partial(name, options = {})
    item_name = name.to_sym
    counter_name = "#{name}_counter".to_sym
    if collection = options.delete(:collection)
      collection.enum_for(:each_with_index).collect do |item, index|
        partial(name, options.merge(:locals => { item_name => item, counter_name => index + 1 }))
      end.join

    elsif object = options.delete(:object)
      partial name, options.merge(:locals => {item_name => object, counter_name => nil})
    else
      haml "_#{name}".to_sym, options.merge(:layout => false)
    end
  end
end

Now you can call the partial from a your page e.g. index.haml

= partial("mypartial", :locals => {:var1 => "value 1", :var2 => "value 2 and so on"})

Create a partial in the same directory as the calling page. Note that this code doesn’t like filenames truncated with a ‘-’, so avoid this if possible. Also like in Rails your partials should start with an underscore. e.g. _mypartial.haml

To access the variable from this partial simply call the local variable name in your code:

%h2 
  This is var1:
  = var1

%p 
  And this is var2:
  = var2

Handling collections, again, is similar to the way Rails handles partial collections. From your page call the partial with a collection such as:

= partial("listitem", :collection => ["item 1", "item 2 and so on"])

Now in the _listitem.haml partial code simply provide the partial name as a variable or the partialname with _counter for the increment number e.g.

%li
  = listitem
  is the 
  = listitem_counter
  in this array

Anyway all pretty basic stuff but I hope it helps the casual Sinatra surfer.

Goodluck.

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

Comments