Reputation: 13300
module Hello
def self.log()
p "log called"
end
class Shape
def self.test
log
end
end
def self.test1
log
end
end
Hello::Shape.test # undefined local variable or method `log'
Hello.test1 # prints "log called"
I know the first statement will work if I prefix log with Hello like :Hello.log
But why cant Shape access the log method even if it is within the same module?
Upvotes: 3
Views: 50
Reputation: 443
Since the value of self is Shape, by default Ruby will look for log method defined in Shape class. You don't have a log method so it will raise an error. Even if the Shape is within the same module, when you use the keyword 'class', Ruby opens a new context, which means all the definitions of methods, variables etc defined within the module Hello goes out of scope within the Shape class. You have to explicity specify which log method you want to call by prefixing it with the class or module name within the Shape class.
Upvotes: 0
Reputation: 22325
Whenever you type a method call without an explicit receiver like
log
That's the same as
self.log
So you're basically doing
class Shape
def self.test
self.log
end
end
self
is Shape
and Shape
doesn't have a log
method. That's why you get the error. So to do what you want to do, you need to add Hello
's method to Shape
. But this is impossible! def self.log
adds a method to Hello
's singleton class, and when it comes to singleton methods Ruby really doesn't let you move them around. Singleton methods only go with a single instance.
So how can you get around this? The key is to define log
as a regular instance method - then you can easily move it around to other classes and modules.
module Hello
# add all instance methods as class methods
extend self
def log
p "log called"
end
class Shape
# Module.nesting.last is just a clever way of referring to Hello
extend Module.nesting.last
def self.test
log
end
end
def test1
log
end
end
Upvotes: 2