The difficulties, or rather impossibilities, of doing in-process code reloading in Ruby have been well-documented.
There are many out-of-process reloading solutions. These all essentially reboot your application, reloading all dependancies.
This provides an obvious incentive to keep your application boot times as fast as possible.
'Rerun launches your program, then watches the filesystem. If a relevant file changes, then it restarts your program. By default it watches files ending in: rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature. Use the --pattern option if you want to change this.' - Doc U. Mentation Jr.
Rerun is a general purpose gem (gem install rerun) for watching files and rerunning some command when any of those files change.
The following example uses rerun to watch for changes to ".rb" and ".ru" files anywhere in the current directory tree.
If a change is made, any previous instance of rackup are shutdown and restarted.
rerun -p "**/*.{rb,ru}" rackup
Why would I use this instead of Shotgun?
'This is an automatic reloading version of the rackup command that's shipped with Rack. Each time a request is received, it forks, loads the application in the child process, processes the request, and exits the child process. The result is clean, application-wide reloading of all source files and templates on each request.' - Doc U. Mentation
Unlike Rerun, Shotgun doesn't do any file watching. It instead reloads your application on every request.
This sounds slow, but Shotgun uses an efficient technique of forking the application server and reloading your application.
For applications that are quick to start, this method is generally preferred.
shotgun