class ActiveSupport::FileUpdateChecker

end
i18n_reloader.execute_if_updated
ActiveSupport::Reloader.to_prepare do
end
I18n.reload!
i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
they are changed upon a new request.
This class is used by Rails to reload the I18n framework whenever
the block only if there was really a change in the filesystem.
After initialization, a call to execute_if_updated must execute
* execute_if_updated which just executes the block if it was updated.
and updates the latest watched files and timestamp.
* execute which executes the given block on initialization
the filesystem or not.
* updated? which returns a boolean if there were updates in
described below.
* initialize which expects two parameters and one block as
and control reloading. The API depends on four methods:
FileUpdateChecker specifies the API used by Rails to watch files

def compile_ext(array)

def compile_ext(array)
  array = Array(array)
  return if array.empty?
  ".{#{array.join(",")}}"
end

def compile_glob(hash)

def compile_glob(hash)
  hash.freeze # Freeze so changes aren't accidentally pushed
  return if hash.empty?
  globs = hash.map do |key, value|
    "#{escape(key)}/**/*#{compile_ext(value)}"
  end
  "{#{globs.join(",")}}"
end

def escape(key)

def escape(key)
  key.gsub(",", '\,')
end

def execute

timestamp.
Executes the given block and updates the latest watched files and
def execute
  @last_watched   = watched
  @last_update_at = updated_at(@last_watched)
  @block.call
ensure
  @watched = nil
  @updated_at = nil
end

def execute_if_updated

Execute the block given if updated.
def execute_if_updated
  if updated?
    yield if block_given?
    execute
    true
  else
    false
  end
end

def initialize(files, dirs = {}, &block)

after FileUpdateChecker has been initialized.
changes. The array of files and list of directories cannot be changed
This method must also receive a block that will be called once a path

watched under that directory.
have directories as keys and the value is an array of extensions to be
of files and the second is an optional hash of directories. The hash must
It accepts two parameters on initialization. The first is an array
def initialize(files, dirs = {}, &block)
  unless block
    raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
  end
  @files = files.freeze
  @glob  = compile_glob(dirs)
  @block = block
  @watched    = nil
  @updated_at = nil
  @last_watched   = watched
  @last_update_at = updated_at(@last_watched)
end

def max_mtime(paths)

reloading is not triggered.
healthy to consider this edge case because with mtimes in the future
can happen for example if the user changes the clock by hand. It is
Files with a mtime in the future are ignored. Such abnormal situation

if the array is empty.
This method returns the maximum mtime of the files in +paths+, or +nil+
def max_mtime(paths)
  time_now = Time.now
  max_mtime = nil
  # Time comparisons are performed with #compare_without_coercion because
  # AS redefines these operators in a way that is much slower and does not
  # bring any benefit in this particular code.
  #
  # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
  paths.each do |path|
    mtime = File.mtime(path)
    next if time_now.compare_without_coercion(mtime) < 0
    if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
      max_mtime = mtime
    end
  end
  max_mtime
end

def updated?

or +execute_if_updated+.
updated_at values are cached until the block is executed via +execute+
Check if any of the entries were updated. If so, the watched and/or
def updated?
  current_watched = watched
  if @last_watched.size != current_watched.size
    @watched = current_watched
    true
  else
    current_updated_at = updated_at(current_watched)
    if @last_update_at < current_updated_at
      @watched    = current_watched
      @updated_at = current_updated_at
      true
    else
      false
    end
  end
end

def updated_at(paths)

def updated_at(paths)
  @updated_at || max_mtime(paths) || Time.at(0)
end

def watched

def watched
  @watched || begin
    all = @files.select { |f| File.exist?(f) }
    all.concat(Dir[@glob]) if @glob
    all
  end
end