public
Created — forked from josevalim/1_README.md

FSSM based FileWatcher for Rails

  • Download Gist
1_README.md
Markdown

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!

2_file_watcher.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.