开发者

Evaluating string templates

开发者 https://www.devze.com 2022-12-21 13:50 出处:网络
I have a string template as shown below template = \'<p class="foo">#{content}</p>\'

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('&开发者_如何学运维quot;', '\"')}\""  # gsub to escape the quotes
end

Is there a better approach to solving this problem?

EDIT

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.


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.


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.


This is also a nice one:

template = "Price of the %s is Rs. %f."
# %s - string, %f - float and %d - integer

p template % ["apple", 70.00]
# prints Price of the apple is Rs. 70.000000.

more here


To late but I think a better way is like ruby-style-guide:

template     = '<p class="foo">%<content>s</p>'
content_text = 'Text inside p'
output = format( template , content: content_text ) 
0

精彩评论

暂无评论...
验证码 换一张
取 消