rack-unreloader 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +6 -0
- data/README.rdoc +11 -2
- data/lib/rack/unreloader.rb +39 -3
- data/spec/unreloader_spec.rb +67 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eacfdd6cd0d57685d8835bcfbc35bb716cc0241
|
4
|
+
data.tar.gz: eed0b264873367b89e234d9b74f1b47805ce48f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61c47de205a000b7048f516d3c841cc4dc20c88b565be214330e868a3c47a7e2561f90d4bcb7a9ed23eb10d62133639ae0e437e23b528a2f4ff362c8fb179def
|
7
|
+
data.tar.gz: 0eb1923fb9131e0a84b4ad020b54538bbd69ae7665bcf6f3bd5dc328685491a67aaec2c522baa01a00e1a4669bbebe0f803d65bc00f8f9eea31b1cd38e40fa40
|
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
@@ -146,10 +146,19 @@ full path:
|
|
146
146
|
|
147
147
|
Unreloader.require '/path/to/app.rb'
|
148
148
|
|
149
|
-
You can use the usual file globbing:
|
149
|
+
You can use the usual file globbing to load multiple files:
|
150
150
|
|
151
151
|
Unreloader.require 'models/*.rb'
|
152
152
|
|
153
|
+
If you want to load all files in a given directory you should just give
|
154
|
+
the directory path:
|
155
|
+
|
156
|
+
Unreloader.require 'models'
|
157
|
+
|
158
|
+
The advantage for doing this is that new files added to the directory will be
|
159
|
+
picked up automatically, and files deleted from the directory will be removed
|
160
|
+
automatically.
|
161
|
+
|
153
162
|
== Speeding Things Up
|
154
163
|
|
155
164
|
By default, <tt>Rack::Unreloader</tt> uses +ObjectSpace+ before and after requiring each
|
@@ -165,7 +174,7 @@ of constants to unload. If you do this, <tt>Rack::Unreloader</tt> will no longe
|
|
165
174
|
to use +ObjectSpace+, which substantially speeds up startup. For example, if all of
|
166
175
|
your models just use a capitalized version of the filename:
|
167
176
|
|
168
|
-
Unreloader.require('models
|
177
|
+
Unreloader.require('models'){|f| File.basename(f).sub(/\.rb\z/, '').capitalize}
|
169
178
|
|
170
179
|
== History
|
171
180
|
|
data/lib/rack/unreloader.rb
CHANGED
@@ -21,6 +21,12 @@ module Rack
|
|
21
21
|
# with values being the last modified time (or nil if the file has not yet been loaded).
|
22
22
|
@monitor_files = {}
|
23
23
|
|
24
|
+
# Hash of directories being monitored for changes, keyed by absolute path of directory name,
|
25
|
+
# with values being the an array with the last modified time (or nil if the directory has not
|
26
|
+
# yet been loaded), an array of files in the directory, and a block to pass to
|
27
|
+
# require_dependency for new files.
|
28
|
+
@monitor_dirs = {}
|
29
|
+
|
24
30
|
# Hash of procs returning constants defined in files, keyed by absolute path
|
25
31
|
# of file name. If there is no proc, must call ObjectSpace before and after
|
26
32
|
# loading files to detect changes, which is slower.
|
@@ -55,6 +61,10 @@ module Rack
|
|
55
61
|
# If there are any changed files, reload them. If there are no changed
|
56
62
|
# files, do nothing.
|
57
63
|
def reload!
|
64
|
+
@monitor_dirs.keys.each do |dir|
|
65
|
+
check_monitor_dir(dir)
|
66
|
+
end
|
67
|
+
|
58
68
|
@monitor_files.to_a.each do |file, time|
|
59
69
|
if file_changed?(file, time)
|
60
70
|
safe_load(file)
|
@@ -62,6 +72,25 @@ module Rack
|
|
62
72
|
end
|
63
73
|
end
|
64
74
|
|
75
|
+
# Check a monitored directory for changes, adding new files and removing
|
76
|
+
# deleted files.
|
77
|
+
def check_monitor_dir(dir)
|
78
|
+
time, files, block = @monitor_dirs[dir]
|
79
|
+
|
80
|
+
if file_changed?(dir, time)
|
81
|
+
cur_files = Dir.new(dir).grep(/\.rb\z/).map{|f| F.join(dir, f)}
|
82
|
+
|
83
|
+
(files - cur_files).each do |f|
|
84
|
+
remove(f)
|
85
|
+
@monitor_files.delete(f)
|
86
|
+
end
|
87
|
+
|
88
|
+
require_dependencies(cur_files - files, &block)
|
89
|
+
|
90
|
+
files.replace(cur_files)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
65
94
|
# Require the given dependencies, monitoring them for changes.
|
66
95
|
# Paths should be a file glob or an array of file globs.
|
67
96
|
def require_dependencies(paths, &block)
|
@@ -76,8 +105,15 @@ module Rack
|
|
76
105
|
uniq.
|
77
106
|
each do |file|
|
78
107
|
|
79
|
-
|
80
|
-
|
108
|
+
if F.directory?(file)
|
109
|
+
@monitor_dirs[file] = [nil, [], block]
|
110
|
+
check_monitor_dir(file)
|
111
|
+
next
|
112
|
+
else
|
113
|
+
@constants_defined[file] = block
|
114
|
+
@monitor_files[file] = nil
|
115
|
+
end
|
116
|
+
|
81
117
|
begin
|
82
118
|
safe_load(file, options)
|
83
119
|
rescue NameError, LoadError => error
|
@@ -285,7 +321,7 @@ module Rack
|
|
285
321
|
# Call the app with the environment.
|
286
322
|
def call(env)
|
287
323
|
if @cooldown && Time.now > @last + @cooldown
|
288
|
-
Thread.exclusive{@reloader.reload!}
|
324
|
+
Thread.respond_to?(:exclusive) ? Thread.exclusive{@reloader.reload!} : @reloader.reload!
|
289
325
|
@last = Time.now
|
290
326
|
end
|
291
327
|
@app_block.call.call(env)
|
data/spec/unreloader_spec.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), '../lib/rack/unreloader')
|
2
2
|
|
3
|
+
if defined?(RSpec)
|
4
|
+
require 'rspec/version'
|
5
|
+
if RSpec::Version::STRING >= '2.11.0'
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.expect_with :rspec do |c|
|
8
|
+
c.syntax = :should
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
3
14
|
module ModifiedAt
|
4
15
|
def set_modified_time(file, time)
|
5
16
|
modified_times[File.expand_path(file)] = time
|
@@ -256,4 +267,60 @@ describe Rack::Unreloader do
|
|
256
267
|
"Error removing constant: Foo",
|
257
268
|
%r{\ARemoved feature .*/spec/app.rb\z}
|
258
269
|
end
|
270
|
+
|
271
|
+
describe "with a directory" do
|
272
|
+
before do
|
273
|
+
Dir.mkdir('spec/dir')
|
274
|
+
end
|
275
|
+
|
276
|
+
after do
|
277
|
+
Dir['spec/dir/*.rb'].each{|f| File.delete(f)}
|
278
|
+
Dir.rmdir('spec/dir')
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should pick up changes to files in that directory" do
|
282
|
+
base_ru
|
283
|
+
update_app("class App; @a = {}; def self.call(env=nil) @a end; end; RU.require 'spec/dir'")
|
284
|
+
update_app("App.call[:foo] = 1", 'spec/dir/a.rb')
|
285
|
+
@ru.require('spec/app.rb')
|
286
|
+
ru.call({}).should == {:foo=>1}
|
287
|
+
update_app("App.call[:foo] = 2", 'spec/dir/a.rb')
|
288
|
+
ru.call({}).should == {:foo=>2}
|
289
|
+
log_match %r{\ALoading.*spec/app\.rb\z},
|
290
|
+
%r{\ALoading.*spec/dir/a\.rb\z},
|
291
|
+
%r{\ANew classes in .*spec/app\.rb: App\z},
|
292
|
+
%r{\ANew features in .*spec/app\.rb: .*spec/dir/a\.rb\z},
|
293
|
+
%r{\AReloading .*/spec/dir/a.rb\z},
|
294
|
+
%r{\ARemoved feature .*/spec/dir/a.rb\z}
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should pick up new files added to the directory" do
|
298
|
+
base_ru
|
299
|
+
update_app("class App; @a = {}; def self.call(env=nil) @a end; end; RU.require 'spec/dir'")
|
300
|
+
@ru.require('spec/app.rb')
|
301
|
+
ru.call({}).should == {}
|
302
|
+
update_app("App.call[:foo] = 2", 'spec/dir/a.rb')
|
303
|
+
ru.call({}).should == {:foo=>2}
|
304
|
+
log_match %r{\ALoading.*spec/app\.rb\z},
|
305
|
+
%r{\ANew classes in .*spec/app\.rb: App\z},
|
306
|
+
%r{\ALoading.*spec/dir/a\.rb\z}
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should drop files deleted from the directory" do
|
310
|
+
base_ru
|
311
|
+
update_app("class App; @a = {}; def self.call(env=nil) @a end; end; RU.require 'spec/dir'")
|
312
|
+
update_app("App.call[:foo] = 1", 'spec/dir/a.rb')
|
313
|
+
@ru.require('spec/app.rb')
|
314
|
+
ru.call({}).should == {:foo=>1}
|
315
|
+
File.delete('spec/dir/a.rb')
|
316
|
+
update_app("App.call[:foo] = 2", 'spec/dir/b.rb')
|
317
|
+
ru.call({}).should == {:foo=>2}
|
318
|
+
log_match %r{\ALoading.*spec/app\.rb\z},
|
319
|
+
%r{\ALoading.*spec/dir/a\.rb\z},
|
320
|
+
%r{\ANew classes in .*spec/app\.rb: App\z},
|
321
|
+
%r{\ANew features in .*spec/app\.rb: .*spec/dir/a\.rb\z},
|
322
|
+
%r{\ARemoved feature .*/spec/dir/a.rb\z},
|
323
|
+
%r{\ALoading.*spec/dir/b\.rb\z}
|
324
|
+
end
|
325
|
+
end
|
259
326
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-unreloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
Rack::Unreloader is a rack middleware that reloads application files when it
|