Chciałbym wiedzieć, czy mogę uzyskać kod źródłowy metody w locie i czy mogę uzyskać plik, w którym znajduje się ta metoda.
lubić
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Zastosowanie 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"
Zwróć uwagę, że w przypadku metod wbudowanych source_location
zwraca nil
. Jeśli chcesz sprawdzić kod źródłowy C (baw się dobrze!), Musisz poszukać odpowiedniego pliku C (są one mniej więcej uporządkowane według klas) i znaleźć rb_define_method
metodę (pod koniec pliku ).
W Ruby 1.8 ta metoda nie istnieje, ale możesz użyć tego klejnotu .
String#include?
. Jak dotądString.instance_method(:include?).source_location
wracanil
.Żadna z dotychczasowych odpowiedzi nie pokazuje, jak wyświetlić kod źródłowy metody w locie ...
W rzeczywistości jest to bardzo proste, jeśli użyjesz niesamowitego klejnotu „method_source” Johna Maira (twórcy Pry): Metoda musi być zaimplementowana w Rubim (nie C) i musi zostać załadowana z pliku (nie irb).
Oto przykład wyświetlania kodu źródłowego metody w konsoli Railsów z 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
Zobacz też:
źródło
source
. Działa to zgodnie z oczekiwaniami.[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
działa dobrzeOto jak wydrukować kod źródłowy z ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
źródło
Bez zależności
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]
Jeśli chcesz korzystać z tego wygodniej, możesz otworzyć
Method
klasę:# ~/.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
A potem po prostu zadzwoń
method.source
Z Pry możesz użyć
show-method
do wyświetlenia źródła metody, a nawet możesz zobaczyć kod źródłowy ruby c zpry-doc
zainstalowanym, zgodnie z dokumentacją pry'a w codde-browingźródło
source
metodę wewnątrzMethod
klasy. Byłoby jeszcze lepiej, gdyby przetwarzał tekst i nowy, kiedy przerwać drukowanie, ponieważ doszedł do końca metody.W tym celu stworzyłem gem „ri_for”
>> require 'ri_for' >> A.ri_for :foo
... wyświetla źródło (i lokalizację, jeśli jesteś na 1.9).
GL. -r
źródło
Musiałem zaimplementować podobną funkcję (pobrać źródło bloku) jako część Wrong i możesz zobaczyć, jak (a może nawet ponownie użyć kodu) w chunk.rb (który opiera się na RubyParserze Ryana Davisa, a także całkiem zabawnych kod źródłowy pliku glomming ). Musisz go zmodyfikować, aby użyć
Method#source_location
i być może dostosować kilka innych rzeczy, aby zawierał lub nie zawierałdef
.BTW Myślę, że Rubinius ma wbudowaną tę funkcję. Z jakiegoś powodu została pominięta w MRI (standardowa implementacja Rubiego), stąd ten hack.
Oooh, podoba mi się niektóre rzeczy w method_source ! Podobnie jak używanie eval do stwierdzenia, czy wyrażenie jest prawidłowe (i kontynuuj przeglądanie wierszy źródłowych, dopóki nie przestaniesz otrzymywać błędów analizy, jak robi to Chunk) ...
źródło
Metody wewnętrzne nie mają źródła ani lokalizacji źródłowej (np.
Integer#to_s
)require 'method_source' User.method(:last).source User.method(:last).source_location
źródło