2010-02-23 3 views
8

У меня есть шаблон строки, как показано нижеоценивающих строковые шаблоны

template = '<p class="foo">#{content}</p>' 

Я хочу, чтобы оценить шаблон на основе текущего значения переменной называется content.

html = my_eval(template, "Hello World") 

Это мой текущий подход к этой проблеме:

def my_eval template, content 
    "\"#{template.gsub('"', '\"')}\"" # gsub to escape the quotes 
end 

Есть ли лучший подход к решению этой проблемы?

EDIT

Я использовал фрагмент HTML в примере кода выше, чтобы продемонстрировать свой сценарий. В моем реальном сценарии есть набор шаблонов XPATH в файле конфигурации. Переменные связывания в шаблоне заменяются для получения допустимой строки XPATH.

Я думал об использовании ERB, но решил, что это может быть перебор.

ответ

11

Вы можете отобразить строку, как если бы это был шаблон erb. Увидев, что вы используете это в грабли, вам лучше использовать Erb.new.

template = '<p class="foo"><%=content%></p>' 
html = Erb.new(template).result(binding) 

Использование методов ActionController первоначально предложенных, включает в себя инстанцировании объект ActionController :: Base и отправка визуализации или render_to_string.

+0

Я использовал фрагмент HTML в шаблоне, чтобы продемонстрировать сценарий. У меня есть набор строк XPATH, которые нуждаются в замене. Я думал об использовании ERB, но мне хотелось чего-то легкого. –

+0

Я должен сказать, что это интригующее решение. Мне нужно запустить мой код в грабли. Поэтому для этого решения может потребоваться некоторая настройка. –

+0

Если вы говорите о рейк-задаче, вам лучше использовать Erb.new вместо ActionController # render. Решение обновлено, чтобы отразить это. – EmFi

3

Не могу сказать, что я действительно рекомендую любой из этих подходов. Это то, для чего нужны библиотеки, такие как erb, и они прошли проверку на все случаи, о которых вы еще не подумали. И все, кто должен коснуться вашего кода, будут вам благодарны. Однако, если вы действительно не хотите использовать внешнюю библиотеку, я включил некоторые рекомендации.

my_eval способ, который вы включили не работал для меня. Попробуйте что-нибудь подобное вместо этого:

template = '<p class="foo">#{content}</p>' 

def my_eval(template, content) 
    eval %Q{"#{template.gsub(/"/, '\"')}"} 
end 

Если вы хотите, чтобы обобщить это это, так что вы можете использовать шаблоны, которые имеют отличные content переменные, вы можете развернуть его на что-то вроде этого:

def my_eval(template, locals) 
    locals.each_pair{ |var, value| eval "#{var} = #{value.inspect}" } 
    eval %Q{"#{template.gsub(/"/, '\"')}"} 
end 

Этот метод будет называться вот так

my_eval('<p class="foo">#{content}</p>', :content => 'value of content') 

Но опять же, я бы посоветовал не кататься самостоятельно в этом случае.

19

Вы можете делать то, что вы хотите с машинным методом струны '%':

> template = "<p class='foo'>%s</p>" 
> content = 'value of content' 
> output = template % content 
> puts output 
=> "<p class='foo'>value of content</p>" 

См http://ruby-doc.org/core/classes/String.html#M000770

+0

Mind_completely_blown.gif – Trip

+1

Это лучший ответ. – WattsInABox

+1

Возможно, стоит добавить, что с помощью этого метода вы можете иметь имена с именами, то есть '' Профиль:% {name},% {age} "% {name: 'John', age: 25}' – mrt

0

Это также хороший один:

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

0

К концу, но я думаю, что лучший способ: ruby-style-guide:

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