Class: Camping::Reloader
Overview
The Camping Reloader
Camping apps are generally small and predictable. Many Camping apps are contained within a single file. Larger apps are split into a handful of other Ruby libraries within the same directory.
Since Camping apps (and their dependencies) are loaded with Ruby’s require method, there is a record of them in $LOADED_FEATURES. Which leaves a perfect space for this class to manage auto-reloading an app if any of its immediate dependencies changes.
Wrapping Your Apps
Since bin/camping and the Camping::Server class already use the Reloader, you probably don’t need to hack it on your own. But, if you’re rolling your own situation, here’s how.
Rather than this:
require 'yourapp'
Use this:
require 'camping/reloader'
reloader = Camping::Reloader.new('/path/to/yourapp.rb')
blog = reloader.apps[:Blog]
wiki = reloader.apps[:Wiki]
The blog
and wiki
objects will behave exactly like your Blog and Wiki, but they will update themselves if yourapp.rb changes.
You can also give Reloader more than one script.
Instance Attribute Summary collapse
-
#file ⇒ Object
readonly
Returns the value of attribute file.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Checks if both scripts watches the same file.
- #apps ⇒ Object
-
#initialize(file, &blk) ⇒ Reloader
constructor
A new instance of Reloader.
-
#load_apps(old_apps) ⇒ Object
Loads the apps available in this script.
-
#load_file ⇒ Object
load_file.
- #name ⇒ Object
-
#reload ⇒ Object
Reloads the file if needed.
- #reload! ⇒ Object
-
#remove_apps ⇒ Object
Removes all the apps defined in this script.
Constructor Details
#initialize(file, &blk) ⇒ Reloader
Returns a new instance of Reloader.
37 38 39 40 41 42 43 44 |
# File 'lib/camping/reloader.rb', line 37 def initialize(file, &blk) @file = file @mtime = Time.at(0) @requires = [] @apps = {} @callback = blk end |
Instance Attribute Details
#file ⇒ Object (readonly)
Returns the value of attribute file.
35 36 37 |
# File 'lib/camping/reloader.rb', line 35 def file @file end |
Instance Method Details
#==(other) ⇒ Object
Checks if both scripts watches the same file.
133 134 135 |
# File 'lib/camping/reloader.rb', line 133 def ==(other) @file == other.file end |
#apps ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/camping/reloader.rb', line 137 def apps if @app { name => @app } else @apps end end |
#load_apps(old_apps) ⇒ Object
Loads the apps available in this script. Use apps
to get the loaded apps.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/camping/reloader.rb', line 57 def load_apps(old_apps) all_requires = $LOADED_FEATURES.dup all_apps = Camping::Apps.dup load_file ensure @requires = [] dirs = [] new_apps = Camping::Apps - all_apps @apps = new_apps.inject({}) do |hash, app| if file = app.[:__FILE__] full = File.(file) @requires << [file, full] dirs << full.sub(/\.[^.]+$/, '') end key = app.name.to_sym hash[key] = app if !old_apps.include?(key) @callback.call(app) if @callback app.create if app.respond_to?(:create) end hash end ($LOADED_FEATURES - all_requires).each do |req| full = full_path(req) @requires << [req, full] if dirs.any? { |x| full.index(x) == 0 } end @mtime = mtime self end |
#load_file ⇒ Object
load_file
Rack::Builder is mainly used to parse a config.ru file and to build a rack app with middleware from that.
99 100 101 102 103 104 105 |
# File 'lib/camping/reloader.rb', line 99 def load_file if @file =~ /\.ru$/ @app = Rack::Builder.parse_file(@file) else load(@file) end end |
#name ⇒ Object
46 47 48 49 50 51 52 53 |
# File 'lib/camping/reloader.rb', line 46 def name @name ||= begin base = @file.dup base = File.dirname(base) if base =~ /\bconfig\.ru$/ base.sub!(/\.[^.]+/, '') File.basename(base).to_sym end end |
#reload ⇒ Object
Reloads the file if needed. No harm is done by calling this multiple times, so feel free call just to be sure.
123 124 125 126 |
# File 'lib/camping/reloader.rb', line 123 def reload return if @mtime >= mtime rescue nil reload! end |
#reload! ⇒ Object
128 129 130 |
# File 'lib/camping/reloader.rb', line 128 def reload! load_apps(remove_apps) end |
#remove_apps ⇒ Object
Removes all the apps defined in this script.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/camping/reloader.rb', line 108 def remove_apps @requires.each do |(path, full)| $LOADED_FEATURES.delete(path) end @apps.each do |name, app| Camping::Apps.delete(app) Object.send :remove_const, name end.dup ensure @apps.clear end |