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