What is TOPLEVEL_BINDING in ruby?
The fact is, TOPLEVEL_BINDING
always refers to a predefined global instance of Binding
, while Kernel#binding
creates a new instance of Binding
that encapsulates the current execution context every time. At top level, they both contain the same bindings, but they are not the same object and you cannot test their binding equality with ==
or ===
.
puts TOPLEVEL_BINDING
puts TOPLEVEL_BINDING
puts binding
puts binding
puts binding == binding
# =>
#<Binding:0x9769ea0>
#<Binding:0x9769ea0>
#<Binding:0x9941ea8>
#<Binding:0x9941e58>
false
Understanding ruby TOPLEVEL_BINDING
TOPLEVEL_BINDING
is the top level binding.
That method is passing the string "run ..." into Builder.new { run ... }
Builder.new then does an instance_eval (https://github.com/rack/rack/blob/df1506b0825a096514fcb3821563bf9e8fd52743/lib/rack/builder.rb#L53-L55) on the block, thereby giving the code inside the block direct access to the instance's methods.
def initialize(default_app = nil,&block)
@use, @map, @run, @warmup = [], nil, default_app, nil
instance_eval(&block) if block_given?
end
run
is an instance method of the Builder class, defined here -> https://github.com/rack/rack/blob/df1506b0825a096514fcb3821563bf9e8fd52743/lib/rack/builder.rb#L103-L105def run(app)
@run = app
end
In short, "run DemoApp::Application"
becomes:Rack::Builder.new {
run DemoApp::Application
}.to_app
Edit: A simple example to illustrate the point:class Builder
def initialize(&block)
instance_eval(&block)
end
def run(what)
puts "Running #{what}"
end
end
TOPLEVEL_BINDING.eval "Builder.new { run 10 }"
printsRunning 10
What's the difference between TOPLEVEL_BINDING and binding?
TOPLEVEL_BINDING
is a constant.
binding
is a method which creates a new binding specific to the place where it is called.
> TOPLEVEL_BINDING #=> #<Binding:0x0000564e7226f1d0>
> TOPLEVEL_BINDING #=> #<Binding:0x0000564e7226f1d0> -- same object
> binding #=> #<Binding:0x0000564e72892aa8>
> binding #=> #<Binding:0x0000564e728907f8> -- new object
> TOPLEVEL_BINDING.source_location #=> ["<main>", 0]
> binding.source_location #=> ["(irb)", 6]
> binding == binding #=> false
> x = 2
> b = binding
> z = 4
> TOPLEVEL_BINDING.eval('x') #=> NameError
> TOPLEVEL_BINDING.eval('z') #=> NameError
> b.eval('x') #=> 2
> b.eval('z') #=> NameError
> binding.eval('x') #=> 2
> binding.eval('z') #=> 4
eval and Binding in ruby
instanceMethodMain
isn't called twice.
You can check it by adding
def instanceMethodMain
puts "BEEN HERE"
p "instanceMethodMain"
end
p
is called twice with "instanceMethodMain"
as parameter.p p "instanceMethodMain"
#=> "instanceMethodMain"
#=> "instanceMethodMain"
Note that p "string"
displays "string"
and returns "string"
, while puts "string"
displays string
and returns nil
:puts puts "instanceMethodMain"
#=> instanceMethodMain
#=>
How to get `main` object evaluated in Ruby?
To gain access to the "main" object from anywhere, use the TOPLEVEL_BINDING
:
class MyShell
def main_object
TOPLEVEL_BINDING.eval('self') #=> "main"
end
end
What's the difference between binding.pry and Pry.start?
Calling Pry.start(binding)
from within a console should have a similar effect to calling binding.pry
:
rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> class Gnar
[1] pry(main)* def self.gar
[1] pry(main)* @var = "lar!"
[1] pry(main)* Pry.start(binding)
[1] pry(main)* end
[1] pry(main)* end
=> :gar
[2] pry(main)> Gnar.gar
From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:
383: def evaluate_ruby(code)
384: inject_sticky_locals!
385: exec_hook :before_eval, code, self
386:
387: result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
=> 388: set_last_result(result, code)
389: ensure
390: update_input_history(code)
391: exec_hook :after_eval, result, self
392: end
[1] pry(#<Pry>)>
A Binding object encapsulates the execution context of your code at a specific location. Binding#pry
starts a Pry REPL over a Binding object. Pry.start
just starts a Pry REPL. If you don't pass it a binding, then it's just a Pry REPL without any execution context; the console tells you whether or not it has context by changing from pry(main)
(no context) to pry(#<Pry>)>
if the execution context of the binding passed to it was a Pry instance:
$ rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> Pry.start(binding)
From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:
383: def evaluate_ruby(code)
384: inject_sticky_locals!
385: exec_hook :before_eval, code, self
386:
387: result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
=> 388: set_last_result(result, code)
389: ensure
390: update_input_history(code)
391: exec_hook :after_eval, result, self
392: end
[1] pry(#<Pry>)> exit
=> nil
[2] pry(main)> binding.pry
From: /Users/redacted/.gem/gems/pry-0.12.2/lib/pry/pry_instance.rb @ line 388 Pry#evaluate_ruby:
383: def evaluate_ruby(code)
384: inject_sticky_locals!
385: exec_hook :before_eval, code, self
386:
387: result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
=> 388: set_last_result(result, code)
389: ensure
390: update_input_history(code)
391: exec_hook :after_eval, result, self
392: end
[1] pry(#<Pry>)> exit
=> nil
[3] pry(main)> exit
Similarly, calling binding.pry from within a class method opens up a Pry REPL within the execution context of that class (pry(ClassName)
). Calling binding.pry from within an instance method opens up a Pry REPL within the execution context of that instance (pry(#<ClassName>
).rails c
Loading development environment (Rails 5.1.6.2)
[1] pry(main)> class A
[1] pry(main)* def self.b
[1] pry(main)* binding.pry
[1] pry(main)* end
[1] pry(main)*
[1] pry(main)* def c
[1] pry(main)* binding.pry
[1] pry(main)* end
[1] pry(main)* end
=> :c
[2] pry(main)> A.b
From: (pry) @ line 4 A.b:
2: def self.b
3: binding.pry
=> 4: end
[1] pry(A)> exit
=> nil
[3] pry(main)> A.new.c
From: (pry) @ line 8 A#c:
6: def c
7: binding.pry
=> 8: end
[1] pry(#<A>)> exit
=> nil
Hope that helps. Any way to create a new, empty Binding in Ruby?
An easy way would be to write a method that calls binding
and nothing else:
def empty_binding
binding
end
Then:b = empty_binding
b.local_variables
# [ ]
That binding will still have a self
and access to whatever instance variables are available to that self
. You could limit that with some chicanery:module Empty
def self.binding
super
end
end
b = Empty.binding
b.eval('puts local_variables.inspect')
# [ ]
b.eval('puts instance_variables.inspect')
# [ ]
b.eval('puts self.inspect')
# Empty
What works depends on what the goal is. A binding with no local variables is pretty easy, a binding with nothing at all probably isn't possible without hacking Ruby itself (although BasicObject
might be useful to get a little closer to empty than a module).None of these things give you a jail to safely eval
inside if that's what you're after.
Related Topics
How to Automatically Escape HTML Content Using Jekyll and Markdown
Problems While Making a Generic Model in Ruby on Rails 3
How to Test Strong Params with Rspec
Sql Like Operator in Ruby on Rails
How to Fix a Deadlock in Join() in Ruby
How to Scrape a Website with The Socksify Gem (Proxy)
Where Are Keywords Defined in Ruby
Sinatra on Nginx Configuration - What's Wrong
Browsing Ruby Code a La Smalltalk
Case Insensitive Search in Rails
Ruby: How to Escape Url with Square Brackets [ and ]
Hw Impossibility: "Create a Rock Paper Scissors Program in Ruby Without Using Conditionals"
Why Slicing The Params Hash Poses a Security Issue on Mass-Assignment