dassets 0.7.0 → 0.8.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.
- data/README.md +1 -1
- data/dassets.gemspec +1 -1
- data/lib/dassets/asset_file.rb +8 -10
- data/lib/dassets/cache.rb +45 -0
- data/lib/dassets/config.rb +39 -0
- data/lib/dassets/file_store.rb +26 -23
- data/lib/dassets/source_file.rb +14 -13
- data/lib/dassets/source_proxy.rb +4 -8
- data/lib/dassets/version.rb +1 -1
- data/lib/dassets.rb +4 -46
- data/test/helper.rb +18 -1
- data/test/system/rack_tests.rb +4 -2
- data/test/unit/asset_file_tests.rb +27 -4
- data/test/unit/cache_tests.rb +53 -0
- data/test/unit/config_tests.rb +15 -5
- data/test/unit/dassets_tests.rb +11 -2
- data/test/unit/engine_tests.rb +1 -1
- data/test/unit/file_store_tests.rb +40 -9
- data/test/unit/server/request_tests.rb +3 -1
- data/test/unit/server/response_tests.rb +4 -2
- data/test/unit/source_file_tests.rb +7 -0
- data/test/unit/source_proxy_tests.rb +49 -4
- data/test/unit/source_tests.rb +2 -0
- metadata +11 -12
- data/lib/dassets/default_cache.rb +0 -29
- data/test/support/config/assets.rb +0 -20
- data/test/unit/default_cache_tests.rb +0 -27
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Dassets.configure do |c|
|
|
20
20
|
# (optional) tell Dassets where to store digested asset files
|
21
21
|
# if none given, Dassets will not write any digested output
|
22
22
|
# use this to "cache" digested assets to the public dir (for example)
|
23
|
-
c.file_store '/path/to/public' # default: `
|
23
|
+
c.file_store '/path/to/public' # default: `FileStore::NullStore.new`
|
24
24
|
|
25
25
|
end
|
26
26
|
```
|
data/dassets.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.add_development_dependency("assert", ["~> 2.
|
20
|
+
gem.add_development_dependency("assert", ["~> 2.4"])
|
21
21
|
gem.add_development_dependency('assert-rack-test', ["~> 1.0"])
|
22
22
|
gem.add_development_dependency("sinatra", ["~> 1.4"])
|
23
23
|
|
data/lib/dassets/asset_file.rb
CHANGED
@@ -21,39 +21,37 @@ class Dassets::AssetFile
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def url
|
24
|
-
|
25
|
-
|
26
|
-
File.join(@dirname, url_basename).sub(/^\.\//, '').sub(/^\//, '')
|
27
|
-
end
|
24
|
+
url_basename = "#{@basename}-#{self.fingerprint}#{@extname}"
|
25
|
+
File.join(@dirname, url_basename).sub(/^\.\//, '').sub(/^\//, '')
|
28
26
|
end
|
29
27
|
|
30
28
|
def href
|
31
|
-
|
29
|
+
"/#{self.url}"
|
32
30
|
end
|
33
31
|
|
34
32
|
def fingerprint
|
35
33
|
return nil if !self.exists?
|
36
|
-
@
|
34
|
+
@source_proxy.fingerprint
|
37
35
|
end
|
38
36
|
|
39
37
|
def content
|
40
38
|
return nil if !self.exists?
|
41
|
-
@
|
39
|
+
@source_proxy.content
|
42
40
|
end
|
43
41
|
|
44
42
|
def mtime
|
45
43
|
return nil if !self.exists?
|
46
|
-
@
|
44
|
+
@source_proxy.mtime.httpdate
|
47
45
|
end
|
48
46
|
|
49
47
|
def size
|
50
48
|
return nil if !self.exists?
|
51
|
-
|
49
|
+
Rack::Utils.bytesize(self.content)
|
52
50
|
end
|
53
51
|
|
54
52
|
def mime_type
|
55
53
|
return nil if !self.exists?
|
56
|
-
|
54
|
+
Rack::Mime.mime_type(@extname)
|
57
55
|
end
|
58
56
|
|
59
57
|
def exists?
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Dassets; end
|
2
|
+
module Dassets::Cache
|
3
|
+
|
4
|
+
class MemCache
|
5
|
+
require 'thread'
|
6
|
+
|
7
|
+
# this is a thread-safe in-memory cache for use with the `SourceCache`
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@hash = {}
|
11
|
+
@write_mutex = ::Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def keys
|
15
|
+
@hash.keys
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
@hash[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(key, value)
|
23
|
+
@write_mutex.synchronize{ @hash[key] = value }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class NoCache
|
29
|
+
|
30
|
+
# This is a no-op cache object. This is the default cache in use and "turns
|
31
|
+
# off caching.
|
32
|
+
|
33
|
+
def keys
|
34
|
+
[]
|
35
|
+
end
|
36
|
+
|
37
|
+
def [](key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def []=(key, value)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'ns-options'
|
3
|
+
require 'dassets/cache'
|
4
|
+
require 'dassets/file_store'
|
5
|
+
require 'dassets/source'
|
6
|
+
|
7
|
+
module Dassets
|
8
|
+
|
9
|
+
class Config
|
10
|
+
include NsOptions::Proxy
|
11
|
+
|
12
|
+
option :file_store, FileStore, :default => proc{ FileStore::NullStore.new }
|
13
|
+
option :cache, :default => proc{ Cache::NoCache.new }
|
14
|
+
|
15
|
+
attr_reader :sources, :combinations
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
super
|
19
|
+
@sources = []
|
20
|
+
@combinations = Hash.new{ |h, k| [k] } # digest pass-thru if none defined
|
21
|
+
end
|
22
|
+
|
23
|
+
def source(path, &block)
|
24
|
+
@sources << Source.new(path).tap{ |s| block.call(s) if block }
|
25
|
+
end
|
26
|
+
|
27
|
+
def combination(key_digest_path, value_digest_paths)
|
28
|
+
@combinations[key_digest_path.to_s] = [*value_digest_paths]
|
29
|
+
end
|
30
|
+
|
31
|
+
def combination?(key_digest_path)
|
32
|
+
# a digest path is only considered a combination is it is not the default
|
33
|
+
# pass-thru above
|
34
|
+
@combinations[key_digest_path.to_s] != [key_digest_path]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/dassets/file_store.rb
CHANGED
@@ -1,35 +1,38 @@
|
|
1
1
|
require 'thread'
|
2
2
|
|
3
|
-
module Dassets
|
4
|
-
class Dassets::FileStore
|
5
|
-
attr_reader :root
|
3
|
+
module Dassets
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
class FileStore
|
6
|
+
attr_reader :root
|
7
|
+
|
8
|
+
def initialize(root)
|
9
|
+
@root = root
|
10
|
+
@save_mutex = ::Mutex.new
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def save(url, &block)
|
14
|
+
@save_mutex.synchronize do
|
15
|
+
store_path(url).tap do |path|
|
16
|
+
FileUtils.mkdir_p(File.dirname(path))
|
17
|
+
File.open(path, "w"){ |f| f.write(block.call) }
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def store_path(url)
|
23
|
+
File.join(@root, url)
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
+
class NullStore < FileStore
|
27
|
+
def initialize
|
28
|
+
super('')
|
29
|
+
end
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
def save(url, &block)
|
32
|
+
store_path(url) # no-op, just return the store path like the base does
|
33
|
+
end
|
34
|
+
end
|
31
35
|
|
32
|
-
def save(url, &block)
|
33
|
-
store_path(url) # no-op, just return the store path like the base does
|
34
36
|
end
|
37
|
+
|
35
38
|
end
|
data/lib/dassets/source_file.rb
CHANGED
@@ -47,7 +47,7 @@ module Dassets
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def compiled
|
50
|
-
@
|
50
|
+
@ext_list.inject(read_file(@file_path)) do |content, ext|
|
51
51
|
self.source.engines[ext].compile(content)
|
52
52
|
end
|
53
53
|
end
|
@@ -89,26 +89,27 @@ module Dassets
|
|
89
89
|
def initialize(digest_path, cache = nil)
|
90
90
|
@file_path, @ext_list = '', []
|
91
91
|
@digest_path = digest_path
|
92
|
-
@
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
if Dassets.config.combination?(@digest_path)
|
97
|
-
source_proxy = SourceProxy.new(@digest_path, cache)
|
98
|
-
@source_compiled = source_proxy.content
|
99
|
-
@source_exists = source_proxy.exists?
|
100
|
-
@source_mtime = source_proxy.mtime
|
92
|
+
@source_proxy = if Dassets.config.combination?(@digest_path)
|
93
|
+
SourceProxy.new(@digest_path, cache)
|
94
|
+
else
|
95
|
+
NullSourceProxy.new
|
101
96
|
end
|
102
97
|
end
|
103
98
|
|
104
|
-
def compiled; @
|
105
|
-
def exists?; @
|
106
|
-
def mtime; @
|
99
|
+
def compiled; @source_proxy.content; end
|
100
|
+
def exists?; @source_proxy.exists?; end
|
101
|
+
def mtime; @source_proxy.mtime; end
|
107
102
|
|
108
103
|
def ==(other_source_file)
|
109
104
|
self.file_path == other_source_file.file_path
|
110
105
|
end
|
111
106
|
|
107
|
+
class NullSourceProxy
|
108
|
+
def content; nil; end
|
109
|
+
def exists?; false; end
|
110
|
+
def mtime; nil; end
|
111
|
+
end
|
112
|
+
|
112
113
|
end
|
113
114
|
|
114
115
|
end
|
data/lib/dassets/source_proxy.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'digest/md5'
|
2
|
+
require 'dassets/cache'
|
2
3
|
require 'dassets/source_file'
|
3
4
|
|
4
5
|
module Dassets; end
|
@@ -8,7 +9,7 @@ class Dassets::SourceProxy
|
|
8
9
|
|
9
10
|
def initialize(digest_path, cache = nil)
|
10
11
|
@digest_path = digest_path
|
11
|
-
@cache = cache || NoCache.new
|
12
|
+
@cache = cache || Dassets::Cache::NoCache.new
|
12
13
|
@source_files = get_source_files(@digest_path, @cache)
|
13
14
|
end
|
14
15
|
|
@@ -35,11 +36,11 @@ class Dassets::SourceProxy
|
|
35
36
|
private
|
36
37
|
|
37
38
|
def source_content
|
38
|
-
@
|
39
|
+
@source_files.map{ |f| f.compiled }.join("\n")
|
39
40
|
end
|
40
41
|
|
41
42
|
def source_fingerprint
|
42
|
-
|
43
|
+
Digest::MD5.new.hexdigest(source_content)
|
43
44
|
end
|
44
45
|
|
45
46
|
def get_source_files(digest_path, cache)
|
@@ -48,9 +49,4 @@ class Dassets::SourceProxy
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
class NoCache
|
52
|
-
def [](key); end
|
53
|
-
def []=(key, value); end
|
54
|
-
end
|
55
|
-
|
56
52
|
end
|
data/lib/dassets/version.rb
CHANGED
data/lib/dassets.rb
CHANGED
@@ -1,68 +1,26 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'set'
|
3
|
-
require 'ns-options'
|
4
|
-
|
5
1
|
require 'dassets/version'
|
6
|
-
require 'dassets/file_store'
|
7
|
-
require 'dassets/default_cache'
|
8
|
-
require 'dassets/source'
|
9
2
|
require 'dassets/asset_file'
|
10
|
-
|
11
|
-
ENV['DASSETS_ASSETS_FILE'] ||= 'config/assets'
|
3
|
+
require 'dassets/config'
|
12
4
|
|
13
5
|
module Dassets
|
14
6
|
|
15
|
-
def self.config;
|
7
|
+
def self.config; @config ||= Config.new; end
|
16
8
|
def self.configure(&block)
|
17
9
|
block.call(self.config)
|
18
10
|
end
|
19
11
|
|
20
12
|
def self.init
|
21
|
-
|
22
|
-
require self.config.assets_file
|
23
|
-
rescue LoadError
|
24
|
-
end
|
13
|
+
@asset_files ||= {}
|
25
14
|
end
|
26
15
|
|
27
16
|
def self.[](digest_path)
|
28
|
-
AssetFile.new(digest_path)
|
17
|
+
@asset_files[digest_path] ||= AssetFile.new(digest_path)
|
29
18
|
end
|
30
19
|
|
31
20
|
def self.source_list
|
32
21
|
SourceList.new(self.config.sources)
|
33
22
|
end
|
34
23
|
|
35
|
-
class Config
|
36
|
-
include NsOptions::Proxy
|
37
|
-
|
38
|
-
option :assets_file, Pathname, :default => ENV['DASSETS_ASSETS_FILE']
|
39
|
-
option :file_store, FileStore, :default => proc{ NullFileStore.new }
|
40
|
-
|
41
|
-
attr_reader :sources, :combinations
|
42
|
-
attr_accessor :cache
|
43
|
-
|
44
|
-
def initialize
|
45
|
-
super
|
46
|
-
@sources = []
|
47
|
-
@combinations = Hash.new{ |h, k| [k] } # digest pass-thru if none defined
|
48
|
-
@cache = DefaultCache.new
|
49
|
-
end
|
50
|
-
|
51
|
-
def source(path, &block)
|
52
|
-
@sources << Source.new(path).tap{ |s| block.call(s) if block }
|
53
|
-
end
|
54
|
-
|
55
|
-
def combination(key_digest_path, value_digest_paths)
|
56
|
-
@combinations[key_digest_path.to_s] = [*value_digest_paths]
|
57
|
-
end
|
58
|
-
|
59
|
-
def combination?(key_digest_path)
|
60
|
-
# a digest path is only considered a combination is it is not the default
|
61
|
-
# pass-thru above
|
62
|
-
@combinations[key_digest_path.to_s] != [key_digest_path]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
24
|
module SourceList
|
67
25
|
def self.new(sources)
|
68
26
|
sources.inject([]){ |list, source| list += source.files }
|
data/test/helper.rb
CHANGED
@@ -11,6 +11,23 @@ require 'pathname'
|
|
11
11
|
TEST_SUPPORT_PATH = Pathname.new(File.expand_path('../support', __FILE__))
|
12
12
|
|
13
13
|
ENV['DASSETS_TEST_MODE'] = 'yes'
|
14
|
-
|
14
|
+
|
15
15
|
require 'dassets'
|
16
|
+
|
17
|
+
@dumb_engine = Class.new(Dassets::Engine) do
|
18
|
+
def ext(in_ext); ''; end
|
19
|
+
def compile(input); "#{input}\nDUMB"; end
|
20
|
+
end
|
21
|
+
@useless_engine = Class.new(Dassets::Engine) do
|
22
|
+
def ext(in_ext); 'no-use'; end
|
23
|
+
def compile(input); "#{input}\nUSELESS"; end
|
24
|
+
end
|
25
|
+
|
26
|
+
Dassets.configure do |c|
|
27
|
+
c.source TEST_SUPPORT_PATH.join("app/assets") do |s|
|
28
|
+
s.engine 'dumb', @dumb_engine
|
29
|
+
s.engine 'useless', @useless_engine
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
16
33
|
Dassets.init
|
data/test/system/rack_tests.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'assert'
|
2
|
+
require 'dassets'
|
3
|
+
|
2
4
|
require 'assert-rack-test'
|
3
5
|
require 'fileutils'
|
4
|
-
require 'test/support/app'
|
5
6
|
require 'dassets/server'
|
7
|
+
require 'test/support/app'
|
6
8
|
|
7
9
|
module Dassets
|
8
10
|
|
@@ -46,7 +48,7 @@ module Dassets
|
|
46
48
|
FileUtils.rm(@url_file)
|
47
49
|
end
|
48
50
|
teardown do
|
49
|
-
Dassets.config.file_store =
|
51
|
+
Dassets.config.file_store = FileStore::NullStore.new
|
50
52
|
end
|
51
53
|
|
52
54
|
should "digest the asset" do
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'assert'
|
2
|
+
require 'dassets/asset_file'
|
3
|
+
|
2
4
|
require 'fileutils'
|
3
5
|
require 'dassets/file_store'
|
4
6
|
require 'dassets/source_proxy'
|
5
|
-
require 'dassets/asset_file'
|
6
7
|
|
7
8
|
class Dassets::AssetFile
|
8
9
|
|
9
|
-
class
|
10
|
+
class UnitTests < Assert::Context
|
10
11
|
desc "Dassets::AssetFile"
|
11
12
|
setup do
|
12
13
|
@asset_file = Dassets::AssetFile.new('file1.txt')
|
@@ -81,9 +82,31 @@ class Dassets::AssetFile
|
|
81
82
|
assert_equal "/nested/file1-.txt", nested.href
|
82
83
|
end
|
83
84
|
|
85
|
+
should "not memoize its attributes" do
|
86
|
+
url1 = subject.url
|
87
|
+
url2 = subject.url
|
88
|
+
assert_not_same url2, url1
|
89
|
+
|
90
|
+
href1 = subject.href
|
91
|
+
href2 = subject.href
|
92
|
+
assert_not_same href2, href1
|
93
|
+
|
94
|
+
fingerprint1 = subject.fingerprint
|
95
|
+
fingerprint2 = subject.fingerprint
|
96
|
+
assert_not_same fingerprint2, fingerprint1
|
97
|
+
|
98
|
+
content1 = subject.content
|
99
|
+
content2 = subject.content
|
100
|
+
assert_not_same content2, content1
|
101
|
+
|
102
|
+
mtime1 = subject.mtime
|
103
|
+
mtime2 = subject.mtime
|
104
|
+
assert_not_same mtime2, mtime1
|
105
|
+
end
|
106
|
+
|
84
107
|
end
|
85
108
|
|
86
|
-
class DigestTests <
|
109
|
+
class DigestTests < UnitTests
|
87
110
|
desc "being digested with an output path configured"
|
88
111
|
setup do
|
89
112
|
Dassets.config.file_store = TEST_SUPPORT_PATH.join('public').to_s
|
@@ -91,7 +114,7 @@ class Dassets::AssetFile
|
|
91
114
|
@outfile = Dassets.config.file_store.store_path(@asset_file.url)
|
92
115
|
end
|
93
116
|
teardown do
|
94
|
-
Dassets.config.file_store = Dassets::
|
117
|
+
Dassets.config.file_store = Dassets::FileStore::NullStore.new
|
95
118
|
end
|
96
119
|
|
97
120
|
should "return the asset file url" do
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'dassets/cache'
|
3
|
+
|
4
|
+
module Dassets::Cache
|
5
|
+
|
6
|
+
class UnitTests < Assert::Context
|
7
|
+
desc "Dassets::Cache"
|
8
|
+
|
9
|
+
should "define an in-memory cache handler" do
|
10
|
+
assert MemCache
|
11
|
+
end
|
12
|
+
|
13
|
+
should "define a no-op cache handler" do
|
14
|
+
assert NoCache
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class MemCacheTests < UnitTests
|
20
|
+
desc "MemCache"
|
21
|
+
setup do
|
22
|
+
@cache = MemCache.new
|
23
|
+
end
|
24
|
+
subject{ @cache }
|
25
|
+
|
26
|
+
should have_imeths :keys, :[], :[]=
|
27
|
+
|
28
|
+
should "cache given key/value pairs in memory" do
|
29
|
+
val = []
|
30
|
+
subject['something'] = val
|
31
|
+
assert_same val, subject['something']
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class NoCacheTests < UnitTests
|
37
|
+
desc "NoCache"
|
38
|
+
setup do
|
39
|
+
@cache = NoCache.new
|
40
|
+
end
|
41
|
+
subject{ @cache }
|
42
|
+
|
43
|
+
should have_imeths :keys, :[], :[]=
|
44
|
+
|
45
|
+
should "not cache given key/value pairs in memory" do
|
46
|
+
val = []
|
47
|
+
subject['something'] = val
|
48
|
+
assert_not_same val, subject['something']
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/test/unit/config_tests.rb
CHANGED
@@ -1,23 +1,33 @@
|
|
1
1
|
require 'assert'
|
2
|
+
require 'dassets/config'
|
3
|
+
|
2
4
|
require 'ns-options/assert_macros'
|
3
|
-
require 'dassets'
|
5
|
+
require 'dassets/cache'
|
6
|
+
require 'dassets/file_store'
|
4
7
|
|
5
8
|
class Dassets::Config
|
6
9
|
|
7
|
-
class
|
10
|
+
class UnitTests < Assert::Context
|
8
11
|
include NsOptions::AssertMacros
|
12
|
+
|
9
13
|
desc "Dassets::Config"
|
10
14
|
setup do
|
11
15
|
@config = Dassets::Config.new
|
12
16
|
end
|
13
17
|
subject{ @config }
|
14
18
|
|
15
|
-
should
|
16
|
-
should have_options :file_store
|
17
|
-
|
19
|
+
should have_options :file_store, :cache
|
18
20
|
should have_reader :combinations
|
19
21
|
should have_imeth :source, :combination, :combination?
|
20
22
|
|
23
|
+
should "default the file store option to a null file store" do
|
24
|
+
assert_kind_of Dassets::FileStore::NullStore, subject.file_store
|
25
|
+
end
|
26
|
+
|
27
|
+
should "default the cache option to no caching" do
|
28
|
+
assert_kind_of Dassets::Cache::NoCache, subject.cache
|
29
|
+
end
|
30
|
+
|
21
31
|
should "register new sources with the `source` method" do
|
22
32
|
path = '/path/to/app/assets'
|
23
33
|
filter = proc{ |paths| [] }
|
data/test/unit/dassets_tests.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'assert'
|
2
|
-
require 'fileutils'
|
3
2
|
require 'dassets'
|
4
3
|
|
4
|
+
require 'fileutils'
|
5
|
+
require 'dassets/asset_file'
|
6
|
+
|
5
7
|
module Dassets
|
6
8
|
|
7
|
-
class
|
9
|
+
class UnitTests < Assert::Context
|
8
10
|
desc "Dassets"
|
9
11
|
subject{ Dassets }
|
10
12
|
|
@@ -23,6 +25,13 @@ module Dassets
|
|
23
25
|
assert_equal 'd41d8cd98f00b204e9800998ecf8427e', file.fingerprint
|
24
26
|
end
|
25
27
|
|
28
|
+
should "cache asset files" do
|
29
|
+
file1 = subject['nested/file3.txt']
|
30
|
+
file2 = subject['nested/file3.txt']
|
31
|
+
|
32
|
+
assert_same file2, file1
|
33
|
+
end
|
34
|
+
|
26
35
|
should "return an asset file that doesn't exist if digest path not found" do
|
27
36
|
file = subject['path/not/found.txt']
|
28
37
|
assert_not file.exists?
|
data/test/unit/engine_tests.rb
CHANGED
@@ -3,13 +3,48 @@ require 'dassets/file_store'
|
|
3
3
|
|
4
4
|
class Dassets::FileStore
|
5
5
|
|
6
|
-
class
|
7
|
-
desc "Dassets::
|
8
|
-
|
6
|
+
class UnitTests < Assert::Context
|
7
|
+
desc "Dassets::FileStore"
|
8
|
+
setup do
|
9
|
+
@root = TEST_SUPPORT_PATH.join('public')
|
10
|
+
@url = 'some/url'
|
11
|
+
@url_path = @root.join(@url).to_s
|
12
|
+
FileUtils.rm_f(@url_path)
|
13
|
+
|
14
|
+
@store = Dassets::FileStore.new(@root.to_s)
|
15
|
+
end
|
16
|
+
teardown do
|
17
|
+
FileUtils.rm_f(@url_path)
|
18
|
+
end
|
19
|
+
subject{ @store }
|
9
20
|
|
10
|
-
should
|
21
|
+
should have_readers :root
|
11
22
|
should have_imeths :save, :store_path
|
12
23
|
|
24
|
+
should "know its root path" do
|
25
|
+
assert_equal @root.to_s, subject.root
|
26
|
+
end
|
27
|
+
|
28
|
+
should "build the store path based on a given url" do
|
29
|
+
assert_equal @url_path, subject.store_path(@url)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "return write a file and return the store path on save" do
|
33
|
+
assert_not_file_exists @url_path
|
34
|
+
path = subject.save(@url){ 'some contents' }
|
35
|
+
|
36
|
+
assert_equal @url_path, path
|
37
|
+
assert_file_exists @url_path
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class NullStoreTests < UnitTests
|
43
|
+
desc "NullStore"
|
44
|
+
setup do
|
45
|
+
@store = Dassets::FileStore::NullStore.new
|
46
|
+
end
|
47
|
+
|
13
48
|
should "be a kind of FileStore" do
|
14
49
|
assert_kind_of Dassets::FileStore, subject
|
15
50
|
end
|
@@ -18,12 +53,8 @@ class Dassets::FileStore
|
|
18
53
|
assert_equal '', subject.root
|
19
54
|
end
|
20
55
|
|
21
|
-
should "build the store path based on a given url" do
|
22
|
-
assert_equal '/some/url', subject.store_path('some/url')
|
23
|
-
end
|
24
|
-
|
25
56
|
should "return the store path on save" do
|
26
|
-
assert_equal
|
57
|
+
assert_equal "/#{@url}", subject.save(@url)
|
27
58
|
end
|
28
59
|
|
29
60
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'assert'
|
2
2
|
require 'dassets/server/request'
|
3
3
|
|
4
|
+
require 'dassets/asset_file'
|
5
|
+
|
4
6
|
class Dassets::Server::Request
|
5
7
|
|
6
|
-
class
|
8
|
+
class UnitTests < Assert::Context
|
7
9
|
desc "Dassets::Server::Request"
|
8
10
|
setup do
|
9
11
|
@req = file_request('GET', '/file1-daa05c683a4913b268653f7a7e36a5b4.txt')
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'assert'
|
2
|
-
require 'rack/utils'
|
3
2
|
require 'dassets/server/response'
|
4
3
|
|
4
|
+
require 'rack/utils'
|
5
|
+
require 'dassets/asset_file'
|
6
|
+
|
5
7
|
class Dassets::Server::Response
|
6
8
|
|
7
|
-
class
|
9
|
+
class UnitTests < Assert::Context
|
8
10
|
desc "Dassets::Server::Response"
|
9
11
|
setup do
|
10
12
|
@resp = file_response(Dassets::AssetFile.new(''))
|
@@ -2,6 +2,7 @@ require 'assert'
|
|
2
2
|
require 'dassets/source_file'
|
3
3
|
|
4
4
|
require 'dassets/asset_file'
|
5
|
+
require 'dassets/source_proxy'
|
5
6
|
|
6
7
|
class Dassets::SourceFile
|
7
8
|
|
@@ -51,6 +52,12 @@ class Dassets::SourceFile
|
|
51
52
|
assert_not_same subject, found
|
52
53
|
end
|
53
54
|
|
55
|
+
should "not memoize its compiled source" do
|
56
|
+
compiled1 = subject.compiled
|
57
|
+
compiled2 = subject.compiled
|
58
|
+
assert_not_same compiled2, compiled1
|
59
|
+
end
|
60
|
+
|
54
61
|
end
|
55
62
|
|
56
63
|
class NullSourceTests < UnitTests
|
@@ -1,30 +1,37 @@
|
|
1
1
|
require 'assert'
|
2
|
+
require 'dassets/source_proxy'
|
3
|
+
|
2
4
|
require 'digest/md5'
|
5
|
+
require 'dassets/cache'
|
3
6
|
require 'dassets/source_file'
|
4
7
|
require 'dassets/source_proxy'
|
5
8
|
|
6
9
|
class Dassets::SourceProxy
|
7
10
|
|
8
|
-
class
|
11
|
+
class UnitTests < Assert::Context
|
9
12
|
desc "Dassets::SourceProxy"
|
10
13
|
setup do
|
11
14
|
@source_proxy = Dassets::SourceProxy.new('file1.txt')
|
12
15
|
end
|
13
16
|
subject{ @source_proxy }
|
14
17
|
|
15
|
-
should have_readers :digest_path, :source_files
|
18
|
+
should have_readers :digest_path, :source_files, :cache
|
16
19
|
should have_imeths :content, :fingerprint, :key, :mtime, :exists?
|
17
20
|
|
18
21
|
should "know its digest path" do
|
19
22
|
assert_equal 'file1.txt', subject.digest_path
|
20
23
|
end
|
21
24
|
|
22
|
-
should "know its source
|
25
|
+
should "know its source files" do
|
23
26
|
exp_source_file = Dassets::SourceFile.find_by_digest_path('file1.txt')
|
24
27
|
assert_equal 1, subject.source_files.size
|
25
28
|
assert_equal exp_source_file, subject.source_files.first
|
26
29
|
end
|
27
30
|
|
31
|
+
should "use a `NoCache` cache handler by default" do
|
32
|
+
assert_kind_of Dassets::Cache::NoCache, subject.cache
|
33
|
+
end
|
34
|
+
|
28
35
|
should "exist if its source file exists" do
|
29
36
|
assert_equal subject.source_files.first.exists?, subject.exists?
|
30
37
|
end
|
@@ -49,7 +56,7 @@ class Dassets::SourceProxy
|
|
49
56
|
|
50
57
|
end
|
51
58
|
|
52
|
-
class CombinationTests <
|
59
|
+
class CombinationTests < UnitTests
|
53
60
|
desc "when the digest path is a combination to multiple source files"
|
54
61
|
setup do
|
55
62
|
Dassets.config.combination 'file3.txt', ['file1.txt', 'file2.txt']
|
@@ -89,4 +96,42 @@ class Dassets::SourceProxy
|
|
89
96
|
|
90
97
|
end
|
91
98
|
|
99
|
+
class NoCacheTests < UnitTests
|
100
|
+
desc "with a `NoCache` cache handler"
|
101
|
+
setup do
|
102
|
+
@cache = Dassets::Cache::NoCache.new
|
103
|
+
@source_proxy = Dassets::SourceProxy.new('file1.txt', @cache)
|
104
|
+
end
|
105
|
+
|
106
|
+
should "not cache its source content/fingerprint" do
|
107
|
+
content1 = subject.content
|
108
|
+
content2 = subject.content
|
109
|
+
assert_not_same content2, content1
|
110
|
+
|
111
|
+
finger1 = subject.fingerprint
|
112
|
+
finger2 = subject.fingerprint
|
113
|
+
assert_not_same finger2, finger1
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
class MemCacheTests < UnitTests
|
119
|
+
desc "with a `MemCache` cache handler"
|
120
|
+
setup do
|
121
|
+
@cache = Dassets::Cache::MemCache.new
|
122
|
+
@source_proxy = Dassets::SourceProxy.new('file1.txt', @cache)
|
123
|
+
end
|
124
|
+
|
125
|
+
should "cache its source content/fingerprint in memory" do
|
126
|
+
content1 = subject.content
|
127
|
+
content2 = subject.content
|
128
|
+
assert_same content2, content1
|
129
|
+
|
130
|
+
finger1 = subject.fingerprint
|
131
|
+
finger2 = subject.fingerprint
|
132
|
+
assert_same finger2, finger1
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
92
137
|
end
|
data/test/unit/source_tests.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dassets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 8
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.8.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kelly Redding
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2013-
|
19
|
+
date: 2013-12-05 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: assert
|
@@ -26,11 +26,11 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 11
|
30
30
|
segments:
|
31
31
|
- 2
|
32
|
-
-
|
33
|
-
version: "2.
|
32
|
+
- 4
|
33
|
+
version: "2.4"
|
34
34
|
type: :development
|
35
35
|
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
@@ -112,7 +112,8 @@ files:
|
|
112
112
|
- dassets.gemspec
|
113
113
|
- lib/dassets.rb
|
114
114
|
- lib/dassets/asset_file.rb
|
115
|
-
- lib/dassets/
|
115
|
+
- lib/dassets/cache.rb
|
116
|
+
- lib/dassets/config.rb
|
116
117
|
- lib/dassets/engine.rb
|
117
118
|
- lib/dassets/file_store.rb
|
118
119
|
- lib/dassets/server.rb
|
@@ -130,7 +131,6 @@ files:
|
|
130
131
|
- test/support/app/assets/grumpy_cat.jpg
|
131
132
|
- test/support/app/assets/nested/a-thing.txt.useless.dumb
|
132
133
|
- test/support/app/assets/nested/file3.txt
|
133
|
-
- test/support/config/assets.rb
|
134
134
|
- test/support/empty/.gitkeep
|
135
135
|
- test/support/public/file1-daa05c683a4913b268653f7a7e36a5b4.txt
|
136
136
|
- test/support/public/file2-9bbe1047cffbb590f59e0e5aeff46ae4.txt
|
@@ -143,9 +143,9 @@ files:
|
|
143
143
|
- test/support/source_files/test1.txt
|
144
144
|
- test/system/rack_tests.rb
|
145
145
|
- test/unit/asset_file_tests.rb
|
146
|
+
- test/unit/cache_tests.rb
|
146
147
|
- test/unit/config_tests.rb
|
147
148
|
- test/unit/dassets_tests.rb
|
148
|
-
- test/unit/default_cache_tests.rb
|
149
149
|
- test/unit/engine_tests.rb
|
150
150
|
- test/unit/file_store_tests.rb
|
151
151
|
- test/unit/server/request_tests.rb
|
@@ -196,7 +196,6 @@ test_files:
|
|
196
196
|
- test/support/app/assets/grumpy_cat.jpg
|
197
197
|
- test/support/app/assets/nested/a-thing.txt.useless.dumb
|
198
198
|
- test/support/app/assets/nested/file3.txt
|
199
|
-
- test/support/config/assets.rb
|
200
199
|
- test/support/empty/.gitkeep
|
201
200
|
- test/support/public/file1-daa05c683a4913b268653f7a7e36a5b4.txt
|
202
201
|
- test/support/public/file2-9bbe1047cffbb590f59e0e5aeff46ae4.txt
|
@@ -209,9 +208,9 @@ test_files:
|
|
209
208
|
- test/support/source_files/test1.txt
|
210
209
|
- test/system/rack_tests.rb
|
211
210
|
- test/unit/asset_file_tests.rb
|
211
|
+
- test/unit/cache_tests.rb
|
212
212
|
- test/unit/config_tests.rb
|
213
213
|
- test/unit/dassets_tests.rb
|
214
|
-
- test/unit/default_cache_tests.rb
|
215
214
|
- test/unit/engine_tests.rb
|
216
215
|
- test/unit/file_store_tests.rb
|
217
216
|
- test/unit/server/request_tests.rb
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
# this is a thread-safe in-memory cache for use with the `SourceCache` that
|
4
|
-
# only caches source fingerprint keys. there are a few reasons for using this
|
5
|
-
# as the "default":
|
6
|
-
# * source fingerprints are accessed more frequently than contents (ie hrefs,
|
7
|
-
# urls, etc) so caching them can have nice affects on performance. Plus it
|
8
|
-
# seems silly to have to compile the source file everytime you want to get its
|
9
|
-
# href so you can link it in.
|
10
|
-
# * fingerprints have a much smaller data size so won't overly bloat memory.
|
11
|
-
|
12
|
-
class Dassets::DefaultCache
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@hash = {}
|
16
|
-
@write_mutex = ::Mutex.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def keys; @hash.keys; end
|
20
|
-
def [](key); @hash[key]; end
|
21
|
-
|
22
|
-
def []=(key, value)
|
23
|
-
@write_mutex.synchronize do
|
24
|
-
@hash[key] = value if key =~ /-- fingerprint$/ # only write fingerprint keys
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'dassets'
|
2
|
-
|
3
|
-
@dumb_engine = Class.new(Dassets::Engine) do
|
4
|
-
def ext(in_ext); ''; end
|
5
|
-
def compile(input); "#{input}\nDUMB"; end
|
6
|
-
end
|
7
|
-
@useless_engine = Class.new(Dassets::Engine) do
|
8
|
-
def ext(in_ext); 'no-use'; end
|
9
|
-
def compile(input); "#{input}\nUSELESS"; end
|
10
|
-
end
|
11
|
-
|
12
|
-
Dassets.configure do |c|
|
13
|
-
c.source TEST_SUPPORT_PATH.join("app/assets") do |s|
|
14
|
-
s.engine 'dumb', @dumb_engine
|
15
|
-
s.engine 'useless', @useless_engine
|
16
|
-
end
|
17
|
-
|
18
|
-
c.cache = nil # use no cache
|
19
|
-
|
20
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'assert'
|
2
|
-
require 'dassets/default_cache'
|
3
|
-
|
4
|
-
class Dassets::DefaultCache
|
5
|
-
|
6
|
-
class BaseTests < Assert::Context
|
7
|
-
desc "Dassets::DefaultCache"
|
8
|
-
setup do
|
9
|
-
@cache = Dassets::DefaultCache.new
|
10
|
-
end
|
11
|
-
subject{ @cache }
|
12
|
-
|
13
|
-
should have_imeths :keys, :[], :[]=
|
14
|
-
|
15
|
-
should "only cache fingerprint keys" do
|
16
|
-
subject['some val'] = 'something'
|
17
|
-
assert_empty subject.keys
|
18
|
-
assert_nil subject['some val']
|
19
|
-
|
20
|
-
subject['a -- fingerprint'] = 'finger'
|
21
|
-
assert_includes 'a -- fingerprint', subject.keys
|
22
|
-
assert_equal 'finger', subject['a -- fingerprint']
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|