ettu 3.0.0 → 3.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/README.md +9 -18
- data/ROADMAP.md +3 -3
- data/lib/ettu/configuration.rb +22 -16
- data/lib/ettu/fresh_when.rb +4 -14
- data/lib/ettu/version.rb +1 -1
- data/lib/ettu.rb +1 -14
- data/spec/ettu_spec.rb +42 -33
- data/spec/fixtures.rb +9 -4
- data/spec/fresh_when_spec.rb +6 -28
- data/spec/spec_helper.rb +8 -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: 2d25ab552acd13252c6c5b916e118e4fb84fe99f
|
4
|
+
data.tar.gz: 2235cc55e58233893a321d28b308d51e94a41655
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65087d66aa1735063f863232f47e18fb97816b9ce894edcd1f04b732f548d470c3e4a7087a26b93d4eedead50927f5223c60c515be033675a8be9e0df592ed2e
|
7
|
+
data.tar.gz: 01e1259d72f51e4a37c3ae90996a872c72ac7ef2875cddee04ba38cea974b2831aaba5728e61b27203d73880469d9eb3d2ed46fc3d5b73b25a3610311777738f
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
Ettu
|
2
2
|
====
|
3
3
|
|
4
|
+
[](https://travis-ci.org/cloudspace/ettu)
|
5
|
+
|
4
6
|
Using Rails 3's `stale?` or `fresh_when`? Are your users seeing old view
|
5
7
|
code even after new deploys? The Rails way `fresh_when(@product)`
|
6
8
|
doesn't account for changes in your view code, you have to do it
|
@@ -46,10 +48,9 @@ end
|
|
46
48
|
```
|
47
49
|
|
48
50
|
Ettu wants you to keep using either syntax, and let it worry about the
|
49
|
-
view code. By default, it will add in the
|
50
|
-
|
51
|
-
|
52
|
-
browser.
|
51
|
+
view code. By default, it will add in the fingerprints of your
|
52
|
+
precompiled assets along with the cache digest of the current action
|
53
|
+
into the calculation for the final ETag sent to the browser.
|
53
54
|
|
54
55
|
### Configuring
|
55
56
|
|
@@ -68,34 +69,24 @@ Of course, you can override Ettu's default behavior:
|
|
68
69
|
```ruby
|
69
70
|
# config/initializers/ettu.rb
|
70
71
|
Ettu.configure do |config|
|
71
|
-
# Set the default js file
|
72
|
-
config.js = 'app.js'
|
73
|
-
# Or don't account for javascript
|
74
|
-
# config.js = false
|
75
|
-
|
76
|
-
# Set the default css file
|
77
|
-
config.css = 'style.css'
|
78
|
-
# Or don't account for css
|
79
|
-
# config.css = false
|
80
|
-
|
81
72
|
# Add in extra assets to account for
|
82
|
-
config.assets
|
73
|
+
config.assets += ['first.js', 'second.css']
|
83
74
|
end
|
84
75
|
```
|
85
76
|
|
86
77
|
Or each can be passed on an individual basis:
|
87
78
|
|
88
|
-
fresh_when @product,
|
79
|
+
fresh_when @product, assets: 'super.css'
|
89
80
|
|
90
81
|
Additionally, you can specify a different template to calculate with the
|
91
82
|
`view` option:
|
92
83
|
|
93
|
-
fresh_when @product, view:
|
84
|
+
fresh_when @product, view: 'products/index'
|
94
85
|
|
95
86
|
You can even stop Ettu from accounting for any of them by setting the
|
96
87
|
value to `false`:
|
97
88
|
|
98
|
-
fresh_when @product,
|
89
|
+
fresh_when @product, assets: false, view: false
|
99
90
|
|
100
91
|
### What about Rails' default `fresh_when`?
|
101
92
|
|
data/ROADMAP.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Ettu Roadmap
|
2
2
|
============
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
- [x] Decouple Ettu and Configuration
|
5
|
+
- [x] Remove Rails Version checking
|
6
6
|
- Separate gem into branches
|
7
7
|
- v3 branch will track Rails 3
|
8
8
|
- v4 branch will track Rails 4
|
9
|
-
|
9
|
+
- [x] Default assets to those set in Rails.application.config.assets
|
data/lib/ettu/configuration.rb
CHANGED
@@ -13,9 +13,7 @@ class Ettu
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def set_defaults
|
16
|
-
self.
|
17
|
-
self.css = 'application.css'
|
18
|
-
self.assets = []
|
16
|
+
self.assets = LateLoadAssets.new(self, :assets)
|
19
17
|
|
20
18
|
# Don't actually set view by default.
|
21
19
|
# This'll allow #fetch to return the real default
|
@@ -23,32 +21,40 @@ class Ettu
|
|
23
21
|
# self.view = "#{controller_name}/#{action_name}"
|
24
22
|
delete :view if key? :view
|
25
23
|
|
26
|
-
|
27
|
-
# if one has already been found
|
28
|
-
unless self.template_digestor
|
29
|
-
self.template_digestor = LateLoadTemplateDigestor.new(self)
|
30
|
-
end
|
24
|
+
self.template_digestor = LateLoadTemplateDigestor.new(self, :template_digestor)
|
31
25
|
end
|
32
26
|
|
33
|
-
class
|
34
|
-
def initialize(config)
|
27
|
+
class LateLoad
|
28
|
+
def initialize(config, name)
|
35
29
|
@config = config
|
30
|
+
@name = name
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method, *args, &block)
|
34
|
+
late_load = defaults
|
35
|
+
@config[@name] = late_load
|
36
|
+
late_load.send method, *args, &block
|
36
37
|
end
|
38
|
+
end
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
class LateLoadAssets < LateLoad
|
41
|
+
def to_a
|
42
|
+
super
|
41
43
|
end
|
42
44
|
|
43
|
-
|
45
|
+
def defaults
|
46
|
+
::Rails.application.config.assets.digests.keys
|
47
|
+
end
|
48
|
+
end
|
44
49
|
|
45
|
-
|
50
|
+
class LateLoadTemplateDigestor < LateLoad
|
51
|
+
def defaults
|
46
52
|
unless defined? CacheDigests::TemplateDigestor
|
47
53
|
# Attempt to load cache_digets
|
48
54
|
require 'cache_digests'
|
49
55
|
end
|
50
56
|
# Attempt to use CacheDigests::TemplateDigestor on Rails 3
|
51
|
-
|
57
|
+
::CacheDigests::TemplateDigestor
|
52
58
|
rescue LoadError
|
53
59
|
raise "Ettu requires the cache_digests gem in Rails v#{Rails::VERSION::STRING}"
|
54
60
|
end
|
data/lib/ettu/fresh_when.rb
CHANGED
@@ -2,22 +2,12 @@ class Ettu
|
|
2
2
|
module FreshWhen
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
def fresh_when(record_or_options, additional_options = {})
|
6
|
+
ettu = Ettu.new record_or_options, additional_options, self
|
7
7
|
|
8
|
-
|
9
|
-
ettu = ettu_instance(record_or_options, additional_options, self)
|
8
|
+
ettu_params = {etag: ettu.etags, last_modified: ettu.last_modified}
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
old_fresh_when nil, ettu.options.merge(ettu_params)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def ettu_instance(record_or_options, additional_options, controller)
|
20
|
-
Ettu.new record_or_options, additional_options, controller
|
10
|
+
super nil, ettu.options.merge(ettu_params)
|
21
11
|
end
|
22
12
|
end
|
23
13
|
end
|
data/lib/ettu/version.rb
CHANGED
data/lib/ettu.rb
CHANGED
@@ -32,11 +32,8 @@ class Ettu
|
|
32
32
|
def etags
|
33
33
|
etags = [*response_etag]
|
34
34
|
etags << view_etag
|
35
|
-
if @controller.request.format.try(:html?)
|
36
|
-
etags << js_etag
|
37
|
-
etags << css_etag
|
38
|
-
end
|
39
35
|
etags.concat asset_etags
|
36
|
+
etags.compact
|
40
37
|
end
|
41
38
|
|
42
39
|
def last_modified
|
@@ -53,16 +50,6 @@ class Ettu
|
|
53
50
|
@view_etag ||= view_digest(view)
|
54
51
|
end
|
55
52
|
|
56
|
-
def js_etag
|
57
|
-
js = @options.fetch(:js, @@config.js)
|
58
|
-
asset_etag js
|
59
|
-
end
|
60
|
-
|
61
|
-
def css_etag
|
62
|
-
css = @options.fetch(:css, @@config.css)
|
63
|
-
asset_etag css
|
64
|
-
end
|
65
|
-
|
66
53
|
def asset_etags
|
67
54
|
assets = @options.fetch(:assets, @@config.assets)
|
68
55
|
[*assets].map { |asset| asset_etag(asset) }
|
data/spec/ettu_spec.rb
CHANGED
@@ -4,24 +4,16 @@ describe Ettu do
|
|
4
4
|
let(:controller) { Controller.new }
|
5
5
|
let(:record) { Record.new(DateTime.now) }
|
6
6
|
let(:hash) { { etag: record, last_modified: DateTime.now } }
|
7
|
-
before(:all) do
|
8
|
-
Ettu.configure { |config| config.template_digestor = Digestor }
|
9
|
-
end
|
10
7
|
|
11
8
|
context 'when supplied with options' do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
it 'will use :js option over default' do
|
16
|
-
expect(ettu.js_etag).to eq('custom.js.digest')
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'will use :css option over default' do
|
20
|
-
expect(ettu.css_etag).to eq('custom.css.digest')
|
9
|
+
before(:all) do
|
10
|
+
Ettu.configure { |config| config.template_digestor = Digestor }
|
21
11
|
end
|
12
|
+
let(:hash) { { assets: 'first.ext', view: 'custom/action' } }
|
13
|
+
subject(:ettu) { Ettu.new(hash, {}, controller) }
|
22
14
|
|
23
15
|
it 'will use :asset option over default' do
|
24
|
-
expect(ettu.asset_etags).to eq(['first.ext.
|
16
|
+
expect(ettu.asset_etags).to eq(['first.ext.manifest'])
|
25
17
|
end
|
26
18
|
|
27
19
|
it 'will use :view option over default' do
|
@@ -31,50 +23,53 @@ describe Ettu do
|
|
31
23
|
|
32
24
|
describe '.configure' do
|
33
25
|
subject(:ettu) { Ettu.new(nil, {}, controller) }
|
26
|
+
before(:all) do
|
27
|
+
Ettu.configure { |config| config.template_digestor = Digestor }
|
28
|
+
end
|
34
29
|
after(:all) { Ettu.configure { |config| config.reset } }
|
35
30
|
|
36
31
|
context 'when no options are specified' do
|
37
32
|
before(:all) do
|
38
33
|
Ettu.configure do |config|
|
39
|
-
config.js = 'custom.js'
|
40
|
-
config.css = 'custom.css'
|
41
34
|
config.assets = ['first.ext', 'second.ext']
|
42
35
|
config.view = 'custom/view'
|
43
36
|
end
|
44
37
|
end
|
45
38
|
|
46
|
-
it 'will use the default
|
47
|
-
expect(ettu.
|
39
|
+
it 'will use the default asset files' do
|
40
|
+
expect(ettu.asset_etags).to eq(['first.ext.manifest', 'second.ext.manifest'])
|
48
41
|
end
|
49
42
|
|
50
|
-
it 'will use the default
|
51
|
-
expect(ettu.
|
43
|
+
it 'will use the default view file' do
|
44
|
+
expect(ettu.view_etag).to eq('custom/view.digest')
|
52
45
|
end
|
46
|
+
end
|
53
47
|
|
54
|
-
|
55
|
-
|
48
|
+
context 'can append additional assets' do
|
49
|
+
let(:configuration) { Ettu::Configuration.new }
|
50
|
+
let(:random_string) { SecureRandom.hex }
|
51
|
+
|
52
|
+
it 'with +=' do
|
53
|
+
configuration.assets += [random_string]
|
54
|
+
expect(configuration.assets).to include(random_string)
|
56
55
|
end
|
57
56
|
|
58
|
-
it '
|
59
|
-
|
57
|
+
it 'with <<' do
|
58
|
+
configuration.assets << random_string
|
59
|
+
expect(configuration.assets).to include(random_string)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
context 'when setting default to false' do
|
64
64
|
before(:all) do
|
65
65
|
Ettu.configure do |config|
|
66
|
-
config.
|
67
|
-
config.css = false
|
66
|
+
config.assets = false
|
68
67
|
config.view = false
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
it 'will disable
|
73
|
-
expect(ettu.
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'will disable css etag' do
|
77
|
-
expect(ettu.css_etag).to eq(nil)
|
71
|
+
it 'will disable asset etags' do
|
72
|
+
expect(ettu.asset_etags).to eq([nil])
|
78
73
|
end
|
79
74
|
|
80
75
|
it 'will disable view etags' do
|
@@ -84,13 +79,27 @@ describe Ettu do
|
|
84
79
|
end
|
85
80
|
|
86
81
|
describe '#etags' do
|
82
|
+
before(:all) do
|
83
|
+
Ettu.configure { |config| config.template_digestor = Digestor }
|
84
|
+
end
|
87
85
|
let(:ettu) { Ettu.new(record, {}, controller) }
|
86
|
+
|
88
87
|
it 'will collect all etags' do
|
89
|
-
expected = [
|
88
|
+
expected = [
|
89
|
+
record, 'controller_name/action_name.digest',
|
90
|
+
'application.js.manifest', 'application.css.manifest',
|
91
|
+
'custom.js.manifest', 'custom.css.manifest',
|
92
|
+
'first.ext.manifest', 'second.ext.manifest'
|
93
|
+
]
|
90
94
|
result = ettu.etags
|
91
|
-
expect(
|
95
|
+
expect(result).to include(*expected)
|
92
96
|
expect(expected).to include(*result)
|
93
97
|
end
|
98
|
+
|
99
|
+
it 'will not allow nils' do
|
100
|
+
ettu = Ettu.new(nil, {assets: [nil, nil, nil]}, controller )
|
101
|
+
expect(ettu.etags).not_to include(nil)
|
102
|
+
end
|
94
103
|
end
|
95
104
|
|
96
105
|
context 'when given only a record' do
|
data/spec/fixtures.rb
CHANGED
@@ -13,9 +13,12 @@ class Controller < Nester
|
|
13
13
|
self.action_name = 'action_name'
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
module Freshness
|
17
|
+
def fresh_when(*args)
|
18
|
+
[*args]
|
19
|
+
end
|
18
20
|
end
|
21
|
+
include Freshness
|
19
22
|
|
20
23
|
include ::Ettu::FreshWhen
|
21
24
|
end
|
@@ -48,5 +51,7 @@ Rails.application.assets['custom.js'].digest = 'custom.js.digest'
|
|
48
51
|
Rails.application.assets['custom.css'].digest = 'custom.css.digest'
|
49
52
|
Rails.application.assets['first.ext'].digest = 'first.ext.digest'
|
50
53
|
Rails.application.assets['second.ext'].digest = 'second.ext.digest'
|
51
|
-
Rails.application.config.assets.digests =
|
52
|
-
|
54
|
+
Rails.application.config.assets.digests = Rails.application.assets.keys.reduce({}) do |hash, asset|
|
55
|
+
hash[asset.to_s] = asset.to_s + '.manifest'
|
56
|
+
hash
|
57
|
+
end
|
data/spec/fresh_when_spec.rb
CHANGED
@@ -6,41 +6,19 @@ describe Ettu::FreshWhen do
|
|
6
6
|
Ettu.configure { |config| config.template_digestor = Digestor }
|
7
7
|
end
|
8
8
|
|
9
|
-
let(:ettu) { double }
|
10
9
|
let(:record) { Record.new(DateTime.now) }
|
11
10
|
let(:hash) { { random: true, options: true } }
|
12
11
|
subject(:controller) { Controller.new }
|
13
12
|
|
14
|
-
before(:each) do
|
15
|
-
controller.stub(ettu_instance: ettu)
|
16
|
-
ettu.stub(:etags)
|
17
|
-
ettu.stub(:last_modified)
|
18
|
-
ettu.stub(options: {})
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'calls Ettu#etags' do
|
22
|
-
ettu.should_receive(:etags)
|
23
|
-
controller.fresh_when record, hash
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'calls Ettu#last_modified' do
|
27
|
-
ettu.should_receive(:last_modified)
|
28
|
-
controller.fresh_when record, hash
|
29
|
-
end
|
30
|
-
|
31
13
|
it 'passes nil as the first argument to original fresh_when' do
|
32
|
-
controller.
|
33
|
-
|
34
|
-
|
35
|
-
controller.fresh_when record, hash
|
14
|
+
ret = controller.fresh_when record, hash
|
15
|
+
|
16
|
+
expect(ret[0]).to equal(nil)
|
36
17
|
end
|
37
18
|
|
38
19
|
it 'passes extra options to original fresh_when' do
|
39
|
-
controller.
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
controller.fresh_when record, hash
|
20
|
+
ret = controller.fresh_when record, hash
|
21
|
+
|
22
|
+
expect(ret[1]).to include_hash(hash)
|
45
23
|
end
|
46
24
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,14 @@
|
|
7
7
|
|
8
8
|
require 'date'
|
9
9
|
require 'active_support/ordered_options'
|
10
|
+
require 'securerandom'
|
11
|
+
RSpec::Matchers.define :include_hash do |expected|
|
12
|
+
match do |actual|
|
13
|
+
!actual.nil? &&
|
14
|
+
!actual.empty? &&
|
15
|
+
(actual.to_a & expected.to_a) == expected.to_a
|
16
|
+
end
|
17
|
+
end
|
10
18
|
|
11
19
|
require 'simplecov'
|
12
20
|
SimpleCov.start { add_filter '/spec/' }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ettu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Ridgewell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|