105 votes

Comment puis-je obtenir le code source d'une méthode de façon dynamique et aussi dans quel fichier se trouve cette méthode ?

Je voudrais savoir si je peux obtenir le code source d'une méthode à la volée, et si je peux obtenir dans quel fichier se trouve cette méthode.

comme

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

144voto

Marc-André Lafortune Points 34140

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"

Notez que pour les méthodes intégrées, source_location renvoie à nil . Si vous voulez consulter le code source C (amusez-vous bien !), vous devrez chercher le bon fichier C (ils sont plus ou moins organisés par classe) et trouver le fichier rb_define_method pour la méthode (vers la fin du fichier).

En Ruby 1.8 cette méthode n'existe pas, mais vous pouvez utiliser cette pierre précieuse .

5 votes

Bonjour, je viens du futur, j'utilise Ruby 2.6.1 ! Je veux le code source de String#include? . Jusqu'à présent String.instance_method(:include?).source_location renvoie à nil .

1 votes

@S.Goswami Un peu tard ici, mais l'implémentation de la fonction String#include? est en C, et l'introspection des sources en C n'est pas supportée en Ruby. Ce n'est pas une question de version de Ruby. Voir le code source ici : rubydoc.info/stdlib/core/String:include%3F

43voto

Tilo Points 13833

Aucune des réponses jusqu'ici ne montre comment afficher le code source d'une méthode à la volée...

En fait, c'est très facile si vous utilisez l'impressionnante gemme 'method_source' de John Mair (le créateur de Pry) : La méthode doit être implémentée en Ruby (pas en C), et doit être chargée depuis un fichier (pas irb).

Voici un exemple d'affichage du 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 aussi :

1 votes

Cette fonctionnalité m'a toujours manqué dans Ruby. Lisp peut le faire :)

0 votes

Venant de l'initiative de Clojure source . Cela fonctionne comme prévu.

0 votes

Je reçois cette erreur : [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'

17voto

Cort3z Points 1657

Voici comment imprimer le code source à partir de ruby :

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

4voto

rogerdpack Points 12806

J'ai créé la gemme "ri_for" dans ce but

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

... sort la source (et l'emplacement, si vous êtes en 1.9).

GL. -r

0 votes

Tout ce que cela fait pour moi est de produire un défaut de segmentation :(

0 votes

Comment reproduire le défaut seg ? quelle méthode/classe ?

1voto

AlexChaffee Points 2979

J'ai dû implémenter une fonctionnalité similaire (saisir la source d'un bloc) dans le cadre de l'application de l'outil de gestion de l'information. Mauvais et vous pouvez voir comment (et peut-être même réutiliser le code) en chunk.rb (qui s'appuie sur le RubyParser de Ryan Davis ainsi que sur un fichier source plutôt amusant). code de glaçage ). Vous devrez le modifier pour utiliser Method#source_location et peut-être modifier d'autres choses pour qu'elle inclue ou non le def .

D'ailleurs, je pense que Rubinius a cette fonctionnalité intégrée. Pour une raison quelconque, elle a été laissée de côté dans MRI (l'implémentation standard de Ruby), d'où ce hack.

Oooh, j'aime certaines des choses dans méthode_source ! Comme utiliser eval pour savoir si une expression est valide (et continuez à glommer des lignes de source jusqu'à ce que vous arrêtiez de recevoir des erreurs de parse, comme le fait Chunk)...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X