Câu trả lời:
Sử dụng 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"
Lưu ý rằng đối với các phương thức nội trang, source_location
trả về nil
. Nếu muốn kiểm tra mã nguồn C (chúc bạn vui vẻ!), Bạn sẽ phải tìm đúng tệp C (chúng ít nhiều được sắp xếp theo lớp) và tìm rb_define_method
phương thức (ở cuối tệp ).
Trong Ruby 1.8, phương thức này không tồn tại, nhưng bạn có thể sử dụng gem này .
Cho đến nay, không có câu trả lời nào cho thấy cách hiển thị mã nguồn của một phương thức một cách nhanh chóng ...
Nó thực sự rất dễ dàng nếu bạn sử dụng đá quý 'method_source' tuyệt vời của John Mair (người tạo ra Pry): Phương thức này phải được triển khai bằng Ruby (không phải C) và phải được tải từ một tệp (không phải irb).
Dưới đây là một ví dụ hiển thị mã nguồn phương thức trong bảng điều khiển Rails với 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
Xem thêm:
source
. Điều này hoạt động như mong đợi.
[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
hoạt động tốt mặc dù
Đây là cách in mã nguồn từ ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
Không có phụ thuộc
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]
Nếu bạn muốn sử dụng tiện lợi hơn, bạn có thể mở Method
lớp:
# ~/.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
Và sau đó chỉ cần gọi method.source
Với Pry, bạn có thể sử dụng show-method
để xem nguồn phương thức và thậm chí bạn có thể xem một số mã nguồn ruby c pry-doc
đã được cài đặt, theo tài liệu của pry trong codde-Browing
Lưu ý rằng chúng ta cũng có thể xem các phương thức C (từ Ruby Core) bằng cách sử dụng plugin pry-doc; chúng tôi cũng hiển thị cú pháp thay thế cho phương thức hiển thị:
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
phương thức bên trong Method
lớp. Sẽ tốt hơn nữa nếu nó xử lý văn bản và thời điểm dừng in mới vì nó đã đến cuối phương pháp.
Tôi đã tạo đá quý "ri_for" cho mục đích này
>> require 'ri_for'
>> A.ri_for :foo
... xuất ra nguồn (và vị trí, nếu bạn đang ở 1.9).
GL. -r
Tôi đã phải triển khai một tính năng tương tự (lấy nguồn của khối) như một phần của Wrong và bạn có thể thấy cách (và thậm chí có thể sử dụng lại mã) trong chunk.rb (dựa trên RubyParser của Ryan Davis cũng như một số khá hài hước mã glomming tập tin nguồn ). Bạn sẽ phải sửa đổi nó để sử dụng Method#source_location
và có thể điều chỉnh một số thứ khác để nó có hoặc không bao gồm def
.
BTW Tôi nghĩ rằng Rubinius đã tích hợp sẵn tính năng này. Vì một số lý do, nó đã bị loại khỏi MRI (triển khai Ruby tiêu chuẩn), do đó có vụ hack này.
Ồ, tôi thích một số nội dung trong method_source ! Giống như sử dụng eval để cho biết một biểu thức có hợp lệ hay không (và giữ nguyên các dòng nguồn cho đến khi bạn ngừng nhận được lỗi phân tích cú pháp, như Chunk đã làm) ...
String#include?
. Cho đến nayString.instance_method(:include?).source_location
trở lạinil
.