ettu 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +0 -1
- data/ettu.gemspec +1 -0
- data/lib/ettu/configuration.rb +30 -0
- data/lib/ettu/fresh_when.rb +8 -11
- data/lib/ettu/version.rb +1 -1
- data/lib/ettu.rb +26 -21
- data/spec/ettu_spec.rb +81 -24
- data/spec/fixtures.rb +49 -0
- data/spec/fresh_when_spec.rb +42 -4
- data/spec/spec_helper.rb +7 -1
- metadata +20 -1
data/.rspec
CHANGED
data/ettu.gemspec
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
class Ettu
|
2
|
+
class Configuration < ActiveSupport::OrderedOptions
|
3
|
+
def initialize
|
4
|
+
super
|
5
|
+
set_defaults
|
6
|
+
end
|
7
|
+
|
8
|
+
def reset
|
9
|
+
set_defaults
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def set_defaults
|
15
|
+
self.js = 'application.js'
|
16
|
+
self.css = 'application.css'
|
17
|
+
self.assets = []
|
18
|
+
|
19
|
+
# Don't actually set view by default.
|
20
|
+
# This'll allow #fetch to return the real default
|
21
|
+
# at runtime.
|
22
|
+
# self.view = "#{controller_name}/#{action_name}"
|
23
|
+
delete :view if key? :view
|
24
|
+
|
25
|
+
if defined? ActionView::Digestor
|
26
|
+
self.template_digestor = ActionView::Digestor
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/ettu/fresh_when.rb
CHANGED
@@ -5,22 +5,19 @@ class Ettu
|
|
5
5
|
included do
|
6
6
|
alias_method :old_fresh_when, :fresh_when
|
7
7
|
|
8
|
-
def fresh_when(record_or_options, additional_options
|
9
|
-
ettu =
|
8
|
+
def fresh_when(record_or_options, additional_options)
|
9
|
+
ettu = ettu_instance(record_or_options, additional_options, self)
|
10
10
|
|
11
|
-
|
12
|
-
etags << ettu.view_etag
|
13
|
-
if request.format.try(:html?)
|
14
|
-
etags << ettu.js_etag
|
15
|
-
etags << ettu.css_etag
|
16
|
-
end
|
17
|
-
etags.concat ettu.asset_etags
|
18
|
-
|
19
|
-
ettu_params = {etag: etags, last_modified: ettu.last_modified}
|
11
|
+
ettu_params = {etag: ettu.etags, last_modified: ettu.last_modified}
|
20
12
|
|
21
13
|
old_fresh_when nil, ettu.options.merge(ettu_params)
|
22
14
|
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
23
18
|
|
19
|
+
def ettu_instance(record_or_options, additional_options, controller)
|
20
|
+
Ettu.new record_or_options, additional_options, controller
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
data/lib/ettu/version.rb
CHANGED
data/lib/ettu.rb
CHANGED
@@ -4,22 +4,15 @@ require 'active_support/core_ext/object/blank'
|
|
4
4
|
require 'active_support/core_ext/object/try'
|
5
5
|
|
6
6
|
require 'ettu/version'
|
7
|
+
require 'ettu/configuration'
|
7
8
|
require 'ettu/fresh_when'
|
8
|
-
require 'ettu/railtie' if defined? Rails
|
9
|
+
require 'ettu/railtie' if defined? Rails::Railtie
|
9
10
|
|
10
11
|
class Ettu
|
11
12
|
attr_reader :options
|
12
13
|
|
13
14
|
class << self
|
14
|
-
@@config =
|
15
|
-
@@config.js = 'application.js'
|
16
|
-
@@config.css = 'application.css'
|
17
|
-
@@config.assets = []
|
18
|
-
@@config.template_digestor = if defined? ActionView::Digestor
|
19
|
-
ActionView::Digestor
|
20
|
-
else
|
21
|
-
nil
|
22
|
-
end
|
15
|
+
@@config = Configuration.new
|
23
16
|
|
24
17
|
def configure
|
25
18
|
yield @@config
|
@@ -27,27 +20,36 @@ class Ettu
|
|
27
20
|
end
|
28
21
|
|
29
22
|
def initialize(record_or_options = nil, additional_options = {}, controller = nil)
|
30
|
-
@controller = controller
|
31
|
-
@asset_etags = {}
|
23
|
+
@controller, @asset_etags = controller, {}
|
32
24
|
if record_or_options.is_a? Hash
|
33
|
-
@record = nil
|
34
|
-
@options = record_or_options
|
25
|
+
@record, @options = nil, record_or_options
|
35
26
|
else
|
36
|
-
@record = record_or_options
|
37
|
-
@options = additional_options
|
27
|
+
@record, @options = record_or_options, additional_options
|
38
28
|
end
|
39
29
|
end
|
40
30
|
|
41
|
-
def
|
42
|
-
|
31
|
+
def etags
|
32
|
+
etags = [*response_etag]
|
33
|
+
etags << view_etag
|
34
|
+
if @controller.request.format.try(:html?)
|
35
|
+
etags << js_etag
|
36
|
+
etags << css_etag
|
37
|
+
end
|
38
|
+
etags.concat asset_etags
|
43
39
|
end
|
44
40
|
|
45
41
|
def last_modified
|
46
42
|
@options.fetch(:last_modified, @record.try(:updated_at))
|
47
43
|
end
|
48
44
|
|
45
|
+
def response_etag
|
46
|
+
@options.fetch(:etag, @record)
|
47
|
+
end
|
48
|
+
|
49
49
|
def view_etag
|
50
|
-
|
50
|
+
default_view = @@config.fetch(:view, "#{@controller.controller_name}/#{@controller.action_name}")
|
51
|
+
view = @options.fetch(:view, default_view)
|
52
|
+
@view_etag ||= view_digest(view)
|
51
53
|
end
|
52
54
|
|
53
55
|
def js_etag
|
@@ -73,9 +75,10 @@ class Ettu
|
|
73
75
|
|
74
76
|
# Jeremy Kemper
|
75
77
|
# https://gist.github.com/jeremy/4211803
|
76
|
-
def view_digest
|
78
|
+
def view_digest(view)
|
79
|
+
return nil unless view.present?
|
77
80
|
@@config.template_digestor.digest(
|
78
|
-
|
81
|
+
view,
|
79
82
|
@controller.request.format.try(:to_sym),
|
80
83
|
@controller.lookup_context
|
81
84
|
)
|
@@ -86,6 +89,8 @@ class Ettu
|
|
86
89
|
# Check precompiled asset manifest (production) or compute the digest (dev).
|
87
90
|
def asset_digest(asset)
|
88
91
|
return nil unless asset.present?
|
92
|
+
# Is Rails.application.config.assets.digests needed?
|
93
|
+
# Seems to always be nil...
|
89
94
|
if manifest = Rails.application.config.assets.digests
|
90
95
|
manifest[asset]
|
91
96
|
else
|
data/spec/ettu_spec.rb
CHANGED
@@ -1,41 +1,98 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
return self
|
3
|
+
describe Ettu do
|
4
|
+
let(:controller) { Controller.new }
|
5
|
+
let(:record) { Record.new(DateTime.now) }
|
6
|
+
let(:hash) { { etag: record, last_modified: DateTime.now } }
|
7
|
+
before(:all) do
|
8
|
+
Ettu.configure { |config| config.template_digestor = Digestor }
|
10
9
|
end
|
11
|
-
end
|
12
|
-
module Rails
|
13
|
-
module Railtie; end
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
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) }
|
19
14
|
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
it 'will use :js option over default' do
|
16
|
+
expect(ettu.js_etag).to eq('custom.js.digest')
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
it 'will use :css option over default' do
|
20
|
+
expect(ettu.css_etag).to eq('custom.css.digest')
|
21
|
+
end
|
27
22
|
|
28
|
-
|
29
|
-
|
23
|
+
it 'will use :asset option over default' do
|
24
|
+
expect(ettu.asset_etags).to eq(['first.ext.digest'])
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'will use :view option over default' do
|
28
|
+
expect(ettu.view_etag).to eq('custom/action.digest')
|
29
|
+
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
describe '.configure' do
|
33
|
+
subject(:ettu) { Ettu.new(nil, {}, controller) }
|
33
34
|
|
35
|
+
context 'when no options are specified' do
|
36
|
+
before(:all) do
|
37
|
+
Ettu.configure do |config|
|
38
|
+
config.js = 'custom.js'
|
39
|
+
config.css = 'custom.css'
|
40
|
+
config.assets = ['first.ext', 'second.ext']
|
41
|
+
config.view = 'custom/view'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
after(:all) { Ettu.configure { |config| config.reset } }
|
34
45
|
|
35
|
-
|
46
|
+
it 'will use the default js file' do
|
47
|
+
expect(ettu.js_etag).to eq('custom.js.digest')
|
48
|
+
end
|
36
49
|
|
50
|
+
it 'will use the default css file' do
|
51
|
+
expect(ettu.css_etag).to eq('custom.css.digest')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'will use the default asset files' do
|
55
|
+
expect(ettu.asset_etags).to eq(['first.ext.digest', 'second.ext.digest'])
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'will use the default view file' do
|
59
|
+
expect(ettu.view_etag).to eq('custom/view.digest')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when setting default to false' do
|
64
|
+
before(:all) do
|
65
|
+
Ettu.configure do |config|
|
66
|
+
config.js = false
|
67
|
+
config.css = false
|
68
|
+
config.view = false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
after(:all) { Ettu.configure { |config| config.reset } }
|
72
|
+
|
73
|
+
it 'will disable js etag' do
|
74
|
+
expect(ettu.js_etag).to eq(nil)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'will disable css etag' do
|
78
|
+
expect(ettu.css_etag).to eq(nil)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'will disable view etags' do
|
82
|
+
expect(ettu.view_etag).to eq(nil)
|
83
|
+
end
|
84
|
+
end
|
37
85
|
end
|
38
86
|
|
87
|
+
describe '#etags' do
|
88
|
+
let(:ettu) { Ettu.new(record, {}, controller) }
|
89
|
+
it 'will collect all etags' do
|
90
|
+
expected = [record, 'controller_name/action_name.digest', 'application.js.digest', 'application.css.digest']
|
91
|
+
result = ettu.etags
|
92
|
+
expect(ettu.etags).to include(*expected)
|
93
|
+
expect(expected).to include(*result)
|
94
|
+
end
|
95
|
+
end
|
39
96
|
|
40
97
|
context 'when given only a record' do
|
41
98
|
subject(:ettu) { Ettu.new(record) }
|
data/spec/fixtures.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
class Nester < ActiveSupport::OrderedOptions
|
2
|
+
def initialize
|
3
|
+
super { |h, k| h[k] = Nester.new }
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Controller < Nester
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
|
11
|
+
self.request.format['html?'] = true
|
12
|
+
self.controller_name = 'controller_name'
|
13
|
+
self.action_name = 'action_name'
|
14
|
+
end
|
15
|
+
|
16
|
+
def fresh_when(*args)
|
17
|
+
:old_fresh_when
|
18
|
+
end
|
19
|
+
|
20
|
+
include ::Ettu::FreshWhen
|
21
|
+
end
|
22
|
+
|
23
|
+
class Digestor
|
24
|
+
def self.method_missing(name, *args, &block)
|
25
|
+
args.first.to_s + '.digest'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Record
|
30
|
+
attr_accessor :updated_at
|
31
|
+
|
32
|
+
def initialize(updated_at)
|
33
|
+
@updated_at = updated_at
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Rails
|
38
|
+
def self.application
|
39
|
+
@nested ||= Nester.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
Rails.application.assets['application.js'].digest = 'application.js.digest'
|
43
|
+
Rails.application.assets['application.css'].digest = 'application.css.digest'
|
44
|
+
Rails.application.assets['custom.js'].digest = 'custom.js.digest'
|
45
|
+
Rails.application.assets['custom.css'].digest = 'custom.css.digest'
|
46
|
+
Rails.application.assets['first.ext'].digest = 'first.ext.digest'
|
47
|
+
Rails.application.assets['second.ext'].digest = 'second.ext.digest'
|
48
|
+
Rails.application.config.assets.digests = nil
|
49
|
+
|
data/spec/fresh_when_spec.rb
CHANGED
@@ -1,8 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
1
4
|
describe Ettu::FreshWhen do
|
2
|
-
|
3
|
-
|
5
|
+
before(:all) do
|
6
|
+
Ettu.configure { |config| config.template_digestor = Digestor }
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:ettu) { double }
|
10
|
+
let(:record) { Record.new(DateTime.now) }
|
11
|
+
let(:hash) { { random: true, options: true } }
|
12
|
+
subject(:controller) { Controller.new }
|
13
|
+
|
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
|
+
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
|
36
|
+
end
|
4
37
|
|
5
|
-
|
6
|
-
|
38
|
+
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
|
7
45
|
end
|
8
46
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,8 +5,14 @@
|
|
5
5
|
#
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
7
|
|
8
|
-
require 'ettu'
|
9
8
|
require 'date'
|
9
|
+
require 'active_support/ordered_options'
|
10
|
+
|
11
|
+
require 'simplecov'
|
12
|
+
SimpleCov.start { add_filter '/spec/' }
|
13
|
+
|
14
|
+
require 'ettu'
|
15
|
+
require 'fixtures'
|
10
16
|
|
11
17
|
RSpec.configure do |config|
|
12
18
|
config.run_all_when_everything_filtered = true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ettu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -75,6 +75,22 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: simplecov
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
78
94
|
description: Account for js, css, and views when using ETags.
|
79
95
|
email:
|
80
96
|
- jridgewell@cloudspace.com
|
@@ -91,10 +107,12 @@ files:
|
|
91
107
|
- Rakefile
|
92
108
|
- ettu.gemspec
|
93
109
|
- lib/ettu.rb
|
110
|
+
- lib/ettu/configuration.rb
|
94
111
|
- lib/ettu/fresh_when.rb
|
95
112
|
- lib/ettu/railtie.rb
|
96
113
|
- lib/ettu/version.rb
|
97
114
|
- spec/ettu_spec.rb
|
115
|
+
- spec/fixtures.rb
|
98
116
|
- spec/fresh_when_spec.rb
|
99
117
|
- spec/spec_helper.rb
|
100
118
|
homepage: http://github.com/cloudspace/ettu
|
@@ -124,5 +142,6 @@ specification_version: 3
|
|
124
142
|
summary: Account for view code when using ETags.
|
125
143
|
test_files:
|
126
144
|
- spec/ettu_spec.rb
|
145
|
+
- spec/fixtures.rb
|
127
146
|
- spec/fresh_when_spec.rb
|
128
147
|
- spec/spec_helper.rb
|