Reputation: 3494
In MyClass I have a class method which creates certain instance methods dynamically (using define_method). However, I also want to dynamically create class methods.
As can be seen below, I am using class << self
and calling define_method
from within this scope (actually I am not sure if scope is the right word to use, though block also doesn't seem correct. What is the correct term to reference everything executed inside of class << self
?) to define a class method.
However, I want to name the class method using a variable that comes from outside of class << self
, namely, column_name
.
Therefore I want to use the variable column_name
inside of class << self
to name my class methods in define_method
.
I get an error when I try to run create_methods
:
NameError: undefined local variable or method 'column_name' for # from (pry):7:in 'singleton class'
class MyClass
@columns = ['col1', 'col2']
def self.create_methods
@columns.each do |column_name|
define_method(column_name) { |column_name| puts column_name }
class << self
define_method(column_name) { |column_name| puts "class_method defined" }
end
end
end
end
How can I access a variable from inside the singleton class? What is the best way of accomplishing what I want to accomplish here (creating class methods)?
Note: I have tried the method define_singleton_method
and it seems to work for what I want to do. Does it accomplish exactly what I am trying to do? Even if it does, my question about using class << self
remains.
Upvotes: 0
Views: 260
Reputation: 631
To accomplish what you want, you can do:
class MyClass
@@columns = ['col1', 'col2']
def self.create_methods
@@columns.each do |column_name|
define_method(column_name) { |column_name| puts column_name }
end
class << self
@@columns.each do |column_name|
define_method(column_name) { |col_name| puts "class_method defined" }
end
end
end
end
Note: Using def self."method_name"
to define a class method let you to use instances variables (ie. @columns
), that's why i redefined as class variable.
When you open the singleton class (class << self
), you lose the previous scope, so you cant get column_name
(Name Error). But have access to class variables.
In your case, use define_singleton_method
. As follow:
class MyClass
@columns = ['col1', 'col2']
def self.create_methods
@columns.each do |column_name|
define_method(column_name) { |column_name| puts column_name }
define_singleton_method(column_name) { |col_name| puts "class_method defined" }
end
end
end
Upvotes: 1