una tecnicas sencillas secundaria rapidas presentacion para niños juegos iniciar grupo divertidas dinamicas conocerse clase ruby class dynamic metaprogramming

ruby - tecnicas - Definición dinámica de clase CON un nombre de clase



juegos para iniciar una clase (4)

¿Qué tal el siguiente código?

dynamic_name = "TestEval2" class_string = """ class #{dynamic_name} def method1 end end """ eval(class_string) dummy2 = Object.const_get(dynamic_name) puts "dummy2: #{dummy2}"

Eval no devuelve el objeto Class de tiempo de ejecución, al menos en mi PC no lo hace. Use Object.const_get para obtener el objeto Class.

¿Cómo defino dinámicamente una clase en Ruby WITH a name?

Sé cómo crear una clase dinámicamente sin un nombre usando algo como:

dynamic_class = Class.new do def method1 end end

Pero no puedes especificar un nombre de clase. Quiero crear una clase dinámicamente con un nombre.

Aquí hay un ejemplo de lo que quiero hacer pero, por supuesto, en realidad no funciona.
(Tenga en cuenta que no estoy creando una instancia de una clase sino una definición de clase)

class TestEval def method1 puts "name: #{self.name}" end end class_name = "TestEval" dummy = eval("#{class_name}") puts "dummy: #{dummy}" dynamic_name = "TestEval2" class_string = """ class #{dynamic_name} def method1 end end """ dummy2 = eval(class_string) puts "dummy2: #{dummy2}" # doesn''t work

Salida real:

dummy: TestEval dummy2:

Salida deseada:

dummy: TestEval dummy2: TestEval2

=============================================== ====

Respuesta: una solución totalmente dinámica que utiliza el método de sepp2k

dynamic_name = "TestEval2" Object.const_set(dynamic_name, Class.new) dummy2 = eval("#{dynamic_name}") puts "dummy2: #{dummy2}"


El nombre de una clase es simplemente el nombre de la primera constante que se refiere a ella.

Es decir, si hago myclass = Class.new y luego MyClass = myclass , el nombre de la clase se convertirá en MyClass . Sin embargo, no puedo hacer MyClass = si no sé el nombre de la clase hasta el tiempo de ejecución.

Entonces, en su lugar, puede usar Module#const_set , que establece dinámicamente el valor de una const. Ejemplo:

dynamic_name = "ClassName" Object.const_set(dynamic_name, Class.new { def method1() 42 end }) ClassName.new.method1 #=> 42


He estado jugando con esto también. En mi caso, estaba intentando probar las extensiones de ActiveRecord :: Base. Necesitaba poder crear dinámicamente una clase, y como el registro activo busca una tabla basada en un nombre de clase, esa clase no puede ser anónima.

No estoy seguro de si esto ayuda a su caso, pero esto es lo que se me ocurrió:

test_model_class = Class.new(ActiveRecord::Base) do def self.name ''TestModel'' end attr_accessible :foo, :bar end

En lo que respecta a ActiveRecord, la definición de self.name fue suficiente. Supongo que esto funcionará en todos los casos donde una clase no puede ser anónima.

(Acabo de leer la respuesta de sepp2k y estoy pensando que es mejor. Dejaré esto aquí de todos modos).


Sé que esta es una pregunta muy antigua, y algunos otros Rubyistas podrían rechazarme de la comunidad por esto, pero estoy trabajando en la creación de una gema de envoltura muy fina que envuelva un popular proyecto de Java con clases de rubí. Basado en la respuesta de @sepp2k, creé un par de métodos auxiliares porque tuve que hacer esto muchas, muchas veces en un proyecto. Tenga en cuenta que el espacio de nombres de estos métodos para que no estén contaminando un espacio de nombres de alto nivel como Object o 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

Para utilizar estos métodos (tenga en cuenta que esto es 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

¿¿POR QUÉ??

Esto me permite crear una gema JRuby que utiliza el proyecto Java y permitiría que la comunidad de código abierto y yo decoremos estas clases en el futuro, según sea necesario. También crea un espacio de nombres más amigable para usar las clases. Como mi gema es una envoltura muy, muy delgada, tuve que crear muchas, muchas subclases y módulos para extender otros módulos.

Como decimos en JD Power, "este es un desarrollo impulsado por la apología: lo siento".