Mike Cargal
Mike Cargal

Reputation: 6785

String interpolation when not using a string literal

I have a Ruby script that used string interpolation to build error messages.

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

Another programmer came through and attempted to externalize the string literals to a separate configuration file. Of course, he doesn't get the substitution.

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

I've looked around, but couldn't come up with anything better than converting to sprintf strings and using printf.

Does anybody know how to get the #{} substitution to work on strings that are not double quote literals within the Ruby script?

Upvotes: 15

Views: 6760

Answers (3)

Mark A. Nicolosi
Mark A. Nicolosi

Reputation: 85571

Actually Ruby has functionality very similar to John's Python example:

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

This is also useful if your argument is an array constant. If you must use #{} style interpolation you could use eval:

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

The eval approach is going to be much slower than using % style interpolation, so it's a trade-off.

Upvotes: 24

Raimonds Simanovskis
Raimonds Simanovskis

Reputation: 2948

I suggest that you look at Liquid templating language which provides more powerful features (e.g. you can reference parameters by name). Previous example would look like:

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!"

Upvotes: 2

August Lilleaas
August Lilleaas

Reputation: 54593

Here's how I do it, just for the record. A bit clearer imo.

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

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

But honestly, that is such a hack. Unless you have a really good reason to use a string, use a proc instead. I always try to use plain ruby instead of evaling strings.

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

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

Upvotes: 1

Related Questions