Как вы перечисляете в настоящее время доступные объекты в текущей области в рубине? - PullRequest
34 голосов
/ 23 октября 2008

Я новичок в ruby ​​и играю с IRB.

Я обнаружил, что могу перечислять методы объекта, используя метод ".methods", и что своего рода self.methods дает мне то, что я хочу (похоже на каталог Python ( builtins )?), но как мне найти методы библиотеки / модуля, которые я загрузил через include и 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>

Я привык к python, где я использую функцию dir (), чтобы выполнить то же самое:

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

Ответы [ 7 ]

40 голосов
/ 25 октября 2008

Я не совсем уверен, что вы подразумеваете под «текущими объектами». Вы можете перебирать ObjectSpace, как уже упоминалось. Но вот несколько других методов.

local_variables
instance_variables
global_variables

class_variables
constants

Есть одна ошибка. Они должны быть названы в нужных областях. Итак, прямо в IRB, или в экземпляре объекта, или в области видимости класса (так везде, в основном) вы можете вызвать первый 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", ...]

Но хм, а что если вы хотите, чтобы ваша программа действительно оценивала их, не требуя, чтобы вы печатали их вручную? Трюк - это оценка.

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

Последние 2 из 5, упомянутых в начале, должны оцениваться на уровне модуля (класс является потомком модуля, поэтому работает).

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"

Вот еще несколько трюков для изучения в разных направлениях

"".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...", ...]
25 голосов
/ 23 октября 2008

ObjectSpace.each_object может быть тем, что вы ищете.

Чтобы получить список включенных модулей, вы можете использовать Module.included_modules .

Вы также можете проверить, реагирует ли объект на метод в каждом конкретном случае, используя object.respond_to? .

6 голосов
/ 09 ноября 2010

Я написал для этого камень:

$ 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

Я работаю над улучшением параметров передачи и настроек по умолчанию, но сейчас я бы предложил вам добавить в файл .irbrc следующее:

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

Это разрешает цвета и скрывает методы, которые есть у каждого объекта, так как они обычно вам не интересны.

6 голосов
/ 24 октября 2008

Метод dir() имеет значение , четко не определено ...

Примечание: Поскольку dir() поставляется прежде всего для удобства использования в интерактивное приглашение, оно пытается предоставить интересный набор имен больше, чем он пытается поставить строго или последовательно определенный набор имен и его подробное поведение может меняться в зависимости от выпуска.

... но мы можем создать близкое приближение в Ruby. Давайте создадим метод, который будет возвращать отсортированный список всех методов, добавленных в нашу область действия включенными модулями. Мы можем получить список модулей, которые были включены, используя метод included_modules.

Как и dir(), мы хотим игнорировать методы «по умолчанию» (например, print), и мы также хотим сосредоточиться на «интересном» наборе имен. Таким образом, мы будем игнорировать методы в Kernel, и мы будем возвращать только те методы, которые были определены непосредственно в модулях, игнорируя унаследованные методы. Мы можем сделать это позже, передав false в метод methods(). Собрав все воедино, мы получим ...

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

Вы можете передать ему класс, объект или ничего (по умолчанию это текущая область). Давайте попробуем ...

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() также включает локально определенные переменные, и это легко. Просто позвони ...

local_variables

... к сожалению, мы не можем просто добавить вызов local_variables к included_methods, потому что он даст нам переменные, локальные для метода included_methods, и это не будет очень полезно. Так что, если вы хотите, чтобы локальные переменные были включены в методу include_methods, просто вызовите ...

 (included_methods + local_variables).sort
2 голосов
/ 28 июля 2016

А как же:

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

Это список доступных классов для меня. Я не эксперт по ruby, и меня бросали за консоль ruby, не зная, какие классы были под рукой. Этот лайнер был началом.

2 голосов
/ 23 октября 2008

Для доступа ко всем экземплярам объектов в ruby ​​вы используете ObjectSpace

http://www.ruby -doc.org / ядро-1.8.7 / классы / ObjectSpace.html # M000928

Тем не менее, это считается медленным (даже для ruby), и может не включаться в некоторых интерпретаторах (например, jRuby может отключить ObjectSpace, поскольку гораздо быстрее полагаться на jvm для gc без необходимости отслеживать этот материал в jRuby).

0 голосов
/ 23 октября 2008

Вы можете передавать сообщения .methods в библиотеку / модуль еще до загрузки, чтобы увидеть все доступные методы. Выполнение self.methods просто возвращает все методы, которые содержит объект Object. Вы можете увидеть это, выполнив self.class. Допустим, вы хотите увидеть все методы в модуле File. Вы просто делаете File.methods, и вы получите список всех методов, которые существуют в модуле File. Возможно, это не то, что вы хотите, но это должно быть несколько полезно.

...