Anında bir yöntem kaynak kodu alıp alamayacağımı ve bu yöntemin hangi dosyaya ulaşıp ulaşamayacağını bilmek istiyorum.
sevmek
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Yanıtlar:
Kullanım 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"
Yerleşik yöntemler için source_locationdöndüğünü unutmayın nil. C kaynak kodunu kontrol etmek istiyorsanız (iyi eğlenceler!), Doğru C dosyasını aramanız (aşağı yukarı sınıfa göre düzenlenmiştir) ve rb_define_methodyöntemi bulmanız gerekir (dosyanın sonuna doğru) ).
Ruby 1.8'de bu yöntem yoktur, ancak bu mücevheri kullanabilirsiniz .
Şimdiye kadarki yanıtların hiçbiri, bir yöntemin kaynak kodunun anında nasıl görüntüleneceğini göstermiyor ...
John Mair'in (Pry'nin yapımcısı) harika 'method_source' mücevherini kullanırsanız, aslında çok kolaydır: Yöntem Ruby'de uygulanmalıdır (C değil) ve bir dosyadan (irb değil) yüklenmelidir.
Method_source ile Rails konsolundaki yöntem kaynak kodunu görüntüleyen bir örnek:
$ 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
Ayrıca bakınız:
source. Bu beklendiği gibi çalışıyor.
[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_locationyine de iyi çalışıyor
Ruby'den kaynak kodunu şu şekilde yazdırabilirsiniz:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
Bağımlılıklar olmadan
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]
Bunu daha rahat kullanmak isterseniz Methodsınıfı açabilirsiniz :
# ~/.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
Ve sonra sadece ara method.source
Pry ileshow-method bir yöntem kaynağını görüntülemek için kullanabilirsiniz ve hatta kodda pry-docgöz atma belgesine göre , yüklü bir Ruby c kaynak kodunu bile görebilirsiniz.
Ayrıca pry-doc eklentisini kullanarak C yöntemlerini (Ruby Core'dan) görüntüleyebileceğimizi unutmayın; show-method için alternatif sözdizimini de gösteriyoruz:
pry(main)> show-method Array#select From: array.c in Ruby Core (C Method): Number of lines: 15 static VALUE rb_ary_select(VALUE ary) { VALUE result; long i; RETURN_ENUMERATOR(ary, 0, 0); result = rb_ary_new2(RARRAY_LEN(ary)); for (i = 0; i < RARRAY_LEN(ary); i++) { if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) { rb_ary_push(result, rb_ary_elt(ary, i)); } } return result; }
source, Methodsınıfın içindeki bir yöntem için harika bir fikir . Metni işlese ve yöntemin sonuna geldiği için yazdırmayı ne zaman durdurması gerektiğini yenerse daha da iyi olurdu.
Bu amaçla "ri_for" mücevherini yarattım
>> require 'ri_for'
>> A.ri_for :foo
... kaynağı (ve 1.9'daysanız konumu) verir.
GL. -r
Ben bir parçası olarak benzer bir özellik (kapmak bir bloğun kaynağı) uygulamak zorunda Yanlış ve içinde (hatta kodu yeniden ve belki) nasıl görebilirsiniz chunk.rb oldukça komik bazı yanı sıra Ryan Davis' RubyParser dayanır ( kaynak dosyası glomming kodu ). Kullanmak için değiştirmeniz Method#source_locationve belki başka şeyler üzerinde ince ayar yapmanız gerekir, böylece def.
BTW Bence Rubinius bu özelliğe sahip. Nedense MRI (standart Ruby uygulaması) dışında bırakıldı, dolayısıyla bu hack.
Oooh, method_source'daki bazı şeyleri beğendim ! Bir ifadenin geçerli olup olmadığını söylemek için eval kullanmak gibi (ve Chunk'ın yaptığı gibi, ayrıştırma hataları almayı bırakana kadar kaynak satırlarını parlatmaya devam edin) ...
String#include?. Şimdiye kadarString.instance_method(:include?).source_locationgeri dönüyornil.