Reputation: 13
In my .irbrc file I'm trying to write some kind of construct, class, method, module, such that when I invoke the construct in an IRB session, it will output an interleaved array of currently available objects and what classes those objects came from.
In an active IRB session, I successfully created this interleaved array using:
>> 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>]
So, all is well so far.
Then I made a new method in my .irbrc file:
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
and started another IRB session and manually recreated the Ticket
class and ticket1
, ticket2
, and ticket3
variables. Finally, I tried to use the show_top_locals
method:
>> show_top_locals(Ticket)
=> []
I got nothing back because the Kernel.local_variables
method that I'm using in the local_variables_array
variable only looks for variables that are defined within the show_top_locals
method scope.
Then I made a module in a separate file and required the file and included the module in my .irbrc:
require '.\testruby.rb'
include Top
Here's my module:
#testruby.rb
module Top
ShowVars = Class.new do
p Kernel.local_variables
define_method(:toplevelvars) do
p Kernel.local_variables
end
end
end
Back in a new IRB session:
>> show_vars = ShowVars.new
>> => #<Top::ShowVars:0x1eac1e8>
>> show_vars.toplevelvars
[]
=> []
I'm still trapped in the wrong scope.
How can I write code in .irbrc that I can use in an IRB session to give me the aforementioned interleaved object and variable array?
Upvotes: 1
Views: 234
Reputation: 18762
You don't seem to be returning all the values from your method show_top_locals
. Also, the call to Kernel#local_variables
inside a method will only lookup local variables from the method scope. You should pass the binding from the place you are calling the method so that you get list of local variables at the place where method was invoked.
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>]}
You can place the method show_top_locals
in a .rb
file and refer to "Can you 'require' ruby file in irb session, automatically, on every command?" to autoload it in IRB.
Upvotes: 0