Class: Camping::Reloader

Inherits:
Object
  • Object
show all
Defined in:
lib/camping/reloader.rb

Overview

for alterations.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(script) ⇒ Reloader

Creates the reloader, assigns a script to it and initially loads the application. Pass in the full path to the script, otherwise the script will be loaded relative to the current working directory.



36
37
38
39
40
41
# File 'lib/camping/reloader.rb', line 36

def initialize(script)
    @script = File.expand_path(script)
    @mount = File.basename(script, '.rb')
    @requires = nil
    load_app
end

Instance Attribute Details

#klassObject

Returns the value of attribute klass.



31
32
33
# File 'lib/camping/reloader.rb', line 31

def klass
  @klass
end

#mountObject

Returns the value of attribute mount.



31
32
33
# File 'lib/camping/reloader.rb', line 31

def mount
  @mount
end

#mtimeObject

The timestamp of the most recently modified app dependency.



87
88
89
# File 'lib/camping/reloader.rb', line 87

def mtime
  @mtime
end

#requiresObject

Returns the value of attribute requires.



31
32
33
# File 'lib/camping/reloader.rb', line 31

def requires
  @requires
end

Class Method Details

.conditional_connectObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/camping/reloader.rb', line 135

def conditional_connect
    # If database models are present, `autoload?` will return nil.
    unless Camping::Models.autoload? :Base
        require 'logger'
        require 'camping/session'
        Camping::Models::Base.establish_connection @database if @database

        case @log
        when Logger
            Camping::Models::Base.logger = @log
        when String
            Camping::Models::Base.logger = Logger.new(@log == "-" ? STDOUT : @log)
        end

        begin
            Camping::Models::Session.create_schema
        rescue MissingSourceFile
            puts "** #$0 stopped: SQLite3 not found, please install."
            puts "** See http://code.whytheluckystiff.net/camping/wiki/BeAlertWhenOnSqlite3 for instructions."
            exit
        end

        if @database and @database[:adapter] == 'sqlite3'
            begin
                require 'sqlite3_api'
            rescue LoadError
                puts "!! Your SQLite3 adapter isn't a compiled extension."
                abort "!! Please check out http://code.whytheluckystiff.net/camping/wiki/BeAlertWhenOnSqlite3 for tips."
            end
        end
    end
end

.database=(db) ⇒ Object



129
130
131
# File 'lib/camping/reloader.rb', line 129

def database=(db)
    @database = db
end

.log=(log) ⇒ Object



132
133
134
# File 'lib/camping/reloader.rb', line 132

def log=(log)
    @log = log
end

Instance Method Details

#find_app(title) ⇒ Object

Find the application, based on the script name.



44
45
46
# File 'lib/camping/reloader.rb', line 44

def find_app(title)
    @klass = Object.const_get(Object.constants.grep(/^#{title}$/i)[0]) rescue nil
end

#load_appObject

Loads (or reloads) the application. The reloader will take care of calling this for you. You can certainly call it yourself if you feel it’s warranted.



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
# File 'lib/camping/reloader.rb', line 57

def load_app
    title = File.basename(@script)[/^([\w_]+)/,1].gsub /_/,'' 
    begin
        all_requires = $LOADED_FEATURES.dup
        load @script
        @requires = ($LOADED_FEATURES - all_requires).select do |req|
            req.index(File.basename(@script) + "/") == 0 || req.index(title + "/") == 0
        end
    rescue Exception => e
        puts "!! trouble loading #{title}: [#{e.class}] #{e.message}"
        puts e.backtrace.join("\n")
        find_app title
        remove_app
        return
    end

    @mtime = mtime
    find_app title
    unless @klass and @klass.const_defined? :C
        puts "!! trouble loading #{title}: not a Camping app, no #{title.capitalize} module found"
        remove_app
        return
    end
    
    Reloader.conditional_connect
    @klass.create if @klass.respond_to? :create
    @klass
end

#reload_appObject

Conditional reloading of the app. This gets called on each request and only reloads if the modification times on any of the files is updated.



101
102
103
104
105
106
107
108
109
110
# File 'lib/camping/reloader.rb', line 101

def reload_app 
    return if @klass and @mtime and mtime <= @mtime

    if @requires
        @requires.each { |req| $LOADED_FEATURES.delete(req) }
    end
    k = @klass
    Object.send :remove_const, k.name if k
    load_app
end

#remove_appObject

If the file isn’t found, if we need to remove the app from the global namespace, this will be sure to do so and set @klass to nil.



50
51
52
53
# File 'lib/camping/reloader.rb', line 50

def remove_app
    Object.send :remove_const, @klass.name if @klass
    @klass = nil
end

#run(*a) ⇒ Object

Conditionally reloads (using reload_app.) Then passes the request through to the wrapped Camping app.



114
115
116
117
118
119
120
121
# File 'lib/camping/reloader.rb', line 114

def run(*a)
    reload_app
    if @klass
        @klass.run(*a) 
    else
        Camping.run(*a)
    end
end

#view_sourceObject

Returns source code for the main script in the application.



124
125
126
# File 'lib/camping/reloader.rb', line 124

def view_source
    File.read(@script)
end