Je voudrais savoir si je peux obtenir le code source d’une méthode à la volée et si je peux savoir dans quel fichier se trouve cette méthode.
comme
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Utilisez 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"
C'est nouveau pour Ruby 1.9, cependant. Pour Ruby 1.8, vous pouvez utiliser ce bijou , et je recopierai ce code dans backports
dès que j'aurai une seconde.
Jusqu'à présent, aucune des réponses n'a montré comment afficher le code source d'une méthode à la volée ...
C'est en fait très facile si vous utilisez l'impressionnant bijou 'method_source' de John Mair (le fabricant de Pry): La méthode doit être implémentée dans Ruby (pas C) ).
Voici un exemple affichant le code source de la méthode dans la console Rails avec 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
Voir également:
Voici comment imprimer le code source de Ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
Sans dépendances
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]
Si vous voulez utiliser ceci plus facilement, vous pouvez ouvrir 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
Et ensuite, appelez simplement method.source
Avec Pry, vous pouvez utiliser le show-method
pour afficher une source de méthode. Vous pouvez même voir du code source Ruby c avec pry-doc
installé, selon la documentation de pry dans codde-browing
Notez que nous pouvons également afficher les méthodes C (à partir de Ruby Core) à l’aide de pry-doc plugin; nous montrons également la syntaxe alternative pour show-method:
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; }
J'ai créé le joyau "ri_for" à cet effet
>> require 'ri_for'
>> A.ri_for :foo
... affiche la source (et l'emplacement, si vous êtes sur 1.9).
GL .- r
J'ai dû implémenter une fonctionnalité similaire (saisir la source d'un bloc) dans Wrong et vous pouvez voir comment (et peut-être même réutiliser le code) dans chunk.rb (qui s'appuie sur Ryan Davis 'RubyParser ainsi que des fichiers source assez drôles glomming code ). Vous devrez le modifier pour utiliser Method#source_location
et peut-être modifier quelques autres choses afin d’inclure ou non la def
.
BTW Je pense que Rubinius a cette fonctionnalité intégrée. Pour une raison quelconque, elle n’a pas été laissée dans l’IRM (implémentation standard de Ruby), d’où ce hack.
Oooh, j'aime certaines choses dans method_source ! Comme utiliser eval pour indiquer si une expression est valide (et garder les lignes sources vantées jusqu'à ce que vous n'ayez plus d'erreur d'erreur d'analyse, comme le fait Chunk) ...
Les méthodes internes n'ont pas de source ou d'emplacement source (par exemple, Integer#to_s
)
require 'method_source'
User.method(:last).source
User.method(:last).source_location