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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 28eeeb019730fdbde0370f53b31ee30dade06adb
4
- data.tar.gz: 7b925784197f8e7d9c8009b57563e0d85ce1f49a
3
+ metadata.gz: 2d25ab552acd13252c6c5b916e118e4fb84fe99f
4
+ data.tar.gz: 2235cc55e58233893a321d28b308d51e94a41655
5
5
  SHA512:
6
- metadata.gz: 0c41c23a43c47b53764dbfb531248c6cce4c026461e4277de4c4905ad0928be4de9ac291db68999054c0aa9c3260140a6f86909fc01959f7251db36f092cb29d
7
- data.tar.gz: 40f849ff897c470f6af3f8ccef53795cb0263a5c9f7710e2c1f9a03ad28bfaafee3ede974bde2cb5d3db2e7af4339f38d6e7a9a982305d8cd35c6e68f4e60cf0
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
+ [![Build Status](https://travis-ci.org/cloudspace/ettu.png?branch=v3)](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 asset fingerprints of
50
- `application.js` and `application.css` along with the cache digest of
51
- the current action into the calculation for the final ETag sent to the
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 = ['first.js', 'second.css']
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, js: 'app.js', css: 'style.css', assets: 'super.css'
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: "products/index"
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, js: false, css: false, view: false
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
- 1. [x] Decouple Ettu and Configuration
5
- 2. [ ] Remove Rails Version checking
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
- 3. [ ] Default assets to those set in Rails.application.config.assets.precompile
9
+ - [x] Default assets to those set in Rails.application.config.assets
@@ -13,9 +13,7 @@ class Ettu
13
13
  private
14
14
 
15
15
  def set_defaults
16
- self.js = 'application.js'
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
- # Don't attempt to reset the template_digestor
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 LateLoadTemplateDigestor
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
- def digest(*args)
39
- digestor = attempt_late_template_digestor_set
40
- digestor.digest(*args)
40
+ class LateLoadAssets < LateLoad
41
+ def to_a
42
+ super
41
43
  end
42
44
 
43
- private
45
+ def defaults
46
+ ::Rails.application.config.assets.digests.keys
47
+ end
48
+ end
44
49
 
45
- def attempt_late_template_digestor_set
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
- @config.template_digestor = CacheDigests::TemplateDigestor
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
@@ -2,22 +2,12 @@ class Ettu
2
2
  module FreshWhen
3
3
  extend ActiveSupport::Concern
4
4
 
5
- included do
6
- alias_method :old_fresh_when, :fresh_when
5
+ def fresh_when(record_or_options, additional_options = {})
6
+ ettu = Ettu.new record_or_options, additional_options, self
7
7
 
8
- def fresh_when(record_or_options, additional_options = {})
9
- ettu = ettu_instance(record_or_options, additional_options, self)
8
+ ettu_params = {etag: ettu.etags, last_modified: ettu.last_modified}
10
9
 
11
- ettu_params = {etag: ettu.etags, last_modified: ettu.last_modified}
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
@@ -1,3 +1,3 @@
1
1
  class Ettu
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'
3
3
  end
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
- let(:hash) { { js: 'custom.js', css: 'custom.css', assets: 'first.ext', view: 'custom/action' } }
13
- subject(:ettu) { Ettu.new(hash, {}, controller) }
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.digest'])
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 js file' do
47
- expect(ettu.js_etag).to eq('custom.js.digest')
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 css file' do
51
- expect(ettu.css_etag).to eq('custom.css.digest')
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
- it 'will use the default asset files' do
55
- expect(ettu.asset_etags).to eq(['first.ext.digest', 'second.ext.digest'])
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 'will use the default view file' do
59
- expect(ettu.view_etag).to eq('custom/view.digest')
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.js = false
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 js etag' do
73
- expect(ettu.js_etag).to eq(nil)
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 = [record, 'controller_name/action_name.digest', 'application.js.digest', 'application.css.digest']
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(ettu.etags).to include(*expected)
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
- def fresh_when(*args)
17
- :old_fresh_when
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 = nil
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
@@ -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.should_receive(:old_fresh_when) do |r, h|
33
- r.nil?
34
- end
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.should_receive(:old_fresh_when) do |r, h|
40
- hash.each_pair.all? do |k, v|
41
- h[k] == v
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.0.0
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-07-01 00:00:00.000000000 Z
11
+ date: 2013-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails