Reputation: 4735
I really don’t need the overhead of Rails for my very small project, so I’m trying to achieve this just using just plain Ruby and HAML.
I want to include another HAML file inside my HAML template. But I haven’t found a good—or really usable—way of doing this.
For example, I have these two HAML files:
documents.haml
%html
%body
= include(menu.haml) body
%article …
menu.haml
%ul
%li
%a whatever …
Include is obviously not the way to go here. But it does a nice job describing what I’m trying to achieve in this example.
Upvotes: 17
Views: 13635
Reputation: 3144
I totally recommend the Tilt gem for these things. It provides a standard interface for rendering many different template langages with the same API, lets you set custom scope and locals, lets you use yield, and is robust and fast. Sinatra is using it for templates.
Example:
require 'haml'
require 'tilt'
template = Tilt.new('path/to/file.haml')
# => #<Tilt::HAMLTemplate @file="path/to/file.haml" ...>
layout = Tilt.new('path/to/layout.haml')
output = layout.render { template.render }
This lets you yield
inside the layout to get the rendered template, just like Rails. As for partials, David already described a simple and nice way to go.
But actually, if what you're writing is going to be served over HTTP, i suggest you take a look at Sinatra, which already provides templating, and has the simplest request routing you could imagine.
Upvotes: 23
Reputation: 6724
(Adding this semi-redundant answer to show how one might incorporate the techniques from other answers.)
Include something like this in your setup code to monkey-patch the Haml library.
module Haml::Helpers
def render_haml(filename)
contents = File.read(Rails.root.join("app", "assets", "templates", filename))
Haml::Engine.new(contents).render
end
end
Then in your Haml file
.foo
= render_haml('partial.haml')
.bar
Obviously this is a Rails-ish example (because I wanted to use HAML in my asset pipeline instead of as views)... You will want to replace Rails.root.join(...)
with a way to find filename
in your project's templates or partials directory.
Upvotes: -1
Reputation: 91
I've had great success just using the instructions posted by David Richards in a concatenated way, without variables, like this:
= Haml::Engine.new(File.read('/Volumes/Project/file_to_include.haml')).render
There's obviously a more elegant way. But for someone who just wants to include one or two files, this should work nicely. It's a drawback that all base files using these includes have to be recompiled after some changes to the latter. It might be worthwile to just use php include if the environment allows that.
Upvotes: 3
Reputation: 191
def render_file(filename)
contents = File.read('views/'+filename)
Haml::Engine.new(contents).render
end
Upvotes: 0
Reputation: 955
I've done this before, just for a quick-and-dirty template producer. The easiest way is to just render the HAML inside the parent object:
%p some haml that's interesting
= Haml::Engine.new('%p this is a test').render
%p some more template
You'll more than likely want to build some methods to make this easier--a couple of helper methods. Maybe you write one called render_file that takes a filename as an argument. That method might look something like:
def render_file(filename)
contents = File.read(filename)
Haml::Engine.new(contents).render
end
Then, your template would look more like:
%p some template
= render_file('some_filename.haml')
%p more template
Note, you will probably need to pass self to the original Haml::Engine render so that it knows how to find your render_file method.
Upvotes: 18