I have a string template as shown below
template = '<p class="foo">#{content}</p>'
I want to evaluate the template based on current value of the variable called content
.
html = my_eval(template, "Hello World")
This is my current approach for this problem:
def my_eval template, content
"\"#{template.gsub('"', '\"')}\"" # gsub to escape the quotes
end
Is there a better approach to solving this problem?
I used HTML fragment in the sample code above to demonstrate my scenario. My real scenario has set of XPATH templates in a configuration file. The bind variables in the template are substituted to get a valid XPATH string.
I have thought about using ERB, but decided against as it might be a overkill.
I can't say I really recommend either of these approaches. This is what libraries like erb are for, and they've been throughly tested for all the edge cases you haven't thought of yet. And everyone else who has to touch your code will thank you. However, if you really don't want to use an external library, I've included some recommendations.
The my_eval
method you included didn't work for me. Try something like this instead:
template = '<p class="foo">#{content}</p>'
def my_eval( template, content )
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
If you want to generalize this this so you can use templates that have variables other than content
, you could expand it to something like this:
def my_eval( template, locals )
locals.each_pair{ |var, value| eval "#{var} = #{value.inspect}" }
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
That method would be called like this
my_eval( '<p class="foo">#{content}</p>', :content => 'value of content' )
But again, I'd advise against rolling your own in this instance.
You can do what you want with String's native method '%':
> template = "<p class='foo'>%s</p>"
> content = 'value of content'
> output = template % content
> puts output
=> "<p class='foo'>value of content</p>"
See http://ruby-doc.org/core/classes/String.html#M000770
You can render a string as if it were an erb template. Seeing that you're using this in a rake task you're better off using Erb.new.
template = '<p class="foo"><%=content%></p>'
html = Erb.new(template).result(binding)
Using the ActionController methods originally suggested, involves instantiating an ActionController::Base object and sending render or render_to_string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With