मैं एक विधि के स्रोत कोड को गतिशील रूप से कैसे प्राप्त कर सकता हूं और यह भी कि यह विधि किस फ़ाइल में है


89

मैं जानना चाहूंगा कि क्या मुझे मक्खी पर स्रोत कोड एक विधि मिल सकती है, और क्या मुझे यह पता चल सकता है कि यह विधि किस फ़ाइल में है।

पसंद

A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE

जवाबों:


116

उपयोग करें 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"

ध्यान दें कि बिलियन तरीकों के लिए, source_locationरिटर्न nil। यदि आप C स्रोत कोड की जाँच करना चाहते हैं (मज़े करना चाहते हैं!), तो आपको सही C फ़ाइल (वे वर्ग द्वारा कम या ज्यादा व्यवस्थित की गई है) ढूंढनी होगी और rb_define_methodविधि की खोज करनी होगी (फ़ाइल के अंत की ओर) )।

रूबी 1.8 में यह विधि मौजूद नहीं है, लेकिन आप इस रत्न का उपयोग कर सकते हैं ।


2
हाय, मैं भविष्य से हूं, रूबी 2.6.1 का उपयोग कर! मुझे सोर्स कोड चाहिए String#include?। अब तक String.instance_method(:include?).source_locationरिटर्न nil
एस। गोस्वामी

39

अब तक कोई भी जवाब नहीं दिखा कि मक्खी पर किसी विधि का स्रोत कोड कैसे दिखाया जाए ...

यह वास्तव में बहुत आसान है यदि आप जॉन मैयर (प्र्री के निर्माता) द्वारा भयानक 'method_source' मणि का उपयोग करते हैं: विधि को रूबी (सी नहीं) में लागू किया जाना है, और एक फ़ाइल से लोड किया जाना है (irb नहीं)।

यहाँ एक उदाहरण है जो मेथड्स सोर्स कोड को मेथड्स कोड कोड मे मेथ्स_सोर्स के साथ प्रदर्शित करता है:

  $ 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 

यह सभी देखें:


1
मैं हमेशा रूबी में इस सुविधा को याद करता था। लिस्प यह कर सकते हैं :)
तिलो

क्लोजर से आ रहा है source। यह उम्मीद के मुताबिक काम करता है।
सेबस्टियन पाल्मा

मुझे यह त्रुटि मिलती है: [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हालांकि ठीक काम करता है
अब्राम

17

माणिक से सोर्स कोड को प्रिंट करने का तरीका इस प्रकार है:

puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])

10

बिना निर्भरता के

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]

यदि आप इसे और अधिक आसानी से उपयोग करना चाहते हैं, तो आपका Methodवर्ग खुल सकता है :

# ~/.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

और फिर कॉल करें method.source

Pry के साथ आप show-methodएक विधि स्रोत को देखने के लिए उपयोग कर सकते हैं , और आप कोडी-ब्राउनिंगpry-doc में pry के डॉक्टर के अनुसार कुछ रूबी c स्रोत कोड भी देख सकते हैं

ध्यान दें कि हम प्रि-डॉक प्लगइन का उपयोग करके सी तरीके (रूबी कोर से) भी देख सकते हैं; हम शो-विधि के लिए वैकल्पिक सिंटैक्स भी दिखाते हैं:

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अंदर एक विधि के लिए यह एक महान विचार है Method। यह बेहतर होगा यदि यह मुद्रण को रोकने के लिए पाठ और नए को संसाधित करता है क्योंकि यह विधि के अंत तक पहुंच गया है।
टॉबी 1 केनोबी

4

मैंने इस उद्देश्य के लिए "ri_for" रत्न बनाया

 >> require 'ri_for'
 >> A.ri_for :foo

... स्रोत का उत्पादन (और स्थान, यदि आप 1.9 पर हैं)।

जीएल। -r


यह सब मेरे लिए एक विभाजन दोष पैदा कर रहा है। :(
पँजी

कैसे सीजी गलती को पुन: पेश करने के लिए? कौन सी विधि / वर्ग?
रोज़गारपैक

1

मुझे रोंग के हिस्से के रूप में एक समान विशेषता (ब्लॉक के स्रोत को पकड़ो) को लागू करना था और आप देख सकते हैं कि chunk.rb में (और शायद कोड का पुन: उपयोग कैसे किया जा सकता है) (जो कि रयान डेविस के रूबीपैरर्स पर निर्भर करता है ) स्रोत फ़ाइल glomming कोड )। आपको इसका उपयोग करने के लिए इसे संशोधित करना होगा Method#source_locationऔर हो सकता है कि कुछ अन्य चीजों को मोड़ दिया जाए ताकि यह इसमें शामिल न हो या इसमें शामिल न हो def

BTW मुझे लगता है कि रुबिनियस में इस सुविधा का निर्माण किया गया है। किसी कारण से इसे एमआरआई (मानक रूबी कार्यान्वयन) से छोड़ दिया गया है, इसलिए यह हैक।

Oooh, मुझे method_source में कुछ सामान पसंद हैं ! जैसे कि यह बताने के लिए कि क्या कोई अभिव्यक्ति वैध है (और जब तक आप चेस नहीं करते हैं, तो पार्स त्रुटियों को रोकना बंद कर देते हैं, तब तक स्रोत लाइनों को चमकते रहें ...)


1

आंतरिक विधियों में स्रोत या स्रोत स्थान नहीं है (उदाहरण के लिए Integer#to_s)

require 'method_source'
User.method(:last).source
User.method(:last).source_location
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.