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_hashdefines reader and writer methods for the given attribute. It is equivalent to this:@some_hashrefers to an instance variable of the object, whilesome_hashandsome_hash=are methods. The former returns the value of the variable, the latter sets it.The idiom
self.some_hash ||= {}is equivalent toself.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:
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:Since it sets the instance variable directly, you will not have problems with recursion, nor will you have to call a writer method.
some_hashcan never returnnil, because if@some_hashisnil, 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
Userinstance is created.