filmnut filmnut - 1 month ago 8
Ruby Question

Setting Variables within `self.included`

In Ruby, why can't I set the value of variables directly within a module's

self.included
method?

For example, the following code outputs
NilClass
(indicating that the
@sound
variable has NOT been set):

module Animal
def self.included(klass)
attr_accessor :sound
@sound = "Woof!" # <-- Variable assignment
end

def speak
puts @sound.class
end
end

class Dog
include Animal
end

dog = Dog.new
dog.speak # => NilClass


However, if I set the value of
@sound
within the module's
speak
method (instead of inside of
self.included
), then the variable is set correctly. For example, the following code outputs
String
:

module Animal
def self.included(klass)
attr_accessor :sound
end

def speak
@sound = "Woof!" # <-- Variable assignment
puts @sound.class
end
end

class Dog
include Animal
end

dog = Dog.new
dog.speak # => String


I would have expected both code samples above to output
String
.

Answer

In first example the receiver in self.included block is Dog class, not it's instance, meaning you are defining class instance variable @sound, not instance variable.

You can check it by running

Dog.instance_variable_get(:@sound) # with first example

speak method returns NilClass because dog does not have @sound instance variable defined.

In second example you are defining an instance variable @sound, thus it works as you expect.

Comments