What's the difference between "#@{var}" and "@#{var}" in Ruby?

470 views Asked by At

I am quite new to Ruby and always assumed these two notations were an identical way to interpolate instance variables until I noticed the difference in the example code below for the 'vendor' parameter.

class Component
    def  initialize(name, version)
         @vendor = "vendor"
         @name = name
         @version = version
         puts  "#{@vendor}-@#{name}-@#{version}" 
    end 
end

ConfiguredComponent.new("param1", "param2")

=> this works

class Component
    def  initialize(name, version)
         @vendor = "vendor"
         @name = name
         @version = version
         puts  "@#{vendor}-@#{name}-@#{version}" 
    end 
end

ConfiguredComponent.new("param1", "param2")

=> using @#{vendor} notation does't work => :in 'initialize': undefined local variable or method `vendor' for # (NameError)

  class Component
     def  initialize(name, version)
        @vendor = "vendor"
        @name = name
        @version = version
        puts  "#{@vendor}-#{@name}-#{@version}" 
     end 
  end

  Component.new("param1", "param2")

=> this also works

2

There are 2 answers

1
SteveTurczyn On BEST ANSWER

It's the #{(expression)} that's significant.

If the expression is #{name} then that's substituting the variable name which in all your examples comes from the parameters input into the method.

If the expression is #{@name} then that's substituting the variable @name which is defined in the fourth line of your methods.

@#{name} is not a special construct. It's just the string @ followed by the contents of the variable name.

The reason it didn't work in your second example is that you simply haven't defined a variable vendor.

2
Eric Duminil On

Here are all the examples I could think of :

@a = "hello"

strings =[ 
  "@a world",
  "@{a} world",
  "#a world",
  "#{@a} world",
  "#@a world",
  "#@aworld", # ! Will not output anything (no space after "@a", and @aworld isn't defined ) !
  "@#{@a} world"
]

puts strings

It outputs :

@a world
@{a} world
#a world
hello world
hello world

@hello world

But :

puts "@#{a} world"

throws an exception :

undefined local variable or method `a' for main:Object (NameError)

a needs to be a defined variable or a method :

class Test
  attr_accessor :a

  def greetings
    puts "#{a} world"
  end
end

t   = Test.new
t.a = "hello"
t.greetings # hello world