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_locationdevuelve 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_methodel 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_locationvuelvenil.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 => nilVer también:
fuente
source. Esto funciona como se esperaba.[1] pry(main)> RSpec.method(:class_exec).sourceMethodSource::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_locationaunque 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
Methodclase:# ~/.irbrc class Method def source(limit=10) file, line = source_location if file && line IO.readlines(file)[line-1,limit] else nil end end endY luego solo llama
method.sourceCon palanca , puede usar
show-methodpara ver la fuente de un método, e incluso puede ver un código fuente de ruby cpry-docinstalado, según el documento de pry en codde-browingfuente
sourcemétodo dentro de laMethodclase. 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_locationy 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_locationfuente