Class Camping::Reloader
In: lib/camping/reloader.rb
Parent: Object

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.

Methods

==   apps   load_apps   load_file   name   new   reload   reload!   remove_apps  

Attributes

file  [R] 

Public Class methods

[Source]

    # File lib/camping/reloader.rb, line 37
37:     def initialize(file, &blk)
38:       @file = file
39:       @mtime = Time.at(0)
40:       @requires = []
41:       @apps = {}
42:       @callback = blk
43:     end

Public Instance methods

Checks if both scripts watches the same file.

[Source]

     # File lib/camping/reloader.rb, line 128
128:     def ==(other)
129:       @file == other.file
130:     end

[Source]

     # File lib/camping/reloader.rb, line 132
132:     def apps
133:       if @app
134:         { name => @app }
135:       else
136:         @apps
137:       end
138:     end

Loads the apps availble in this script. Use apps to get the loaded apps.

[Source]

    # File lib/camping/reloader.rb, line 56
56:     def load_apps(old_apps)
57:       all_requires = $LOADED_FEATURES.dup
58:       all_apps = Camping::Apps.dup
59: 
60:       load_file
61:     ensure
62:       @requires = []
63:       dirs = []
64:       new_apps = Camping::Apps - all_apps
65:       
66:       @apps = new_apps.inject({}) do |hash, app|
67:         if file = app.options[:__FILE__]
68:           full = File.expand_path(file)
69:           @requires << [file, full]
70:           dirs << full.sub(/\.[^.]+$/, '')
71:         end
72: 
73:         key = app.name.to_sym
74:         hash[key] = app
75:         
76:         if !old_apps.include?(key)
77:           @callback.call(app) if @callback
78:           app.create if app.respond_to?(:create)
79:         end
80: 
81:         hash
82:       end
83: 
84:       ($LOADED_FEATURES - all_requires).each do |req|
85:         full = full_path(req)
86:         @requires << [req, full] if dirs.any? { |x| full.index(x) == 0 }
87:       end
88: 
89:       @mtime = mtime
90:       
91:       self
92:     end

[Source]

     # File lib/camping/reloader.rb, line 94
 94:     def load_file
 95:       if @file =~ /\.ru$/
 96:         @app,_ = Rack::Builder.parse_file(@file)
 97:       else
 98:         load(@file)
 99:       end
100:     end

[Source]

    # File lib/camping/reloader.rb, line 45
45:     def name
46:       @name ||= begin
47:         base = @file.dup
48:         base = File.dirname(base) if base =~ /\bconfig\.ru$/
49:         base.sub!(/\.[^.]+/, '')
50:         File.basename(base).to_sym
51:       end
52:     end

Reloads the file if needed. No harm is done by calling this multiple times, so feel free call just to be sure.

[Source]

     # File lib/camping/reloader.rb, line 118
118:     def reload
119:       return if @mtime >= mtime rescue nil
120:       reload!
121:     end

[Source]

     # File lib/camping/reloader.rb, line 123
123:     def reload!
124:       load_apps(remove_apps)
125:     end

Removes all the apps defined in this script.

[Source]

     # File lib/camping/reloader.rb, line 103
103:     def remove_apps
104:       @requires.each do |(path, full)|
105:         $LOADED_FEATURES.delete(path)
106:       end
107: 
108:       @apps.each do |name, app|
109:         Camping::Apps.delete(app)
110:         Object.send :remove_const, name
111:       end.dup
112:     ensure
113:       @apps.clear
114:     end

[Validate]