Строковая интерполяция, когда не используется строковый литерал
У меня есть 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