Reputation: 283
I have a module that contains both instance methods and class methods when included in a class. Both instance methods and class methods shall access class variables.
module MyModule
@@a_class_variable = "lorem ipsum"
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def a_class_method
@@a_class_variable << "abc"
end
end
# Use it in constructor
def initialize
@@a_class_variable << "abc"
end
def an_instance_method
@@a_class_variable << "abc"
end
end
When I include MyModule
in some class, the interpreter says: NameError: uninitialized class variable @@a_class_method in MyModule::ClassMethods
What am I doing wrong?
Upvotes: 2
Views: 1285
Reputation: 54303
When inside MyModule::ClassMethods
, you're not inside MyModule
and don't have access to @@a_class_variable
. Here's a related question.
With an accessor, your code works fine :
module MyModule
@@a_class_variable = "lorem ipsum"
def self.a_class_variable
@@a_class_variable
end
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def a_class_method
MyModule.a_class_variable << " abc1"
end
end
# Use it in constructor
def initialize
@@a_class_variable << " abc2"
end
def an_instance_method
@@a_class_variable << " abc3"
end
end
class MyObject
include MyModule
end
my_object = MyObject.new
MyObject.a_class_method
p my_object.an_instance_method
#=> "lorem ipsum abc2 abc1 abc3"
As you noted in the comments, it exposes @@a_class_variable
to the public.
Setting the method as private
or protected
wouldn't work in the above example, since ClassMethods
and MyModule
aren't related.
It might not be the cleanest solution, but you could use send
to access the private method :
module MyModule
@@a_class_variable = 'lorem ipsum'
module ClassMethods
def a_class_method
MyModule.send(:__a_class_variable) << ' abc1'
end
end
# Use it in constructor
def initialize
@@a_class_variable << ' abc2'
end
def an_instance_method
@@a_class_variable << ' abc3'
end
class << self
def included(base)
base.extend ClassMethods
end
private
def __a_class_variable
@@a_class_variable
end
end
end
Upvotes: 1