如何在IRB中逃避范围?

时间:2016-01-25 17:11:54

标签: ruby scope irb

在我的.irbrc文件中,我正在尝试编写某种构造,类,方法,模块,这样当我在IRB会话中调用构造时,它将输出当前可用对象的交错数组以及哪些类那些物品来自。

在活动的IRB会话中,我使用以下方法成功创建了此交错数组:

>> class Ticket
>>    def event
>>        "Stuff"
>>    end
>> end
>>
>> ticket1 = Ticket.new
>> => #<Ticket:0x25f5900>
>> ticket2 = Ticket.new
>> => #<Ticket:0x27622c8>
>> ticket3 = Ticket.new
>> => #<Ticket:0x304f590>
>>
>> available_objects_array = ObjectSpace.each_object(Ticket).to_a
>> => [#<Ticket:0x25f5900>, #<Ticket:0x27622c8>, #<Ticket:0x304f590>]
>> local_variables_array = local_variables.delete_if {|y| eval(y.to_s).class != Ticket}
>> => [:ticket3, :ticket2, :ticket1]
>> local_variables_array_reversed = local_variables_array.reverse.map {|z| z.to_s}
>> => ["ticket1", "ticket2", "ticket3"]
>> objects_and_variables_array = local_variables_array_reversed.zip(available_objects_array).flatten.compact
>> => ["ticket1", #<Ticket:0x25f5900>, "ticket2", #<Ticket:0x27622c8>, "ticket3", #<Ticket:0x304f590>]

所以,到目前为止一切都很顺利。

然后我在.irbrc文件中创建了一个新方法:

def show_top_locals(class_param)
    available_objects_array = ObjectSpace.each_object(class_param).to_a
    local_variables_array = local_variables.delete_if {|y| eval(y.to_s).class != class_param}
    local_variables_array_reversed = local_variables_array.reverse.map {|z| z.to_s}
objects_and_variables_array = local_variables_array_reversed.zip(available_objects_array).flatten.compact
end

并启动另一个IRB会话并手动重新创建Ticket类和ticket1ticket2ticket3变量。最后,我尝试使用show_top_locals方法:

>> show_top_locals(Ticket)
=> []

我什么都没回来,因为我在Kernel.local_variables变量中使用的local_variables_array方法只查找在show_top_locals方法范围内定义的变量。

然后我在一个单独的文件中创建了一个模块,并且需要该文件并将模块包含在我的.irbrc中:

require '.\testruby.rb'
include Top

这是我的模块:

#testruby.rb
module Top
    ShowVars = Class.new do
        p Kernel.local_variables

        define_method(:toplevelvars) do
            p Kernel.local_variables
        end
    end
end

返回新的IRB会话:

>> show_vars = ShowVars.new
>> => #<Top::ShowVars:0x1eac1e8>
>> show_vars.toplevelvars
[]
=> []

我仍然被困在错误的范围内。

如何在.irbrc中编写代码,我可以在IRB会话中使用它来提供前面提到的交错对象和变量数组?

1 个答案:

答案 0 :(得分:0)

您似乎无法返回方法show_top_locals中的所有值。此外,方法内部对Kernel#local_variables的调用只会从方法范围中查找局部变量。您应该从调用方法的位置传递绑定,以便在调用方法的位置获取局部变量列表。

require "pp"

# For backward compatibility with Ruby 2.1 and below
def local_vars(binding)
    if binding.respond_to? :local_variables
        binding.local_variables
    else
        eval "Kernel.local_variables", binding
    end
end

def show_top_locals(class_param, binding)
    available_objects_array = ObjectSpace.each_object(class_param).to_a
    local_variables_array = local_vars(binding).delete_if {|y| binding.eval(y.to_s).class != class_param}
    local_variables_array_reversed = local_variables_array.reverse.map {|z| z.to_s}
    objects_and_variables_array = local_variables_array_reversed.zip(available_objects_array).flatten.compact
    return {
       available_objs: available_objects_array,
       local_vars: local_variables_array,
       local_vars_reversed: local_variables_array_reversed,
       objs_and_vars: objects_and_variables_array
     }
end

class Foo
end

a = Foo.new
b = Foo.new

pp show_top_locals(Foo, binding)
#=> {:available_objs=>[#<Foo:0x000000027825b0>, #<Foo:0x000000027825d8>],
#    :local_vars=>[:a, :b],
#    :local_vars_reversed=>["b", "a"],
#    :objs_and_vars=>["b", #<Foo:0x000000027825b0>, "a", #<Foo:0x000000027825d8>]}

您可以将方法show_top_locals放在.rb文件中,并参考&#34; Can you 'require' ruby file in irb session, automatically, on every command?&#34;在IRB中自动加载。