String Interpolation in Ruby Doesn't Work

String interpolation in Ruby doesn't work?

Regardless of which version of Ruby you're using, string interpolation doesn't happen in single-quoted strings. Use double-quoted strings or %Q-style strings.

Why does single quote not work with string interpolation in ruby

Ruby doesn't interpret single-quoted strings.

This might seem like a limitation at first, but it's actually a nice feature. It allows you to enter many characters without having to escape them, which results in more legible code:

file = 'C:\foo\bar\baz.txt'

# as opposed to:

file = "C:\\foo\\bar\\baz.txt"

Or when having a string about string interpolation itself: (note that Stack Overflow's syntax highlighting is misleading – there's no interpolation)

string = 'In Ruby, you can write "1 + 2 = #{ 1 + 2 }" to get "1 + 2 = 3".'

# instead of:

string = "In Ruby, you can write \"1 + 2 = \#{ 1 + 2 }\" to get \"1 + 2 = 3\"."

Apart from '...' and "...", Ruby also has %q(...) and %Q(...) style string literals (the former without, the latter with interpolation). This is especially useful if your string contains both, single and double quotes:

string = %q(A string containing '...' and "...")

You can even pick your own delimiter: (again, the syntax highlighter can't keep up)

string = %q@A string containing '...', "..." and (...)"@

And finally, you can mix and match different string literal styles:

string = %q(foo) 'bar' "baz"
#=> "foobarbaz"

Ruby string interpolation not working when called from an included file

Local variables like id cannot be called across files. Their scopes are limited within a file. In order to use it, you have to assign id in the same file as it is used. Furthermore, your assignment of id after requiring 'urls.rb' is meaningless.

String interpolation not working in Sinatra redirect

In ruby the string literals declared in single quotes are not interpolated, unlike double-quoted literals:

"#{42}"
#⇒ "42"
'#{42}'
#⇒ "\#{42}"

So, just change single quotes to double quotes in the argument to redirect to.

Ruby String #{} doesn't work

#{} is not some magic that gets converted to interpolation whenever it occurs. It's a literal syntax for interpolating. Here you are not writing it literally, you get it by doing a replacement. Instead, you could do something like:

template = "{{name}} likes {{animal_type}}"
options = {name: 'John', animal_type: 'dogs'}
template.gsub(/{{(.*?)}}/) { options[$1.to_sym] } # => "John likes dogs"

This captures the name inside the moustaches and indexes the hash with it.


Even better would be to utilize the existing format functionality. Instead of moustaches, use %{}:

template = "%{name} likes %{animal_type}"
options = {name: 'John', animal_type: 'dogs'}
template % options # => "John likes dogs"

What happens when you use string interpolation in ruby?

Short version

Ruby does call to_s, but it checks that to_s returns a string. If it doesn't, ruby calls the default implementation of to_s instead. Calling to_s recursively wouldn't be a good idea (no guarantee of termination) - you could crash the VM and ruby code shouldn't be able to crash the whole VM.

You get different output from Fake.new.to_s because irb calls inspect to display the result to you, and inspect calls to_s a second time

Long version

To answer "what happens when ruby does x", a good place to start is to look at what instructions get generated for the VM (this is all MRI specific). For your example:

puts RubyVM::InstructionSequence.compile('"#{Foo.new}"').disasm

outputs

0000 trace            1                                               (   1)
0002 getinlinecache 9, <is:0>
0005 getconstant :Foo
0007 setinlinecache <is:0>
0009 opt_send_simple <callinfo!mid:new, argc:0, ARGS_SKIP>
0011 tostring
0012 concatstrings 1
0014 leave

There's some messing around with the cache, and you'll always get trace, leave but in a nutshell this says.

  1. get the constant Foo
  2. call its new method
  3. execute the tostring instruction
  4. execute the concatstrings instruction with the result of the tostring instruction (the last value on the stack (if you do this with multiple #{} sequences you can see it building up all the individual strings and then calling concatstrings once on all consuming all of those strings)

The instructions in this dump are defined in insns.def: this maps these instructions to their implementation. You can see that tostring just calls rb_obj_as_string.

If you search for rb_obj_as_string through the ruby codebase (I find http://rxr.whitequark.org useful for this) you can see it's defined here as

VALUE
rb_obj_as_string(VALUE obj)
{
VALUE str;

if (RB_TYPE_P(obj, T_STRING)) {
return obj;
}
str = rb_funcall(obj, id_to_s, 0);
if (!RB_TYPE_P(str, T_STRING))
return rb_any_to_s(obj);
if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
return str;
}

In brief, if we already have a string then return that. If not, call the object's to_s method. Then, (and this is what is crucial for your question), it checks the type of the result. If it's not a string it returns rb_any_to_s instead, which is the function that implements the default to_s

Ruby String interpolation throws syntax error in 1.9.3 but not 2.3.1

It is not iterpolation that is the problem.

{ symbol: value } is a new syntax, which is a shortcut for { :symbol => value }. In its first iteration, I don't think it supported { "symbol": value } automatic string symbolification feature. Use the old-fashioned { "symbol".to_sym => value } if backward compatibility is a goal.

(If you know that all you're doing is converting to JSON, you can even just leave it as { "string" => value }, comforted by the knowledge that JSON does not make a distinction between strings and symbols; but I'd consider it a code smell.)

ERB String interpolation generating incorrect HTML syntax

This produces:

<div class="product" fav>

No, it doesn't. It produces <div class=product fav>. What you see (via something like "inspect element", correct?) is browser trying to interpret your broken markup as close to html spec as it can.

As noted in other answers, what you should do instead is something like this:

<div class="<%= cls %>">

Why doesn't interpolation of constants work with percent notation in Ruby

You're misusing %W literal. From book:

%W - Interpolated Array of words, separated by whitespace

so it doesn't have anything to do with interpolation.

Ruby String interpolation in a shell execution

The issue is that you're using single quotes for the string. Single-quoted strings don't use interpolation. Here's something that works:

require 'date'
puts "Start"
datuh = DateTime.now
puts datuh
pid1 = Kernel.spawn("mkdir -p \"#{datuh}\"")
Process.wait pid1
puts "Finished"

More details here: https://ruby-for-beginners.rubymonstas.org/bonus/string_interpolation.html



Related Topics



Leave a reply



Submit