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.
- get the constant Foo
- call its new method
- execute the tostring instruction
- 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
Dry Ruby Initialization With Hash Argument
How to Set Up the Database.Yml File in Rails
Rails Object Relationships and Json Rendering
How to Use "Rvm --Default" on Macosx
Matching Balanced Parenthesis in Ruby Using Recursive Regular Expressions Like Perl
Ruby on Rails Callback, What Is Difference Between :Before_Save and :Before_Create
How to Compile and Statically Link Ruby Libs for Docker
Is the &Method(:Method_Name) Idiom Bad for Performance in Ruby
Is There a 'Variable_Get' Method? If Not, How to Create My Own
Convert Time from One Time Zone to Another in Rails
What Does the "||=" Operand Stand for in Ruby
Nokogiri Gem Installation Error
Rails 3.1 Limit User Created Objects
Validation Failed: Upload File Has an Extension That Does Not Match Its Contents
Looking For Suggestions For Building a Secure Rest API Within Ruby on Rails