with method dynamically define_method define ruby metaprogramming class-method

ruby - dynamically - ¿Cómo uso define_method para crear métodos de clase?



ruby define method (7)

Creo que en Ruby 1.9 puedes hacer esto:

class A define_singleton_method :loudly do |message| puts message.upcase end end A.loudly "my message" # >> MY MESSAGE

Esto es útil si está intentando crear métodos de clase metaprogramáneamente:

def self.create_methods(method_name) # To create instance methods: define_method method_name do ... end # To create class methods that refer to the args on create_methods: ??? end

Mi respuesta a seguir ...


Derivado de: Jay y Why , que también proporcionan formas de hacer que esto sea más bonito.

self.create_class_method(method_name) (class << self; self; end).instance_eval do define_method method_name do ... end end end

Actualización : a partir de la contribución de VR a continuación; un método más conciso (siempre y cuando solo defina un método de esta manera) que todavía sea independiente:

self.create_class_method(method_name) (class << self; self; end).send(:define_method, method_name) do ... end end

pero tenga en cuenta que usar send () para acceder a métodos privados como define_method () no es necesariamente una buena idea (en mi opinión es que se va en Ruby 1.9).


Esta es la forma más simple en Ruby 1.8+:

class A class << self def method_name ... end end end


Esto funciona para mí en Ruby 1.9.3

class B def self.class_method(param) puts param end end B.class_method("something") # outputs "something".


Para ser utilizado en Rails si desea definir dinámicamente métodos de clase de preocupación:

module Concerns::Testable extend ActiveSupport::Concern included do singleton_class.instance_eval do define_method(:test) do puts ''test'' end end end end


Prefiero usar send para llamar a define_method, y también me gusta crear un método de metaclase para acceder a la metaclase:

class Object def metaclass class << self self end end end class MyClass # Defines MyClass.my_method self.metaclass.send(:define_method, :my_method) do ... end end


También podría hacer algo como esto sin depender de definir_método:

A.class_eval do def self.class_method_name(param) puts param end end A.class_method_name("hello") # outputs "hello" and returns nil