So I create a class in ruby:
class User
def initialize
end
end
Now say I want to create a attribute that is a hash with a getter/setter, I'm confused as to the options I have doing this.
If I do this:
class User
attr_accessor :some_hash
end
But I don't want this hash to be nil ever, always an empty hash.
I'm confused when I should do:
def some_hash
self.some_hash ||= {}
end
and do:
def some_hash
@some_hash ||= {}
end
What is the difference?
If I don't use the attr_accessor, I have to create both the reader and writer (or getter/setter):
def some_hash=()
end
def some_hash
end
I'm hoping someone can clear up the options I would have for creating a some_hash attribute which is a hash, and that never returns a nil if it is empty.
i.e. using attr_accessor, manually creating the methods, and finally when to use @some_hash and self.some_hash
attr_accessor :some_hash
defines reader and writer methods for the given attribute. It is equivalent to this:
class User
def some_hash
@some_hash
end
def some_hash=(a_hash)
@some_hash = a_hash
end
end
@some_hash
refers to an instance variable of the object, while some_hash
and some_hash=
are methods. The former returns the value of the variable, the latter sets it.
The idiom self.some_hash ||= {}
is equivalent to self.some_hash || self.some_hash = {}
.
Boolean operators in Ruby short circuit, which means the second expression (self.some_hash = {}
) will not be executed at all if the first expression (self.some_hash
) returns a true value.
The method:
def some_hash
self.some_hash ||= {}
end
Is actually recursive, since it expands to some_hash || self.some_hash = {}
. It will keep calling itself until you get a stack overflow. Use the second form:
def some_hash
@some_hash ||= {}
end
Since it sets the instance variable directly, you will not have problems with recursion, nor will you have to call a writer method. some_hash
can never return nil
, because if @some_hash
is nil
, it will be assigned an empty hash before the method returns.
By the way, this is also called lazy initialization, because the variable is initialized when it is first accessed, not when the User
instance is created.