Search code examples
rubydebuggingprivate-methods

Can I temporarily make all Ruby methods public?


I'm reproducing a bug in my Rails console. I'm interested in what some methods return, but some of them turn out to be private, so in my console I have to write:

> my_object.my_method
NoMethodError (private method `my_method' called for #<MyClass:0x0123456789ABCDEF>)
> my_object.send(:my_method)

This gets a bit tedious after a while, especially since it's not obvious which are private without drilling through to the class they're defined in.

Is there any way I could temporarily make all methods public? I don't intend to use it in production, just temporarily in my local console while I'm debugging.

UPDATE: when I say “all methods”, I don’t just mean the ones on my_object. I mean literally all methods on every object.


Solution

  • To make all methods public, this should work:

    ObjectSpace.each_object(Module) do |m|
      m.send(:public, *m.private_instance_methods(false))
    end
    

    ObjectSpace.each_object traverses all modules (that includes classes and singleton classes) and makes their (own) private_instance_methods public.


    To just make a single object public, you could use:

    my_object.singleton_class.send(:public, *my_object.private_methods)
    

    By changing the singleton class, only the my_object instance is affected.

    Note that by default, private_methods returns inherited methods too, including many from Kernel. You might want to pass false to just include the object's own private methods.