How do I dynamically define a class in Ruby WITH a name?
I know how to create a class dynamically without a name using something li
I know this is a really old question, and some other Rubyists might shun me from the community for this, but I am working on creating a very thin wrapper gem that wraps a popular java project with ruby classes. Based on @sepp2k's answer, I created a couple helper methods because I had to do this many, many times in one project. Note that I namespaced these methods so that they were not polluting some top-level namespace like Object or Kernel.
module Redbeam
# helper method to create thin class wrappers easily within the given namespace
#
# @param parent_klass [Class] parent class of the klasses
# @param klasses [Array[String, Class]] 2D array of [class, superclass]
# where each class is a String name of the class to create and superclass
# is the class the new class will inherit from
def self.create_klasses(parent_klass, klasses)
parent_klass.instance_eval do
klasses.each do |klass, superklass|
parent_klass.const_set klass, Class.new(superklass)
end
end
end
# helper method to create thin module wrappers easily within the given namespace
#
# @param parent_klass [Class] parent class of the modules
# @param modules [Array[String, Module]] 2D array of [module, supermodule]
# where each module is a String name of the module to create and supermodule
# is the module the new module will extend
def self.create_modules(parent_klass, modules)
parent_klass.instance_eval do
modules.each do |new_module, supermodule|
parent_klass.const_set new_module, Module.new { extend supermodule }
end
end
end
end
To use these methods (note that this is JRuby):
module Redbeam::Options
Redbeam.create_klasses(self, [
['PipelineOptionsFactory', org.apache.beam.sdk.options.PipelineOptionsFactory]
])
Redbeam.create_modules(self, [
['PipelineOptions', org.apache.beam.sdk.options.PipelineOptions]
])
end
WHY??
This allows me to create a JRuby gem that uses the Java project and would allow the open source community and I to decorate these classes in the future, as necessary. It also creates a more friendly namespace to use the classes in. Since my gem is a very, very thin wrapper, I had to create many, many subclasses and modules to extend other modules.
As we say at J.D. Power, "this is apology-driven development: I'm sorry".