Pry lets you call "binding.pry" anywhere in your program to dump you into a shell within that context, with full access to local variables etc.. And tab-completion and plenty of introspection features. I frequently find myself triggering Pry in the middle of handling http requests if something doesn't work, for example. Letting me inspect the environment, modify stuff, and when I exit the request is completed.
It can also do things (with some limitations) like bring up an editor to where the current method was defined, and let you edit and reload the code.
And you can attach to it remotely using Drb in case the app in question doesn't run attached to a terminal.
At this point it's almost criminal to do Ruby development without Pry.