2010-01-06 8 views
6

Tenemos el código para registrar datos en nuestra aplicación web Ruby 1.8.6. Usted lo llama más o menos de la siguiente manera:Obtener el módulo de la persona que llama en Ruby

$log.info("Some text here") 

Ahora, en la salida conectado, me gustaría incluir el módulo en el que apareció esa línea. Sé que el Kernel#caller me dará una matriz en la que puedo extraer el archivo y el número de línea en que se produjo la línea de registro, pero no quiero eso. Quiero el módulo, no el nombre del archivo. La solución obvia es modificar la línea de registro de manera que se lee como:

$log.info("Some text here", self.class.name) 

y luego analizar el resultado. Sin embargo, eso no va a funcionar, porque estoy tratando de extraer esta información en el caso predeterminado. Es decir, necesito que la solución funcione si el programador olvidó especificar el módulo, el segundo parámetro para la línea de registro.

¿Hay alguna manera de hacer esto? De lo contrario, tendré que conformarme con la matriz caller; la mayoría de nuestros módulos están en directorios separados, por lo que esta sería una solución al 80%.

más completo ejemplo, disculpen los errores sintácticos mínimos:

en log.rb archivo:

module Log 
    class Logger 
    def info(msg, mod = '') 
     puts "Module: #{mod} Msg: #{msg}" 
    end 
    end # class Logger 
end # module Log 
$log = Log::Logger.new 

en foo.rb archivo:

module Foo 
    class Bar 
    def do_something 
     # Do not pass in self.class.name. 
     # We want the output to look like: 
     # Module: Foo Msg: I did something! 
     $log.info "I did something!" 
    end 
    end # class Bar 
end #module Foo 
+0

No veo cómo puede hacerlo, a menos que pase 'self' o' binding' al objeto logger. Tendría que analizar el archivo con la información de 'calller', que estoy seguro que no desea hacer. –

Respuesta

3

Uso call_stack.

instala por primera vez con RubyGems:

gem install call_stack 

a continuación, cambiar a log.rb:

require 'rubygems' 
require 'call_stack' 

call_stack_on 

module Log 
    class Logger 
    def info(msg, mod = '') 
     mod = call_stack(2)[0][0] if mod == '' 
     puts "Module: #{mod} Msg: #{msg}" 
    end 
    end # class Logger 
end # module Log 
$log = Log::Logger.new 

funciona para mí (rubí 1.8.7).

$ ruby foo.rb 
Module: Foo::Bar Msg: I did something! 
+0

Según su sitio, queremos usar ruby-debug en su lugar, aunque los enlaces aparecen rotos. También señala que esto implica una desaceleración sustancial. De hecho, puede que ni siquiera funcione. Aún así, la mejor solución hasta ahora, así que estoy +1 en esta respuesta. Gracias. – ChrisInEdmonton

+0

Aquí está ruby-debug: http://rubyforge.org/projects/ruby-debug/, y sí, sería lento. El soporte predeterminado de Ruby para la inspección de callstack es patético y ha habido numerosas sugerencias para mejorarlo, así que todo lo que obtiene es Kernel # caller. Cualquier solución implicaría trazar o trabajar con la API, por lo que representé lo que parece ser el más simple. Sugiero que si realmente necesita esta funcionalidad, aplique una convención de codificación y siempre los programadores especifiquen el módulo al llamar (sin valor predeterminado). Inconveniente, pero rápido. O puede desactivar call_stack cuando no esté depurando. –

2

Encontré esta publicación mientras buscaba una respuesta para mis propios fines.

No encontré uno que fuera apropiado, así que busqué la fuente de Ruby y armé una extensión. Me he liado como una joya- debe instalar sin ningún problema siempre y cuando se está utilizando de Ruby 1.9.1: joya

sudo instalar emisor

Esto no va a funcionar con Ruby 1.8 , ya que 1.8 tiene un modelo diferente para rastrear marcos.

http://rubygems.org/gems/sender

3

Un mixin resuelve los requisitos específicos de la OP (por su parte, 1 a Asher para resolver el genérico "que me llamó" caso!).

module Log 
    module Logger 
    def info(msg) 
     puts "Module: #{self} Msg: #{msg}" 
    end 
    end # class Logger 
end # module Log 

module Foo 
    class Bar 
    include Log::Logger 
    def do_something 
     # Do not pass in self.class.name. 
     # We want the output to look like: 
     # Module: Foo Msg: I did something! 
     info "I did something!" 
    end 
    end # class Bar 
end # module Foo 

foobar = Foo::Bar.new 
foobar.do_something 
Cuestiones relacionadas