Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Ruby use symbols to reference variable names?

When we are defining getter and setter methods for name in the following code:

class Animal
    attr_accessor :name
    def initialize(name)
        @name = name
    end
end

what is happening internally? How is Ruby able to take a symbol and match it with a variable?

like image 515
Jordan Scales Avatar asked Feb 18 '23 22:02

Jordan Scales


2 Answers

It uses instance_variable_get and instance_variable_set for that.

Update: as Andrew Marshall noted, not exactly. Most ruby core methods are defined in C, but the result is essentially the same.

One could define attr_accessor and friends as follows:

def self.attr_accessor(*names)
  names.each do |name|
    define_method(name) do
      instance_variable_get("@#{name}")
    end

    define_method("#{name}=") do |new_value|
      instance_variable_set("@#{name}", new_value)
    end
  end
end

Note that I've also used define_method here to define the accessor methods.

I recommend that you take a look at some introductory texts about ruby metaprogramming, such as "Don’t Know Metaprogramming In Ruby?".

like image 94
Renato Zannon Avatar answered Mar 04 '23 05:03

Renato Zannon


It doesn't match it with a variable, attr_accessor does essentially this (it's actually written in C, but I've written it's roughly Ruby translation here):

def attr_accessor(var_name)
  ivar_name = :"@#{var_name}"
  define_method(var_name) do
    instance_variable_get ivar_name
  end
  define_method("#{var_name}=") do |value|
    instance_variable_set ivar_name, value
  end
end

As you can see, it simply uses the symbol passed to create two methods. It doesn't do anything fancy with the symbol, and is mostly just passing it through. Note, also, that all instance variables "exist" by default and are set to nil, so this will never blow up.

like image 30
Andrew Marshall Avatar answered Mar 04 '23 04:03

Andrew Marshall