¿Cómo se enumeran los objetos actualmente disponibles en el alcance actual en Ruby?

StackOverflow https://stackoverflow.com/questions/228648

  •  04-07-2019
  •  | 
  •  

Pregunta

Soy nuevo en Ruby y estoy jugando con el IRB.

Descubrí que puedo enumerar métodos de un objeto usando el método ".methods", y que self.methods me da lo que quiero (similar al directorio de Python (incorporados)?), pero ¿cómo puedo encontrar los métodos de una biblioteca/módulo que he cargado mediante include y 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>

Estoy acostumbrado a Python, donde uso la función dir() para lograr lo mismo:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>>
¿Fue útil?

Solución

ObjectSpace.each_object podría ser lo que estás buscando.

Para obtener una lista de los módulos incluidos, puede usar Module.included_modules .

También puede verificar si un objeto responde a un método caso por caso usando object.respond_to? .

Otros consejos

No estoy completamente seguro de lo que quieres decir con "objetos actuales". Puede iterar sobre ObjectSpace, como ya se mencionó. Pero aquí hay algunos otros métodos.

local_variables
instance_variables
global_variables

class_variables
constants

Hay una trampa. Deben llamarse en los ámbitos correctos. Entonces, justo en IRB, o en una instancia de objeto o en el ámbito de la clase (básicamente, en todas partes) puede llamar a los primeros 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", ...]

Pero umm, ¿qué pasa si quieres que tu programa realmente los evalúe sin necesidad de que los escribas de manera manual? El truco es evaluar.

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

Los 2 últimos de los 5 mencionados al principio deben evaluarse a nivel de módulo (una clase es un descendiente de un módulo, por lo que funciona).

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"

Aquí hay algunos trucos más para explorar en diferentes direcciones

"".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...", ...]

El método dir() es no está claramente definido ...

  

Nota: porque se suministra included_modules   principalmente como una conveniencia para su uso en   un mensaje interactivo, intenta   proporcionar un conjunto interesante de nombres   más de lo que intenta suministrar un   conjunto definido rigurosa o consistentemente   de nombres y su comportamiento detallado   puede cambiar entre versiones.

... pero podemos crear una aproximación cercana en Ruby. Hagamos un método que devuelva una lista ordenada de todos los métodos agregados a nuestro alcance por los módulos incluidos. Podemos obtener una lista de los módulos que se han incluido utilizando el método print.

Al igual que Kernel, queremos ignorar el " default " métodos (como false), y también queremos centrarnos en " interesante " conjunto de nombres Por lo tanto, ignoraremos los métodos en methods(), y solo devolveremos los métodos que se definieron directamente en los módulos, ignorando los métodos heredados. Podemos lograr lo siguiente pasando local_variables al método included_methods. Poniendo todo junto, obtenemos ...

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

Puede pasarle una clase, un objeto o nada (el valor predeterminado es el alcance actual). Probémoslo ...

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

<=> también incluye variables definidas localmente, y eso es fácil. Solo llama ...

local_variables

... desafortunadamente, no podemos simplemente agregar la llamada <=> a <=> porque nos daría las variables que son locales para el método <=>, y eso no sería muy útil. Entonces, si desea incluir variables locales con los métodos_incluidos, simplemente llame ...

 (included_methods + local_variables).sort

Escribí una gema para eso:

$ 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 :::
%, &, *, **, +, -, -@, /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, 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 :::
+@, 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

Estoy trabajando en una mejora de las opciones de paso y la configuración predeterminada, pero por ahora sugeriría que agregue lo siguiente a su archivo .irbrc:

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

Esto habilita los colores y oculta los métodos que tiene cada objeto, ya que generalmente no estás interesado en ellos.

¿Qué pasa con:

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

Eso enumera las clases disponibles para mí. No soy un experto en rubíes y me dejaron caer en una consola de rubíes sin tener idea de qué clases estaban disponibles. Ese trazador de líneas fue un comienzo.

Para acceder a todas las instancias de objetos en ruby, use ObjectSpace

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

Sin embargo, esto se considera lento (incluso para ruby), y puede que no esté habilitado en algunos intérpretes (por ejemplo, jRuby puede deshabilitar ObjectSpace ya que es mucho más rápido confiar en jvm para gc sin necesidad de rastrear estas cosas en jRuby).

Puede pasar los mensajes .methods a la biblioteca/módulo incluso antes de cargarlo, para ver todos los métodos disponibles.Haciendo self.methods simplemente devuelve todos los métodos que contiene el objeto Object.Puedes ver esto haciendo self.class.Entonces digamos que desea ver todos los métodos en el módulo Archivo.simplemente lo haces File.methods y obtendrá una lista de todos los métodos que existen en el módulo Archivo.Quizás esto no sea lo que desea, pero debería ser algo útil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top