On Mon, Mar 17, 2014 at 3:58 PM, gvim [email protected] wrote:
Read the rest of Abinoam’s earlier response (sorry if I got your name
haven’t a clue what the options hash refers to.
gvim
Let’s try the explanation from the other direction:
class Person
attr_accessor :age
def initialize(options)
self.age = options[:age]
end
def teenager?
(13…19) === age
end
end
Person.new(age: 17)
When you call a method with this syntax: object.method(key: value)
what it means is:
Create a hash with a key with the symbol :key and the value → value.
So this is equivalent to
a = { :key => value}
It’s a little syntactic sugar to make it look like you are naming
method parameters, but in the end it’s just a simple hash object, with
keys and values, where the keys happen to be symbols.
So, this hash is pass to the method, in this case “new”, which in turn
will pass it internally to “initialize”. Let’s look at that:
def initialize(options)
self.age = options[:age]
end
You have declared that your initialize method receives one parameter
called options. options is the name of the local variable, local to
the method, that is bound to the object that you pass to the “new”
method. In this example it happens to be a hash, remember, so we can
call the method [] on it, with a symbol and get an integer back, cause
that’s what you put in, when calling “new”. You created a hash with
key :age and value 17, so options[:age] returns 17.
Summarizing this part, what you see is equivalent to:
options = { :age => 17}
options[:age] #=> returns 17
Now, the part related to the age instance variable. As Abinoam
explained, attr_accessor creates two methods for you:
def age=(age)
@age = age
end
and
def age
@age
end
So, internally you do have an instance variable called @age. From the
outside, you could set it like
person = Person.new(17)
person.age=18 # birthday → this calls the method age=
puts person.age # this calls the method age
From the inside, you can call the methods on self (the current
instance):
class Person
def test
puts self.age
end
end
Person.new(25).test # should print 25
Now, the age method can be called without self, like this:
class Person
def test
puts age
end
end
There’s no ambiguity here that you mean the method age. So no problem.
But the setter is different. What should Ruby do with this?
class Person
def test_new_age new_age
age = new_age
end
end
As you can see, this looks exactly the same as a regular local
variable assigment. To avoid this ambiguity Ruby tells you to call
methods with the self receiver, in order to differentiate from local
variable assignments. So you need to do:
class Person
def test_new_age new_age
self.age = new_age
end
end
And everything is fine again:
person = Person.new(25)
person.test_new_age(26)
person.age #=> 26
So, coming back to your original example:
def initialize(options)
self.age = options[:age]
end
It’s taking the value assigned to key :age from the hash named
options, and calling the method age= of the object self, passing the
value it got from the hash. The method age= is the one generated by
attr_accessor, which just stores the value in the @age instance
variable.
Hope this helps,
Jesus.