Строковая интерполяция, когда не используется строковый литерал

У меня есть Ruby script, который использовал строчную интерполяцию для создания сообщений об ошибках.

p "#{vName} is not a defined variable"  => 'xxx is not a defined variable'

Другой программист пришел и попытался вытеснить строковые литералы в отдельный файл конфигурации. Конечно, он не получает замену.

p err_string_from_config  => '#{vName} is not a defined variable'

Я огляделся, но не мог придумать ничего лучше, чем преобразовать строки sprintf и использовать printf.

Кто-нибудь знает, как заставить подстановку # {} работать с строками, которые не являются буквами двойной кавычки в Ruby script?

Ответы

Ответ 1

На самом деле Ruby имеет функциональность, очень похожую на пример Джона Питона:

$ irb
>> greeting = 'hello %s, my name is %s!'
>> interpolated = greeting % ['Mike', 'John']
=> "hello Mike, my name is John!"
>>

Это также полезно, если ваш аргумент является константой массива. Если вы должны использовать интерполяцию стиля # {}, вы можете использовать eval:

>> greeting = 'hi #{name}'    # notice name is not defined yet
>> name = "mike"
>> eval '"' + greeting + '"'

Метод eval будет намного медленнее, чем использование интерполяции% style, поэтому это компромисс.

Ответ 2

Я предлагаю вам посмотреть Liquid templating language, который предоставляет более мощные функции (например, вы можете ссылаться на параметры по имени). Предыдущий пример будет выглядеть так:

greeting = Liquid::Template.parse("hello {{your_name}}, my name is {{my_name}}!")
interpolated = greeting.render('your_name' => 'Mike', 'my_name' => 'John')
# => "hello Mike, my name is John!"

Ответ 3

Вот как я это делаю, только для записи. Немного яснее imo.

gief = '#{later} please'
later = "later"

puts eval(%Q["#{gief}"])
# => later please

Но, честно говоря, это такой хак. Если у вас нет веской причины использовать строку, используйте вместо нее proc. Я всегда стараюсь использовать простой рубин вместо строк.

gief = Proc.new {|l| "#{l} please" }
later = "later"

puts gief.call(later)
# => later please