Add ActiveSupport::FileUpdateChecker.

This commit is contained in:
José Valim 2010-06-20 13:26:42 +02:00
parent 9e081caee7
commit 71703c98ba
3 changed files with 96 additions and 1 deletions

View File

@ -39,6 +39,9 @@ require "active_support/dependencies/autoload"
module ActiveSupport
extend ActiveSupport::Autoload
autoload :DescendantsTracker
autoload :FileUpdateChecker
# TODO: Narrow this list down
eager_autoload do
autoload :BacktraceCleaner
@ -51,7 +54,6 @@ module ActiveSupport
autoload :Concern
autoload :Configurable
autoload :Deprecation
autoload :DescendantsTracker
autoload :Gzip
autoload :Inflector
autoload :JSON

View File

@ -0,0 +1,37 @@
module ActiveSupport
# This class is responsible to track files and invoke the given block
# whenever one of these files are changed. For example, this class
# is used by Rails to reload routes whenever they are changed upon
# a new request.
#
# routes_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
# paths.each { |p| load(p) }
# Rails::Application.routes.reload!
# end
#
# ActionDispatch::Callbacks.to_prepare do
# routes_reloader.execute_if_updated
# end
#
class FileUpdateChecker
attr_reader :paths, :last_update_at
def initialize(paths, calculate=false, &block)
@paths = paths
@block = block
@last_update_at = updated_at if calculate
end
def updated_at
paths.map { |path| File.stat(path).mtime }.max
end
def execute_if_updated
current_update_at = self.updated_at
if @last_update_at != current_update_at
@last_update_at = current_update_at
@block.call
end
end
end
end

View File

@ -0,0 +1,56 @@
require 'abstract_unit'
require 'test/unit'
require 'active_support'
require 'fileutils'
MTIME_FIXTURES_PATH = File.expand_path("../fixtures", __FILE__)
class FileUpdateCheckerTest < Test::Unit::TestCase
FILES = %w(1.txt 2.txt 3.txt)
def setup
FileUtils.touch(FILES)
end
def teardown
FileUtils.rm(FILES)
end
def test_should_not_execute_the_block_if_no_paths_are_given
i = 0
checker = ActiveSupport::FileUpdateChecker.new([]){ i += 1 }
checker.execute_if_updated
assert_equal 0, i
end
def test_should_invoke_the_block_on_first_call_if_it_does_not_calculate_last_updated_at_on_load
i = 0
checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 }
checker.execute_if_updated
assert_equal 1, i
end
def test_should_not_invoke_the_block_on_first_call_if_it_calculates_last_updated_at_on_load
i = 0
checker = ActiveSupport::FileUpdateChecker.new(FILES, true){ i += 1 }
checker.execute_if_updated
assert_equal 0, i
end
def test_should_not_invoke_the_block_if_no_file_has_changed
i = 0
checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 }
5.times { checker.execute_if_updated }
assert_equal 1, i
end
def test_should_invoke_the_block_if_a_file_has_changed
i = 0
checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 }
checker.execute_if_updated
sleep(1)
FileUtils.touch(FILES)
checker.execute_if_updated
assert_equal 2, i
end
end