2

I really don't know how else to entitle this one. Anyway, I am doing some metaprogramming in Ruby, and while I was debugging I came across a reference to "main:Object".

This got me thinking, if Ruby classes are never fully closed and I can reopen them later for any reason, is it possible to access this "main:Object"? if this is really an Object is should be possible just like any other class/object? If it is not, then why not? Is this a truly protected space? Either way, I want to know if I can access it from anywhere in Ruby. And if so how? And if not why not?

Other than the interpreter complaining about something not being in there, I haven't really many any references or info about this. I mean other than this is the top level scope. But this is not really what I want to know.

There really isn't much out there, these posts below talk about what it is.

Is there a “main” method in Ruby like in C?
What is “main” in Ruby?

I know this doesn't give you action items work with but I do hope that some of the experts the like share their knowledge here in StackOverflow might share it and we (I) can all learn something new.

Anyway, thanks in advance. And if this is not the correct forum please let me know which one is.

luis.madrigal
  • 1,366
  • 1
  • 15
  • 31
  • Your question is unclear. Are you asking how to get a reference to the `main` object? That's easy, at the top-level `self` is `main`. – Jörg W Mittag Aug 09 '19 at 09:26

2 Answers2

1

It is an instance introduced by irb/pry REPLs or Ruby interpreter on the top level, outside of any other declaration. You might check how does it do:

self
#⇒ main
self.class
#⇒ Object
self.__id__
#⇒ 47421128700280

When you type def foo; 42; end you actually extend this object.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • 1
    Methods defined on the top-level are private instance methods of `Object`, not singleton methods of `main`. – Jörg W Mittag Aug 09 '19 at 09:24
  • @JörgWMittag `main> self.methods.grep(/foo/) #⇒ [:foo]` but `main> Object.private_instance_methods.grep(/foo/) #⇒ []`. What am I missing? – Aleksei Matiushkin Aug 09 '19 at 09:34
  • 1
    Are you by any chance testing this in IRb? In IRb, they become *public* instance methods of `Object`. One of the many incompatibilities of IRb with Ruby. You should always test with plain Ruby, especially where edge cases are concerned. – Jörg W Mittag Aug 09 '19 at 09:38
  • Pry seems to have the same bug. – Jörg W Mittag Aug 09 '19 at 09:43
  • [This](https://github.com/ruby/ruby/blob/v3_0_1/lib/irb/workspace.rb#L21-L106) is probably the relevant part of `irb`. – x-yuri May 27 '21 at 17:58
1

TOPLEVEL_BINDING (definition) is your friend:

def m1
  class << TOPLEVEL_BINDING.receiver
    def m2
      puts 'm2'
    end
  end
  # or
  # main = TOPLEVEL_BINDING.receiver
  # def main.m2
  #   puts 'm2'
  # end
end
m1
m2 # => m2

Alternatively, you can use TOPLEVEL_BINGING.eval('self') in place of TOPLEVEL_BINGING.receiver.

x-yuri
  • 16,722
  • 15
  • 114
  • 161
  • 1
    If you wish to avoid the use of `eval('self')` the same result can be achieved by using `TOPLEVEL_BINDING.receiver`. – pnomolos Jan 11 '23 at 22:58