Skip to content

Instantly share code, notes, and snippets.

@simonoff
Forked from josevalim/1_README.md
Created December 13, 2011 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonoff/1471983 to your computer and use it in GitHub Desktop.
Save simonoff/1471983 to your computer and use it in GitHub Desktop.
FSSM based FileWatcher for Rails

Rails 3.2 ships with a simple FileWatcher that only reloads your app if any of the files changed.

Besides, it also provides a mechanism to hook up your own file watcher mechanism, so we can use tools like FSSM that hooks into Mac OS X fsevents and does the hard work for us. This is an example on how to hook your own mechanism:

  1. Copy the 2_file_watcher.rb file below to lib/file_watcher.rb

  2. Add the following inside your Application in config/application.rb

    require "file_watcher" config.file_watcher = FileWatcher

  3. Add "fssm" to your Gemfile

  4. Profit!

require "active_support/core_ext/array/wrap"
require "active_support/core_ext/array/extract_options"
require "fssm"
class FileWatcher
def initialize(paths, _calculate, &block)
@block = block
@last_update_at = Time.at(0)
@updated_at = Time.at(1)
start_monitor(paths) { |base, relative| update(base, relative) }
end
def updated?
raise "Error on FileWatcher. FSSM thread is dead." unless @thread.alive?
@updated_at > @last_update_at
end
def execute_if_updated
if updated?
execute
true
else
false
end
end
def execute
@last_update_at = @updated_at
@block.call
end
private
def update(base, relative)
timestamp = File.mtime(File.join(base, relative))
@updated_at = timestamp if timestamp > @updated_at
end
def compile_glob(exts)
array = Array.wrap(array)
return "**/*" if array.empty?
"**/*.{#{array.join(",")}}"
end
def start_monitor(paths, &block)
exprs = Hash.new { |h,k| h[k] = [] }
dirs = paths.extract_options!
paths.each do |path|
exprs[File.dirname(path)] << File.basename(path)
end
dirs.each do |path, exts|
exprs[path] << compile_glob(exts)
end
paths.freeze
dirs.freeze
@monitor = FSSM::Monitor.new
exprs.each do |dir, globs|
@monitor.path dir do
glob "{#{globs.join(",")}}"
update(&block)
create(&block)
end
end
@thread = Thread.new { @monitor.run }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment