método_missing override no funciona

Escribí una extensión de ActiveRecord conveniente para delegar métodos a un objeto base (basado en herencia de múltiples tablas)

class ActiveRecord :: Base def self.acts_as (base) class_eval% Q {def method_missing (method, * args, & blk) # {base} .send (method, * args, & blk) rescue NoMethodError super end} end end

Tengo un estado clase y una base clase

# clase de estado clase Mi Estado <ActiveRecord :: Base pertenece_ a: mi_objeto actúa_as: mi_objeto final # clase base clase MiObjeto <ActiveRecord :: Base tiene_una: cabeza,: nombre_clase => 'Mi Estado' tiene_una: cola,: nombre_clase => 'Mi Estado' final

Cuando probé esto, descubrí que en algunos casos no funciona. Más específicamente,

> MyState.first.some_method_in_base nil> MyObject.first.tail.some_method_in_base NoMethodError: método indefinido `some_method_in_base 'para #

¿Alguien puede explicarme por qué uno funciona y el otro no?

preguntado el 02 de agosto de 10 a las 06:08

También sugiero usar la versión proporcionada por ActiveSupport de esto, que se llama #delegate: api.rubyonrails.org/classes/Module.html#M000051 -

Sí, terminé usando delegados, pero no son tan convenientes como el concepto de reenviar todos los métodos faltantes a una clase base. -

1 Respuestas

Cuando corres MyObject.first.tail el objeto que realmente responde es un Proxy de asociación clase que

ha eliminado la mayoría de los métodos de instancia básicos y delega # métodos desconocidos a @target a través de method_missing

Puede obtener más detalles sobre la ejecución del proxy:

MyObject.first.proxy_owner
MyObject.first.proxy_reflection
MyObject.first.proxy_target

Si observa el código, puede ver que AssociationProxy envía el método some_method_in_base a su clase MyState. sólo si Mi estado responde a algún_método_en_base como puede ver en el código a continuación.

  private
    # Forwards any missing method call to the \target.
    def method_missing(method, *args, &block)
      if load_target
        if @target.respond_to?(method)
          @target.send(method, *args, &block)
        else
          super
        end
      end
    end

Por lo tanto, la falta_método has definido en el clase objetivo nunca se llama.

Respondido 02 ago 10, 12:08

Vi la definición de method_missing en AssociationProxy antes, pero no pude averiguar qué hacía. Esto tiene mucho sentido. ¡Gracias! - Yitao

¡Eres bienvenido! ¡Y bienvenido a la comunidad StackOverflow! Si la respuesta fue correcta y le ayudó, debe marcarla como la respuesta aceptada haciendo clic en el contorno de la casilla de verificación a la izquierda de la respuesta. También puede votar a favor, si lo desea. Más información sobre stackoverflow.com/faq en la sección "¿Cómo hago preguntas aquí?" - Vlad Zloteanu

Ahí tienes. La casilla de verificación es oscura. Gracias por mencionarlo. - Yitao

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.