After my last post on how Ruby initializes objects, Sagar shared with me following code.
class Abc attr_accessor :a, :b def self.new(a, b) @a = a @b = b end end o = Abc.new("a", "b") puts o.a puts o.b
>> o.a => NoMethodError >> o.b => "b" >>
o.a threw an error but surprisingly
o.b is working.
I was a bit confused by looking this code because of the variables used and also usage of
attr_accessors for more confusion.
To understand how this code works, we need to go back to basics.
What we learned in the “How Ruby initializes objects” blog post is that the
Class#new method does three things.
- Allocate object
- Call initialize on object
- Return the object
In Ruby, return value of a method is return value of the last statement in the method.
Let’s see our definition of
def self.new(a, b) @a = a @b = b end
This method will return value of
b as the return value of
new method. We can confirm this in IRB.
>> Abc.new("Hello", "World") => "World"
So no magic is going on and Ruby is not preferring
Now to know why
o.b is working, we can check if someone has defined a method
b on the
>> o.method(:b) => #<Method: String#b>
Indeed! Ruby’s String class defines a method named
b which returns copied string whose encoding is ASCII-8BIT.
>> checkmark = "\u2713" => "✓" >> checkmark.b => "\xE2\x9C\x93" >>
So there is no dark magic going on. It is just plain Ruby and we just found a mysterious method
Note: The documentation for this method already exists as pointed by few people. But it was a surprise for me to see a method named
b. I had not come across this method before. Also some people asked what is the purpose of this blog post. I just want to share what I found interesting and learned.
Subscribe to my newsletter to know more about such interesting insights from Ruby language.