如何逃避 IRB 的范围?

How to escape scope in IRB?

在我的 .irbrc 文件中,我尝试编写某种构造、class、方法、模块,这样当我在 IRB session 中调用构造时,它将输出当前可用 object 的交错数组以及 class 那些 object 的来源。

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

>> 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 session 并手动重新创建了 Ticket class 和 ticket1ticket2ticket3 变量。最后,我尝试使用show_top_locals方法:

>> show_top_locals(Ticket)
=> []

我什么也没得到,因为我在 local_variables_array 变量中使用的 Kernel.local_variables 方法只查找在 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 session:

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

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

如何在 .irbrc 中编写可在 IRB session 中使用的代码,以提供上述交错 object 和变量数组?

您似乎没有从您的方法 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 文件中,并参考“Can you 'require' ruby file in irb session, automatically, on every command?”在 IRB 中自动加载它。