Me gustaría saber si puedo obtener el código fuente de un método sobre la marcha, y si puedo obtener en qué archivo se encuentra este método.
me gusta
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Utilizar source_location
:
class A
def foo
end
end
file, line = A.instance_method(:foo).source_location
# or
file, line = A.new.method(:foo).source_location
puts "Method foo is defined in #{file}, line #{line}"
# => "Method foo is defined in temp.rb, line 2"
Tenga en cuenta que, para los métodos integrados, source_location
devuelve nil
. Si desea consultar el código fuente de C (¡diviértase!), Tendrá que buscar el archivo C correcto (están más o menos organizados por clase) y encontrar rb_define_method
el método (hacia el final del archivo ).
En Ruby 1.8 este método no existe, pero puedes usar esta gema .
String#include?
. Hasta ahoraString.instance_method(:include?).source_location
vuelvenil
.Ninguna de las respuestas hasta ahora muestra cómo mostrar el código fuente de un método sobre la marcha ...
En realidad, es muy fácil si usa la increíble gema 'method_source' de John Mair (el creador de Pry): el método debe implementarse en Ruby (no en C) y debe cargarse desde un archivo (no irb).
Aquí hay un ejemplo que muestra el código fuente del método en la consola de Rails con method_source:
$ rails console > require 'method_source' > I18n::Backend::Simple.instance_method(:lookup).source.display def lookup(locale, key, scope = [], options = {}) init_translations unless initialized? keys = I18n.normalize_keys(locale, key, scope, options[:separator]) keys.inject(translations) do |result, _key| _key = _key.to_sym return nil unless result.is_a?(Hash) && result.has_key?(_key) result = result[_key] result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol) result end end => nil
Ver también:
fuente
source
. Esto funciona como se esperaba.[1] pry(main)> RSpec.method(:class_exec).source
MethodSource::SourceNotFoundError: Could not locate source for class_exec!
from /home/vagrant/.bundle/foo/ruby/2.5.0/gems/method_source-0.9.2/lib/method_source.rb:24:in `source_helper'
RSpec.method(:to_json).source_location
aunque funciona bienA continuación se explica cómo imprimir el código fuente de ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
fuente
Sin dependencias
method = SomeConstant.method(:some_method_name) file_path, line = method.source_location # puts 10 lines start from the method define IO.readlines(file_path)[line-1, 10]
Si desea usar esto de manera más conveniente, puede abrir la
Method
clase:# ~/.irbrc class Method def source(limit=10) file, line = source_location if file && line IO.readlines(file)[line-1,limit] else nil end end end
Y luego solo llama
method.source
Con palanca , puede usar
show-method
para ver la fuente de un método, e incluso puede ver un código fuente de ruby cpry-doc
instalado, según el documento de pry en codde-browingfuente
source
método dentro de laMethod
clase. Sería incluso mejor si procesara el texto y cuándo dejar de imprimir porque llegó al final del método.Creé la gema "ri_for" para este propósito
>> require 'ri_for' >> A.ri_for :foo
... genera la fuente (y la ubicación, si está en 1.9).
GL. -r
fuente
Tuve que implementar una función similar (tomar la fuente de un bloque) como parte de Wrong y puedes ver cómo (y tal vez incluso reutilizar el código) en chunk.rb (que se basa en RubyParser de Ryan Davis, así como en algunos bastante divertidos código glomming del archivo fuente ). Tendrías que modificarlo para usarlo
Method#source_location
y tal vez ajustar algunas otras cosas para que incluya o no eldef
.Por cierto, creo que Rubinius tiene esta función incorporada. Por alguna razón, se ha dejado fuera de MRI (la implementación estándar de Ruby), de ahí este truco.
¡Oooh, me gustan algunas de las cosas en method_source ! Como usar eval para saber si una expresión es válida (y seguir glomming líneas fuente hasta que deje de recibir errores de análisis, como lo hace Chunk) ...
fuente
Los métodos internos no tienen origen ni ubicación de origen (p
Integer#to_s
. Ej. )require 'method_source' User.method(:last).source User.method(:last).source_location
fuente