Partial HAML templating in Ruby without Rails

2019-02-01 00:47发布

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.

5条回答
该账号已被封号
2楼-- · 2019-02-01 01:00

(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.

查看更多
Juvenile、少年°
3楼-- · 2019-02-01 01:01

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.

查看更多
The star\"
4楼-- · 2019-02-01 01:02

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.

查看更多
SAY GOODBYE
5楼-- · 2019-02-01 01:04

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.

查看更多
Rolldiameter
6楼-- · 2019-02-01 01:14
def render_file(filename)
  contents = File.read('views/'+filename)
  Haml::Engine.new(contents).render
end
查看更多
登录 后发表回答