I've got a light-weight haml-based site that I'm building with Middleman (not Rails, but I'm tagging this with Rails because I think Rails people might know the answer).
Is it possible to define a function in-line in the haml file and then use it later in that same file?
(Yes, I know how to use separately-defined helper files. That's not the question.)
I have a page with a function that is uniquely specialized to that page. Defining it in a helper file is to me an unnecessary separation.
Example:
-def foo(color,text)
-content_tag :p, style: "color: #{color}" do
-text
%html
%head
%title Demo page
%body
%h1 demo page
=foo("red", "this is red")
=foo("blue", "this is blue")
Rendering the above page results in undefined method 'foo'
.
Is there a way to make that work? (Did I define the function incorrectly?)
You have to define a singleton method:
:ruby
def self.foo(color, text)
content_tag :p, style: "color: #{color}" do
text
end
end
%html
%head
%title Demo page
%body
%h1 demo page
= foo("red", "this is red")
When you define foo
it is defined as an instance method of Tilt::CompiledTemplates
, but the template is evaluated in the context of a new Object
which doesn't have foo
. This is an abridged version of what this process looks like:
module Compiled; end
# code inside the `__tilt` method is a compiled haml code:
# Haml::Template.compile(File.read('index.html.haml'), engine: Haml::Engine)
source = <<~CODE
Compiled.class_eval do
def __tilt_4220
_buf = ""
def foo(text)
text
end
_buf << "<h1>demo page</h1>\n"
_buf << foo("this is red")
_buf
end
end
CODE
Object.class_eval(source)
method = Compiled.instance_method(:__tilt_4220)
# render
puts method.bind_call(Object.new)
https://github.com/jeremyevans/tilt/blob/v2.4.0/lib/tilt/template.rb#L192