2008-10-23 4 views
33

Je suis nouveau à Ruby et je joue avec l'IRB.Comment lister les objets actuellement disponibles dans la portée actuelle dans ruby?

Je trouve que je peux énumérer les méthodes d'un objet en utilisant la méthode « .methods », et que self.methods sorte de me donner ce que je veux (semblable à dir Python (builtins)?), Mais comment Je trouve les méthodes d'une bibliothèque/module que j'ai chargé via include et require?

irb(main):036:0* self.methods 
=> ["irb_pop_binding", "inspect", "taguri", "irb_chws", "clone", "irb_pushws", "public_methods", "taguri=", "irb_pwws", 
"public", "display", "irb_require", "irb_exit", "instance_variable_defined?", "irb_cb", "equal?", "freeze", "irb_context 
", "irb_pop_workspace", "irb_cwb", "irb_jobs", "irb_bindings", "methods", "irb_current_working_workspace", "respond_to?" 
, "irb_popb", "irb_cws", "fg", "pushws", "conf", "dup", "cwws", "instance_variables", "source", "cb", "kill", "help", "_ 
_id__", "method", "eql?", "irb_pwb", "id", "bindings", "send", "singleton_methods", "popb", "irb_kill", "chws", "taint", 
"irb_push_binding", "instance_variable_get", "frozen?", "irb_source", "pwws", "private", "instance_of?", "__send__", "i 
rb_workspaces", "to_a", "irb_quit", "to_yaml_style", "irb_popws", "irb_change_workspace", "jobs", "type", "install_alias 
_method", "irb_push_workspace", "require_gem", "object_id", "instance_eval", "protected_methods", "irb_print_working_wor 
kspace", "irb_load", "require", "==", "cws", "===", "irb_pushb", "instance_variable_set", "irb_current_working_binding", 
"extend", "kind_of?", "context", "gem", "to_yaml_properties", "quit", "popws", "irb", "to_s", "to_yaml", "irb_fg", "cla 
ss", "hash", "private_methods", "=~", "tainted?", "include", "irb_cwws", "irb_change_binding", "irb_help", "untaint", "n 
il?", "pushb", "exit", "irb_print_working_binding", "is_a?", "workspaces"] 
irb(main):037:0> 

Je suis habitué à python, où j'utilise la fonction dir() pour accomplir la même chose:

>>> dir() 
['__builtins__', '__doc__', '__name__', '__package__'] 
>>> 

Répondre

0

Vous pouvez transmettre les messages .methods à la bibliothèque/module de même avant le chargement pour voir toutes les méthodes disponibles Faire self.methods renvoie juste toutes les méthodes que l'objet Object contient. Vous pouvez le voir en faisant self.class. Supposons que vous souhaitiez voir toutes les méthodes dans le module Fichier. Vous faites simplement File.methods et vous obtiendrez une liste de toutes les méthodes qui existent dans le module Fichier. Ce n'est peut-être pas ce que vous voulez, mais cela devrait être utile.

2

Pour accéder à toutes les instances d'objets en ruby ​​vous utilisez ObjectSpace

http://www.ruby-doc.org/core-1.8.7/classes/ObjectSpace.html#M000928

Cependant, cela est considéré comme lent (même pour le rubis), et ne peuvent pas être activés dans certains interprètes (par exemple JRuby peut désactiver ObjectSpace comme il est beaucoup plus rapide de se fier au jvm pour gc sans avoir besoin de suivre ce truc dans jRuby).

5

La méthode dir() est not clearly defined ...

Note: Parce que dir() est fourni principalement à titre de commodité pour une utilisation à une invite interactive, il tente de fournissent un ensemble intéressant de noms plus qu'il essaie de fournir un rigoureusement ou uniformément défini définir des noms, et son comportement détaillé peut changer d'une publication à l'autre.

... mais nous pouvons créer une approximation proche dans Ruby. Faisons une méthode qui retournera une liste triée de toutes les méthodes ajoutées à notre portée par les modules inclus. Nous pouvons obtenir une liste des modules qui ont été inclus en utilisant la méthode included_modules.

Comme dir(), nous voulons ignorer les méthodes "par défaut" (comme print), et nous voulons aussi nous concentrer sur l'ensemble des noms "intéressants". Donc, nous allons ignorer les méthodes dans Kernel, et nous ne retournerons que les méthodes qui ont été définies directement dans les modules, en ignorant les méthodes héritées. Nous pouvons accomplir le plus tard en passant false dans la méthode methods(). Tout mettre ensemble, nous obtenons ...

def included_methods(object=self) 
    object = object.class if object.class != Class 
    modules = (object.included_modules-[Kernel]) 
    modules.collect{ |mod| mod.methods(false)}.flatten.sort 
end 

Vous pouvez passer une classe, un objet, ou rien (valeur par défaut de la portée actuelle). Nous allons essayer ...

irb(main):006:0> included_methods 
=> [] 
irb(main):007:0> include Math 
=> Object 
irb(main):008:0> included_methods 
=> ["acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cos", "cosh", "erf", "erfc", "exp", "frexp", "hypot", "ldexp", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh"] 

dir() comprend également des variables définies localement, et c'est facile. Il suffit d'appeler ...

local_variables 

... malheureusement, nous ne pouvons pas simplement ajouter à included_methods appel local_variables parce qu'il nous donnerait les variables qui sont locales à la méthode included_methods, et ce ne serait pas très utile. Donc, si vous voulez les variables locales incluses avec les included_methods, appelez juste ...

(included_methods + local_variables).sort 
+0

ok, j'apprends lentement. Cela amène à ma prochaine question, quelle est la différence entre "inclure" et "exiger"? Je vais faire un peu de lecture, mais comment voir les méthodes qui ont été chargées via "require"? – monkut

+1

Un include ajoutera les constantes, les méthodes et les variables de module à la portée actuelle. Il est généralement utilisé pour ajouter des fonctionnalités à une classe. Un require charge un autre fichier ruby ​​(s'il n'a pas déjà été chargé). Si vous voulez le charger (même s'il est déjà chargé), utilisez plutôt la méthode "load". –

+0

Généralement, un fichier requis chargera une classe. Par exemple, require 'foo' chargera les classes Foo. Ainsi, vous pouvez obtenir une liste de méthodes dans cette classe en faisant Foo.methods (false). Si le fichier requis est juste un tas de méthodes: orig = Object.private_methods; exiger 'foo'; p Object.private_methods - orig –

39

Je ne suis pas tout à fait sûr de ce que vous entendez par les « objets actuels ». Vous pouvez itérer sur ObjectSpace, comme cela a déjà été mentionné. Mais voici quelques autres méthodes.

local_variables 
instance_variables 
global_variables 

class_variables 
constants 

Il y a un gotcha. Ils doivent être appelés aux bonnes portées. Donc, en plein CISR, ou dans une instance d'objet ou à la portée de la classe (donc partout, essentiellement), vous pouvez appeler le premier 3.

local_variables #=> ["_"] 
foo = "bar" 
local_variables #=> ["_", "foo"] 
# Note: the _ variable in IRB contains the last value evaluated 
_ #=> "bar" 

instance_variables #=> [] 
@inst_var = 42 
instance_variables #=> ["@inst_var"] 

global_variables #=> ["$-d", "$\"", "$$", "$<", "$_", ...] 
$"     #=> ["e2mmap.rb", "irb/init.rb", "irb/workspace.rb", ...] 

Mais hmm, si vous voulez que votre programme pour les évaluer réellement sans que vous ayez les taper de façon multiple? L'astuce est eval.

eval "@inst_var" #=> 42 
global_variables.each do |v| 
    puts eval(v) 
end 

Les 2 derniers du 5 mentionné au début doivent être évalués au niveau du module (une classe est un descendant d'un module, de sorte que les).

Object.class_variables #=> [] 
Object.constants #=> ["IO", "Duration", "UNIXserver", "Binding", ...] 

class MyClass 
    A_CONST = 'pshh' 
    class InnerClass 
    end 
    def initialize 
    @@meh = "class_var" 
    end 
end 

MyClass.constants   #=> ["A_CONST", "InnerClass"] 
MyClass.class_variables  #=> [] 
mc = MyClass.new 
MyClass.class_variables  #=> ["@@meh"] 
MyClass.class_eval "@@meh" #=> "class_var" 

Voici quelques autres astuces pour explorer dans différentes directions

"".class   #=> String 
"".class.ancestors #=> [String, Enumerable, Comparable, ...] 
String.ancestors #=> [String, Enumerable, Comparable, ...] 

def trace 
    return caller 
end 
trace #=> ["(irb):67:in `irb_binding'", "/System/Library/Frameworks/Ruby...", ...] 
5

j'ai écrit un petit bijou pour que:

$ gem install method_info 
$ rvm use 1.8.7 # (1.8.6 works but can be very slow for an object with a lot of methods) 
$ irb 
> require 'method_info' 
> 5.method_info 
::: Fixnum ::: 
%, &, *, **, +, -, [email protected], /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, abs, 
div, divmod, even?, fdiv, id2name, modulo, odd?, power!, quo, rdiv, 
rpower, size, to_f, to_s, to_sym, zero?, |, ~ 
::: Integer ::: 
ceil, chr, denominator, downto, floor, gcd, gcdlcm, integer?, lcm, 
next, numerator, ord, pred, round, succ, taguri, taguri=, times, to_i, 
to_int, to_r, to_yaml, truncate, upto 
::: Precision ::: 
prec, prec_f, prec_i 
::: Numeric ::: 
[email protected], coerce, eql?, nonzero?, pretty_print, pretty_print_cycle, 
remainder, singleton_method_added, step 
::: Comparable ::: 
between? 
::: Object ::: 
clone, to_yaml_properties, to_yaml_style, what? 
::: MethodInfo::ObjectMethod ::: 
method_info 
::: Kernel ::: 
===, =~, __clone__, __id__, __send__, class, display, dup, enum_for, 
equal?, extend, freeze, frozen?, hash, id, inspect, instance_eval, 
instance_exec, instance_of?, instance_variable_defined?, 
instance_variable_get, instance_variable_set, instance_variables, 
is_a?, kind_of?, method, methods, nil?, object_id, pretty_inspect, 
private_methods, protected_methods, public_methods, respond_to?, ri, 
send, singleton_methods, taint, tainted?, tap, to_a, to_enum, type, 
untaint 
=> nil 

Je travaille sur une amélioration des options de passage et les paramètres par défaut, mais pour l'instant, je vous suggère d'ajouter ce qui suit à votre fichier .irbrc:

require 'method_info' 
MethodInfo::OptionHandler.default_options = { 
:ancestors_to_exclude => [Object], 
:enable_colors => true 
} 

Cela permet d'activer les couleurs et de masquer les méthodes utilisées par chaque objet, car elles ne vous intéressent généralement pas.

+2

Je suppose que ce n'est pas vraiment la question, mais oh jeebus est-ce jamais ce dont j'avais besoin pour irb. L'utilisation intensive de mixins conduisant à trop de méthodes rend les bibliothèques ruby ​​beaucoup plus difficiles à explorer que celles de python, mais cela devrait très bien aider à faire le tri. Maintenant, j'ai juste besoin d'un remplacement pour help() qui est tout aussi bon. –

1

Qu'en est-:

Object.constants.select{|x| eval(x.to_s).class == Class} 

qui répertorie les classes disponibles pour moi. Je ne suis pas experte en rubis et on me laissait tomber sur une console de rubis sans aucune idée des cours à suivre. Ce premier paquebot était un début.

Questions connexes