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?
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?".
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With