Lars O. wrote in post #992249:
Hello again!
I was fooling around with your original requirement:
I want to create a class method that takes a bunch
of options and returns a singleton class with those
options set,
…and I think I was probably running into the same problems you were:
class Object
def singleton_class
class << self
self
end
end
end
class Opportunities
def self.using(options)
# Store options in singleton class variable
# @options and then return singleton class
obj = self.new
singleton = obj.singleton_class
singleton.instance_variable_set(:@options, options)
singleton.class_eval do #<----PROBLEM HERE (see output)
def options
@options
end
end
return singleton
end
end
Foo = Opportunities.using(one: 1, two: 2, three: 3)
Bar = Opportunities.using(four: 4, five: 5, six: 6)
p Foo.options
p Bar.options
–output:–
prog.rb:37:in <main>': undefined method
options’ for
#<Class:#Opportunities:0x88cfef8> (NoMethodError)
The problem is that options() is an instance method of the singleton
class, but in this line:
Foo.options
Foo is the singelton class, and therefore options() is being called as a
class method of Foo. A class method of a singleton
class??!! Whaaaat! But you can actually create such a thing in ruby:
class Object
def singleton_class
class << self
self
end
end
end
class Opportunities
def self.using(options)
# Store options in singleton class variable
# @options and then return singleton class
obj = self.new
singleton = obj.singleton_class
singleton.send(:instance_variable_set, :@options, options)
singleton.singleton_class.class_eval do #<---SOLUTION***
def options
@options
end
end
return singleton
end
end
Foo = Opportunities.using(one: 1, two: 2, three: 3)
Bar = Opportunities.using(four: 4, five: 5, six: 6)
p Foo.options
p Bar.options
–output:–
{:one=>1, :two=>2, :three=>3}
{:four=>4, :five=>5, :six=>6}
The syntax is a little simpler doing this:
class << singleton
attr_reader :options #(self.)attr_reader, where self=singleton
end