Reloadable Ruby applications

Reloading the source code to your application while it is still running is a tremendous time saver during development. You can tweak formulas, fix typos, even refactor code without losing the program state.

Below is how I implemented this feature for Luz. I’m not convinced it is the most robust implementation, but it has worked well so far.

module Kernel
	$source_file_modification_times ||= {}

	# a new 'require' supporting multiple files
	alias_method :single_require, :require
	def require(*list)
		[*list].each { |file|
			# Was the file successfully 'require'd?
			if single_require(file)
				# Grab latest file name (which now includes the .rb) from $LOADED_FEATURES (list of all 'require'd files)
				file = $LOADED_FEATURES.last

				# Find the full file path that was loaded by searching the path the way Ruby does
				filepath = $LOAD_PATH.find { |path| File.exist?("#{path}/#{file}") } + "/#{file}"

				# Add to list
				$source_file_modification_times[filepath] = File.new(filepath).mtime
			end
		}
	end

	def reload_if_newer(filepath)
		mtime = File.new(filepath).mtime

		# Do we already have the current version?
		return false if mtime == $source_file_modification_times[filepath]

		begin
			load filepath
			$source_file_modification_times[filepath] = mtime
			return true
		rescue Exception => e
			# report exception to user somehow...
			return false
		end
	end

	def reload_modified_source_files
		$source_file_modification_times.each_key { |filepath| reload_if_newer(filepath) }
	end
end

Then simply create a keyboard shortcut (I use Ctrl-Shift-R) that calls reload_modified_source_files. Because it only reloads files that have changed on disk, it’s quite fast.

The exception handling around the “load filepath” statement prevents syntax errors from bringing down the application.

(Note that this also adds multi-file “require”, which I discussed earlier.)

One Response to Reloadable Ruby applications

  1. Nice, I am using something similar to this in one of my projects.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: