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 availble in this script.
- #load_file ⇒ Object
- #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 |
# 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.
128 129 130 |
# File 'lib/camping/reloader.rb', line 128 def ==(other) @file == other.file end |
#apps ⇒ Object
132 133 134 135 136 137 138 |
# File 'lib/camping/reloader.rb', line 132 def apps if @app { name => @app } else @apps end end |
#load_apps(old_apps) ⇒ Object
Loads the apps availble in this script. Use apps
to get the loaded apps.
56 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 |
# File 'lib/camping/reloader.rb', line 56 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
94 95 96 97 98 99 100 |
# File 'lib/camping/reloader.rb', line 94 def load_file if @file =~ /\.ru$/ @app,_ = Rack::Builder.parse_file(@file) else load(@file) end end |
#name ⇒ Object
45 46 47 48 49 50 51 52 |
# File 'lib/camping/reloader.rb', line 45 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.
118 119 120 121 |
# File 'lib/camping/reloader.rb', line 118 def reload return if @mtime >= mtime rescue nil reload! end |
#reload! ⇒ Object
123 124 125 |
# File 'lib/camping/reloader.rb', line 123 def reload! load_apps(remove_apps) end |
#remove_apps ⇒ Object
Removes all the apps defined in this script.
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/camping/reloader.rb', line 103 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 |