Saya ingin tahu apakah saya bisa mendapatkan kode sumber suatu metode dengan cepat, dan apakah saya bisa mendapatkan file mana dengan metode ini.
Suka
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Jawaban:
Penggunaan 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"
Perhatikan bahwa untuk metode bawaan, source_locationmengembalikan nil. Jika ingin memeriksa kode sumber C (selamat bersenang-senang!), Anda harus mencari file C yang tepat (mereka kurang lebih diatur berdasarkan kelas) dan menemukan rb_define_methodmetode untuk (menjelang akhir file ).
Di Ruby 1.8 metode ini tidak ada, tetapi Anda dapat menggunakan permata ini .
Sejauh ini tidak ada jawaban yang menunjukkan cara menampilkan kode sumber dari suatu metode dengan cepat ...
Sebenarnya sangat mudah jika Anda menggunakan permata 'method_source' yang mengagumkan dari John Mair (pembuat Pry): Metode ini harus diimplementasikan di Ruby (bukan C), dan harus dimuat dari file (bukan irb).
Berikut adalah contoh yang menampilkan kode sumber metode di konsol Rails dengan 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
Lihat juga:
source. Ini bekerja seperti yang diharapkan.
[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_locationbekerja dengan baik meskipun
Berikut adalah cara mencetak kode sumber dari ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
Tanpa ketergantungan
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]
Jika Anda ingin menggunakan ini lebih nyaman, Anda dapat membuka Methodkelas:
# ~/.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
Dan kemudian panggil saja method.source
Dengan Pry Anda dapat menggunakan show-methoduntuk melihat sumber metode, dan Anda bahkan dapat melihat beberapa kode sumber ruby c dengan pry-docdiinstal, menurut dokumen pry di codde-browing
Perhatikan bahwa kita juga dapat melihat metode C (dari Ruby Core) menggunakan plugin pry-doc; kami juga memamerkan sintaks alternatif untuk metode-pertunjukan:
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; }
sourcemetode di dalam Methodkelas. Akan lebih baik lagi jika teks itu diproses dan baru kapan harus berhenti mencetak karena sudah mencapai akhir metode.
Saya membuat permata "ri_for" untuk tujuan ini
>> require 'ri_for'
>> A.ri_for :foo
... mengeluarkan sumber (dan lokasi, jika Anda menggunakan 1.9).
GL. -r
Saya harus menerapkan fitur serupa (ambil sumber blok) sebagai bagian dari Salah dan Anda dapat melihat bagaimana (dan bahkan mungkin menggunakan kembali kode) di chunk.rb (yang bergantung pada RubyParser Ryan Davis dan juga beberapa yang cukup lucu kode sumber file glomming ). Anda harus memodifikasinya untuk digunakan Method#source_locationdan mungkin mengubah beberapa hal lain sehingga ada atau tidak termasuk file def.
BTW Saya pikir Rubinius memiliki fitur bawaan ini. Untuk beberapa alasan fitur ini telah ditinggalkan dari MRI (implementasi Ruby standar), karenanya hack ini.
Oooh, saya suka beberapa item di method_source ! Seperti menggunakan eval untuk mengetahui apakah ekspresi itu valid (dan terus glomming baris sumber sampai Anda berhenti mendapatkan kesalahan parse, seperti Chunk) ...
String#include?. Sejauh iniString.instance_method(:include?).source_locationkembalinil.