aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/file_update_checker.rb79
-rw-r--r--activesupport/lib/active_support/i18n_railtie.rb3
2 files changed, 74 insertions, 8 deletions
diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb
index 9d617b39d4..4137bbf6a0 100644
--- a/activesupport/lib/active_support/file_update_checker.rb
+++ b/activesupport/lib/active_support/file_update_checker.rb
@@ -1,3 +1,6 @@
+require "active_support/core_ext/array/wrap"
+require "active_support/core_ext/array/extract_options"
+
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
@@ -15,24 +18,86 @@ module ActiveSupport
class FileUpdateChecker
attr_reader :paths, :last_update_at
+ # It accepts two parameters on initialization. The first is
+ # the *paths* and the second is *calculate*, a boolean.
+ #
+ # paths must be an array of file paths but can contain a hash as
+ # last argument. The hash must have directories as keys and the
+ # value is an array of extensions to be watched under that directory.
+ #
+ # If *calculate* is true, the latest updated at will calculated
+ # on initialization, therefore, the first call to execute_if_updated
+ # will only evaluate the block if something really changed.
+ #
+ # This method must also receive a block that will be the block called
+ # once a file changes.
+ #
+ # This particular implementation checks for added files and updated files,
+ # but not removed files. Directories lookup are compiled to a glob for
+ # performance.
def initialize(paths, calculate=false, &block)
@paths = paths
+ @glob = compile_glob(@paths.extract_options!)
@block = block
+ @updated_at = nil
@last_update_at = calculate ? updated_at : nil
end
- def updated_at
- # TODO: Use Enumerable check once we get rid of 1.8.7
- all = paths.is_a?(Array) ? paths : Dir[paths]
- all.map { |path| File.mtime(path) }.max
+ # Check if any of the entries were updated. If so, the updated_at
+ # value is cached until flush! is called.
+ def updated?
+ current_updated_at = updated_at
+ if @last_update_at != current_updated_at
+ @updated_at = updated_at
+ true
+ else
+ false
+ end
+ end
+
+ # Flush the cache so updated? is calculated again
+ def flush!
+ @updated_at = nil
end
+ # Execute the block given if updated. This call
+ # always flush the cache.
def execute_if_updated
- current_update_at = self.updated_at
- if @last_update_at != current_update_at
- @last_update_at = current_update_at
+ if updated?
+ @last_update_at = updated_at
@block.call
+ true
+ else
+ false
end
+ ensure
+ flush!
+ end
+
+ private
+
+ def updated_at #:nodoc:
+ @updated_at || begin
+ all = []
+ all.concat @paths
+ all.concat Dir[@glob] if @glob
+ all.map { |path| File.mtime(path) }.max
+ end
+ end
+
+ def compile_glob(hash) #:nodoc:
+ return if hash.empty?
+ globs = []
+ hash.each do |key, value|
+ globs << "#{key}/**/*#{compile_ext(value)}"
+ end
+ "{#{globs.join(",")}}"
+ end
+
+ def compile_ext(array) #:nodoc:
+ array = Array.wrap(array)
+ return if array.empty?
+ ".{#{array.join(",")}}"
end
end
end
diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb
index 4c59fe9ac9..a989ff8f57 100644
--- a/activesupport/lib/active_support/i18n_railtie.rb
+++ b/activesupport/lib/active_support/i18n_railtie.rb
@@ -17,7 +17,8 @@ module I18n
# point, no path was added to the reloader, I18n.reload! is not triggered
# on to_prepare callbacks. This will only happen on the config.after_initialize
# callback below.
- initializer "i18n.callbacks" do
+ initializer "i18n.callbacks" do |app|
+ app.reloaders << I18n::Railtie.reloader
ActionDispatch::Reloader.to_prepare do
I18n::Railtie.reloader.execute_if_updated
end