mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add initial FileWatcher implementation. The Backend is just an abstract implementation, which will be inherited by backends that do the heavy lifting.
This commit is contained in:
parent
3026843dc1
commit
1fd9d978a7
3 changed files with 107 additions and 0 deletions
|
@ -42,6 +42,7 @@ module ActiveSupport
|
|||
|
||||
autoload :DescendantsTracker
|
||||
autoload :FileUpdateChecker
|
||||
autoload :FileWatcher
|
||||
autoload :LogSubscriber
|
||||
autoload :Notifications
|
||||
|
||||
|
|
41
activesupport/lib/active_support/file_watcher.rb
Normal file
41
activesupport/lib/active_support/file_watcher.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
module ActiveSupport
|
||||
class FileWatcher
|
||||
class Backend
|
||||
def initialize(path, watcher)
|
||||
@watcher = watcher
|
||||
@path = path
|
||||
end
|
||||
|
||||
def trigger(files)
|
||||
@watcher.trigger(files)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@regex_matchers = {}
|
||||
end
|
||||
|
||||
def watch(path, &block)
|
||||
return watch_regex(path, &block) if path.is_a?(Regexp)
|
||||
raise "Paths must be regular expressions. #{path.inspect} is a #{path.class}"
|
||||
end
|
||||
|
||||
def watch_regex(regex, &block)
|
||||
@regex_matchers[regex] = block
|
||||
end
|
||||
|
||||
def trigger(files)
|
||||
trigger_files = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } }
|
||||
|
||||
files.each do |file, state|
|
||||
@regex_matchers.each do |regex, block|
|
||||
trigger_files[block][state] << file if file =~ regex
|
||||
end
|
||||
end
|
||||
|
||||
trigger_files.each do |block, payload|
|
||||
block.call payload
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
65
activesupport/test/file_watcher_test.rb
Normal file
65
activesupport/test/file_watcher_test.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
require 'abstract_unit'
|
||||
|
||||
class FileWatcherTest < ActiveSupport::TestCase
|
||||
class DumbBackend < ActiveSupport::FileWatcher::Backend
|
||||
end
|
||||
|
||||
def setup
|
||||
@watcher = ActiveSupport::FileWatcher.new
|
||||
|
||||
# In real life, the backend would take the path and use it to observe the file
|
||||
# system. In our case, we will manually trigger the events for unit testing,
|
||||
# so we can pass any path.
|
||||
@backend = DumbBackend.new("RAILS_WOOT", @watcher)
|
||||
|
||||
@payload = []
|
||||
@watcher.watch %r{^app/assets/.*\.scss$} do |pay|
|
||||
pay.each do |status, files|
|
||||
files.sort!
|
||||
end
|
||||
@payload << pay
|
||||
end
|
||||
end
|
||||
|
||||
def test_one_change
|
||||
@backend.trigger("app/assets/main.scss" => :changed)
|
||||
assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first)
|
||||
end
|
||||
|
||||
def test_multiple_changes
|
||||
@backend.trigger("app/assets/main.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed)
|
||||
assert_equal([{:changed => ["app/assets/main.scss"]}], @payload)
|
||||
end
|
||||
|
||||
def test_multiple_changes_match
|
||||
@backend.trigger("app/assets/main.scss" => :changed, "app/assets/print.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed)
|
||||
assert_equal([{:changed => ["app/assets/main.scss", "app/assets/print.scss"]}], @payload)
|
||||
end
|
||||
|
||||
def test_multiple_state_changes
|
||||
@backend.trigger("app/assets/main.scss" => :created, "app/assets/print.scss" => :changed)
|
||||
assert_equal([{:changed => ["app/assets/print.scss"], :created => ["app/assets/main.scss"]}], @payload)
|
||||
end
|
||||
|
||||
def test_more_blocks
|
||||
payload = []
|
||||
@watcher.watch %r{^config/routes\.rb$} do |pay|
|
||||
payload << pay
|
||||
end
|
||||
|
||||
@backend.trigger "config/routes.rb" => :changed
|
||||
assert_equal [:changed => ["config/routes.rb"]], payload
|
||||
assert_equal [], @payload
|
||||
end
|
||||
|
||||
def test_overlapping_watchers
|
||||
payload = []
|
||||
@watcher.watch %r{^app/assets/main\.scss$} do |pay|
|
||||
payload << pay
|
||||
end
|
||||
|
||||
@backend.trigger "app/assets/print.scss" => :changed, "app/assets/main.scss" => :changed
|
||||
assert_equal [:changed => ["app/assets/main.scss"]], payload
|
||||
assert_equal [:changed => ["app/assets/main.scss", "app/assets/print.scss"]], @payload
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue