class Rack::Unreloader
Reloading application that unloads constants before reloading the relevant files, calling the new rack app if it gets reloaded.
Constants
- F
Reference to ::File as File would return Rack::File by default.
- MUTEX
Mutex used to synchronize reloads
Attributes
The Rack::Unreloader::Reloader
instead related to this instance, if one.
Public Class Methods
Given the list of paths, find all matching files, or matching ruby files in subdirecories if given a directory, and return an array of expanded paths.
# File lib/rack/unreloader.rb 17 def self.expand_directory_paths(paths) 18 expand_paths(paths). 19 map{|f| F.directory?(f) ? ruby_files(f) : f}. 20 flatten 21 end
Given the path glob or array of path globs, find all matching files or directories, and return an array of expanded paths.
# File lib/rack/unreloader.rb 25 def self.expand_paths(paths) 26 Array(paths). 27 flatten. 28 map{|path| Dir.glob(path).sort_by{|filename| filename.count('/')}}. 29 flatten. 30 map{|path| F.expand_path(path)}. 31 uniq 32 end
Setup the reloader. Options:
- :cooldown
-
The number of seconds to wait between checks for changed files. Defaults to 1. Set to nil/false to not check for changed files.
- :reload
-
Set to false to not setup a reloader, and just have require work directly. Should be set to false in production mode.
- :logger
-
A Logger instance which will log information related to reloading.
- :subclasses
-
A string or array of strings of class names that should be unloaded. Any classes that are not subclasses of these classes will not be unloaded. This also handles modules, but module names given must match exactly, since modules don't have superclasses.
# File lib/rack/unreloader.rb 57 def initialize(opts={}, &block) 58 @app_block = block 59 if opts.fetch(:reload, true) 60 @cooldown = opts.fetch(:cooldown, 1) 61 @handle_reload_errors = opts[:handle_reload_errors] 62 @last = Time.at(0) 63 Kernel.require 'rack/unreloader/reloader' 64 @reloader = Reloader.new(opts) 65 reload! 66 else 67 @reloader = @cooldown = @handle_reload_errors = false 68 end 69 end
The .rb files in the given directory or any subdirectory.
# File lib/rack/unreloader.rb 35 def self.ruby_files(dir) 36 files = [] 37 Find.find(dir) do |f| 38 files << f if f =~ /\.rb\z/ 39 end 40 files.sort 41 end
Public Instance Methods
If the cooldown time has been passed, reload any application files that have changed. Call the app with the environment.
# File lib/rack/unreloader.rb 73 def call(env) 74 if @cooldown && Time.now > @last + @cooldown 75 begin 76 MUTEX.synchronize{reload!} 77 rescue StandardError, ScriptError => e 78 raise unless @handle_reload_errors 79 content = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}" 80 return [500, {'Content-Type' => 'text/plain', 'Content-Length' => content.bytesize.to_s}, [content]] 81 end 82 @last = Time.now 83 end 84 @app_block.call.call(env) 85 end
Records that each path in files
depends on dependency
. If there is a modification to dependency
, all related files will be reloaded after dependency
is reloaded. Both dependency
and each entry in files
can be an array of path globs.
# File lib/rack/unreloader.rb 100 def record_dependency(dependency, *files) 101 if @reloader 102 files = Unreloader.expand_paths(files) 103 Unreloader.expand_paths(dependency).each do |path| 104 @reloader.record_dependency(path, files) 105 end 106 end 107 end
Record that a class is split into multiple files. main_file
should be the main file for the class, which should require all of the other files. files
should be a list of all other files that make up the class.
# File lib/rack/unreloader.rb 112 def record_split_class(main_file, *files) 113 if @reloader 114 files = Unreloader.expand_paths(files) 115 files.each do |file| 116 record_dependency(file, main_file) 117 end 118 @reloader.skip_reload(files) 119 end 120 end
Reload the application, checking for changed files and reloading them.
# File lib/rack/unreloader.rb 123 def reload! 124 @reloader.reload! if @reloader 125 end
Add a file glob or array of file globs to monitor for changes.
# File lib/rack/unreloader.rb 88 def require(paths, &block) 89 if @reloader 90 @reloader.require_dependencies(paths, &block) 91 else 92 Unreloader.expand_directory_paths(paths).each{|f| super(f)} 93 end 94 end
Strip the given path prefix from all absolute paths used by the reloader. This is designed when chrooting an application.
Options:
- :strip_core
-
Also strips the path prefix from $LOADED_FEATURES and
$LOAD_PATH.
# File lib/rack/unreloader.rb 133 def strip_path_prefix(path_prefix, opts={}) 134 if @reloader 135 @reloader.strip_path_prefix(path_prefix) 136 end 137 end