2010-08-03 8 views

risposta

77

Uso 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" 

si tratta di una novità per Ruby 1.9, però. Per Ruby 1.8, è possibile utilizzare this gem e copierò questo codice su backports quando ottengo un secondo.

3

ho creato la gemma "ri_for" per questo scopo

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

... la diffusione della sorgente (e la posizione, se siete su 1.9).

GL. -r

+0

si vuol dire questo http://github.com/rdp/ri_for – allenwei

+0

sì che è il pronti contro termine per esso – rogerdpack

+0

Tutto questo non fa per me è la produzione un errore di segmentazione. :( – panzi

29

Nessuna delle risposte mostrano finora come visualizzare il codice sorgente di un metodo al volo ...

In realtà è molto semplice se si utilizza il 'method_source' gioiello impressionante da John Mair (il creatore di Pry): Il metodo deve essere implementato in Ruby (non C) e deve essere caricato da un file (non irb).

Ecco un esempio che visualizza il codice sorgente metodo nella console Rails con 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 

Vedi anche:

+0

Ho sempre perso questa funzione in Ruby. Lisp può farlo :) – Tilo

1

Ho dovuto implementare una funzione simile (prendi il codice sorgente di un blocco) come parte di Wrong e puoi vedere come (e forse anche riutilizzare il codice) in chunk.rb (che si basa su RubyParser di Ryan Davis e anche piuttosto divertente file sorgente glomming code). Dovresti modificarlo per usare Method#source_location e forse modificare alcune altre cose così fa o non include lo def.

BTW Penso che Rubinius abbia questa funzionalità integrata. Per qualche motivo è stato escluso dalla risonanza magnetica (l'implementazione standard di Ruby), quindi questo hack.

Oooh, mi piacciono alcune delle cose in method_source! Come using eval to tell if an expression is valid (e mantenere glomming righe di origine fino a quando si smette di ottenere errori di analisi, come Chunk fa) ...

12

Ecco come stampare il codice sorgente dal rubino:

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

metodi interni non lo fanno avere la fonte o la posizione (esInteger#to_s)

require 'method_source' 
User.method(:last).source 
User.method(:last).source_location 
0

Senza dipendenze

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] 

Se si desidera utilizzare questo più convenientemente, il vostro possibile aprire la classe 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 

E poi basta chiamare method.source

Con leva è possibile utilizzare la show-method per visualizzare una fonte di metodo, e si può anche vedere qualche codice rosso rubino c sorgente con pry-doc installato, secondo doc di curiosare in codde-browing

Nota che possiamo anche vedere i metodi C (da Ruby Core) utilizzando il plug-in pry-doc ; abbiamo anche mostrare la sintassi alternativa per lo show-metodo:

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; 
} 
Problemi correlati