2012-09-22 16 views
5

Tengo un objeto Ruby (un objeto ActiveRecord, específicamente) llamado User. Responde a métodos como find_by_id, find_by_auth_token, etc. Sin embargo, estos no son métodos que se definen a través de def o define_method. En cambio, son métodos dinámicos que se manejan a través del method_missing.Método de Object # y respondedores dinámicos

me gustaría obtener una referencia a uno de estos métodos a través de Object#method, por ejemplo .:

User.method(:find_by_auth_token) 

No se ve como esto funciona sin embargo. La mejor solución que he llegado con es:

proc { |token| User.find_by_auth_token(token) } 

¿Hay alguna otra manera alrededor usando un método tal como envoltorio esto? ¿Realmente no puedo usar Object#method para métodos dinámicos?

+2

Para cualquier persona que se topa con esto en el futuro, estos métodos de búsqueda dinámicos quedará obsoleta en Rails 4.0. Personalmente, me mantendría cauteloso al agregar funcionalidad adicional sobre ellos. https://github.com/rails/activerecord-deprecated_finders –

Respuesta

5

La respuesta más simple es "no", la única manera de garantizar en general que Object#method(:foo) devolverá una instancia de Method es mediante la definición de un método denominado foo en el objeto.

La respuesta más compilada es que puede forzar Object#method(:foo) para devolver una instancia de Method anulando Object#respond_to_missing? s.t. devuelve true cuando se le da :foo. Por ejemplo:

class User 
    def respond_to_missing?(method_name, include_private = false) 
    method_name.to_s.start_with?('find_by_') 
    end 
end 

m = User.new.method(:find_by_hackish_means) 
# => #<Method: User#find_by_hackish_means> 

(Depende de usted para asegurarse de que el método está definido en realidad):

m.call 
# => NoMethodError: undefined method `find_by_hackish_means' for #<User:0x123> 
+2

Aquí hay una publicación de blog más detallada sobre el tema: http://robots.thoughtbot.com/post/28335346416/always-define-respond-to-missing- when-overriding – pje

+1

+1. Entonces, realmente es culpa de Rails que no funciona. Empecé a solucionarlo en ese sentido, p. https://github.com/rails/rails/pull/6169 –

+0

Bien, eso tiene sentido. Y @ Marc-AndréLafortune, usted respondió mi pregunta que inmediatamente tuve en respuesta a esta respuesta. :) Gracias a ambos! –

Cuestiones relacionadas