versioncake 4.0.1 → 4.1.1
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/.github/workflows/ruby.yml +33 -0
- data/Appraisals +9 -3
- data/CHANGELOG.md +42 -1
- data/Gemfile.lock +26 -24
- data/README.md +14 -11
- data/SECURITY.md +9 -0
- data/gemfiles/rails5.0.gemfile.lock +26 -24
- data/gemfiles/rails5.2.gemfile.lock +36 -34
- data/gemfiles/rails6.0.gemfile +3 -3
- data/gemfiles/rails6.0.gemfile.lock +44 -40
- data/gemfiles/rails7.0.gemfile +9 -0
- data/gemfiles/rails7.0.gemfile.lock +127 -0
- data/lib/versioncake/controller_additions.rb +0 -6
- data/lib/versioncake/railtie.rb +9 -0
- data/lib/versioncake/response_strategy/http_content_type_strategy.rb +4 -2
- data/lib/versioncake/strategies/extraction_strategy.rb +11 -7
- data/lib/versioncake/version.rb +1 -1
- data/lib/versioncake/version_checker.rb +2 -1
- data/lib/versioncake/version_context_service.rb +1 -1
- data/lib/versioncake/versioned_request.rb +1 -1
- data/lib/versioncake/view_additions.rb +8 -88
- data/lib/versioncake/view_additions_rails5.rb +70 -0
- data/lib/versioncake/view_additions_rails6.rb +69 -0
- data/lib/versioncake/view_additions_rails7.rb +155 -0
- data/lib/versioncake.rb +3 -1
- data/spec/integration/controller/unversioned_controller_spec.rb +1 -1
- data/spec/integration/view/render_spec.rb +8 -1
- data/spec/integration/view/view_additions_rails5_spec.rb +67 -0
- data/spec/integration/view/view_additions_rails6_spec.rb +44 -0
- data/spec/integration/view/view_additions_rails7_spec.rb +76 -0
- data/spec/unit/strategies/extraction_strategy_spec.rb +2 -2
- data/spec/unit/version_checker_spec.rb +1 -1
- data/spec/unit/versioned_request_spec.rb +0 -7
- metadata +17 -8
- data/.travis.yml +0 -20
- data/spec/integration/view/view_additions_spec.rb +0 -42
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
versioncake (4.
|
4
|
+
versioncake (4.1.1)
|
5
5
|
actionpack (> 5.0)
|
6
6
|
activesupport (> 5.0)
|
7
7
|
railties (> 5.0)
|
@@ -10,30 +10,31 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
actionpack (
|
14
|
-
actionview (=
|
15
|
-
activesupport (=
|
13
|
+
actionpack (6.0.4.4)
|
14
|
+
actionview (= 6.0.4.4)
|
15
|
+
activesupport (= 6.0.4.4)
|
16
16
|
rack (~> 2.0, >= 2.0.8)
|
17
17
|
rack-test (>= 0.6.3)
|
18
18
|
rails-dom-testing (~> 2.0)
|
19
|
-
rails-html-sanitizer (~> 1.0, >= 1.0
|
20
|
-
actionview (
|
21
|
-
activesupport (=
|
19
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
20
|
+
actionview (6.0.4.4)
|
21
|
+
activesupport (= 6.0.4.4)
|
22
22
|
builder (~> 3.1)
|
23
23
|
erubi (~> 1.4)
|
24
24
|
rails-dom-testing (~> 2.0)
|
25
|
-
rails-html-sanitizer (~> 1.
|
26
|
-
activesupport (
|
25
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
26
|
+
activesupport (6.0.4.4)
|
27
27
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
28
28
|
i18n (>= 0.7, < 2)
|
29
29
|
minitest (~> 5.1)
|
30
30
|
tzinfo (~> 1.1)
|
31
|
-
|
31
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
32
|
+
appraisal (2.4.1)
|
32
33
|
bundler
|
33
34
|
rake
|
34
35
|
thor (>= 0.14.0)
|
35
36
|
builder (3.2.4)
|
36
|
-
concurrent-ruby (1.1.
|
37
|
+
concurrent-ruby (1.1.9)
|
37
38
|
coveralls (0.8.23)
|
38
39
|
json (>= 1.8, < 3)
|
39
40
|
simplecov (~> 0.16.1)
|
@@ -41,42 +42,44 @@ GEM
|
|
41
42
|
thor (>= 0.19.4, < 2.0)
|
42
43
|
tins (~> 1.6)
|
43
44
|
crass (1.0.6)
|
44
|
-
diff-lcs (1.
|
45
|
-
docile (1.
|
46
|
-
erubi (1.
|
47
|
-
i18n (1.8.
|
45
|
+
diff-lcs (1.5.0)
|
46
|
+
docile (1.4.0)
|
47
|
+
erubi (1.10.0)
|
48
|
+
i18n (1.8.11)
|
48
49
|
concurrent-ruby (~> 1.0)
|
49
|
-
json (2.
|
50
|
-
loofah (2.
|
50
|
+
json (2.6.1)
|
51
|
+
loofah (2.13.0)
|
51
52
|
crass (~> 1.0.2)
|
52
53
|
nokogiri (>= 1.5.9)
|
53
|
-
method_source (0.
|
54
|
-
mini_portile2 (2.
|
55
|
-
minitest (5.
|
56
|
-
nokogiri (1.
|
57
|
-
mini_portile2 (~> 2.
|
58
|
-
|
54
|
+
method_source (1.0.0)
|
55
|
+
mini_portile2 (2.7.1)
|
56
|
+
minitest (5.15.0)
|
57
|
+
nokogiri (1.13.1)
|
58
|
+
mini_portile2 (~> 2.7.0)
|
59
|
+
racc (~> 1.4)
|
60
|
+
racc (1.6.0)
|
61
|
+
rack (2.2.3)
|
59
62
|
rack-test (1.1.0)
|
60
63
|
rack (>= 1.0, < 3)
|
61
64
|
rails-dom-testing (2.0.3)
|
62
65
|
activesupport (>= 4.2.0)
|
63
66
|
nokogiri (>= 1.6)
|
64
|
-
rails-html-sanitizer (1.
|
67
|
+
rails-html-sanitizer (1.4.2)
|
65
68
|
loofah (~> 2.3)
|
66
|
-
railties (
|
67
|
-
actionpack (=
|
68
|
-
activesupport (=
|
69
|
+
railties (6.0.4.4)
|
70
|
+
actionpack (= 6.0.4.4)
|
71
|
+
activesupport (= 6.0.4.4)
|
69
72
|
method_source
|
70
73
|
rake (>= 0.8.7)
|
71
|
-
thor (>= 0.
|
72
|
-
rake (13.0.
|
74
|
+
thor (>= 0.20.3, < 2.0)
|
75
|
+
rake (13.0.6)
|
73
76
|
rspec (3.9.0)
|
74
77
|
rspec-core (~> 3.9.0)
|
75
78
|
rspec-expectations (~> 3.9.0)
|
76
79
|
rspec-mocks (~> 3.9.0)
|
77
|
-
rspec-core (3.9.
|
78
|
-
rspec-support (~> 3.9.
|
79
|
-
rspec-expectations (3.9.
|
80
|
+
rspec-core (3.9.3)
|
81
|
+
rspec-support (~> 3.9.3)
|
82
|
+
rspec-expectations (3.9.4)
|
80
83
|
diff-lcs (>= 1.2.0, < 2.0)
|
81
84
|
rspec-support (~> 3.9.0)
|
82
85
|
rspec-mocks (3.9.1)
|
@@ -90,7 +93,7 @@ GEM
|
|
90
93
|
rspec-expectations (~> 3.9.0)
|
91
94
|
rspec-mocks (~> 3.9.0)
|
92
95
|
rspec-support (~> 3.9.0)
|
93
|
-
rspec-support (3.9.
|
96
|
+
rspec-support (3.9.4)
|
94
97
|
simplecov (0.16.1)
|
95
98
|
docile (~> 1.1)
|
96
99
|
json (>= 1.8, < 3)
|
@@ -99,26 +102,27 @@ GEM
|
|
99
102
|
sync (0.5.0)
|
100
103
|
term-ansicolor (1.7.1)
|
101
104
|
tins (~> 1.0)
|
102
|
-
thor (1.
|
105
|
+
thor (1.2.1)
|
103
106
|
thread_safe (0.3.6)
|
104
|
-
tins (1.
|
107
|
+
tins (1.31.0)
|
105
108
|
sync
|
106
|
-
tzinfo (1.2.
|
109
|
+
tzinfo (1.2.9)
|
107
110
|
thread_safe (~> 0.1)
|
111
|
+
zeitwerk (2.5.3)
|
108
112
|
|
109
113
|
PLATFORMS
|
110
114
|
ruby
|
111
115
|
|
112
116
|
DEPENDENCIES
|
113
|
-
actionpack (~>
|
114
|
-
activesupport (~>
|
117
|
+
actionpack (~> 6.0.0)
|
118
|
+
activesupport (~> 6.0.0)
|
115
119
|
appraisal (~> 2.2)
|
116
120
|
coveralls (~> 0.8)
|
117
|
-
railties (~>
|
121
|
+
railties (~> 6.0.0)
|
118
122
|
rake (> 12.0)
|
119
123
|
rspec (~> 3.6)
|
120
124
|
rspec-rails (~> 3.6)
|
121
125
|
versioncake!
|
122
126
|
|
123
127
|
BUNDLED WITH
|
124
|
-
|
128
|
+
2.2.15
|
@@ -0,0 +1,127 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
versioncake (4.1.1)
|
5
|
+
actionpack (> 5.0)
|
6
|
+
activesupport (> 5.0)
|
7
|
+
railties (> 5.0)
|
8
|
+
tzinfo (> 1.2)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
actionpack (7.0.1)
|
14
|
+
actionview (= 7.0.1)
|
15
|
+
activesupport (= 7.0.1)
|
16
|
+
rack (~> 2.0, >= 2.2.0)
|
17
|
+
rack-test (>= 0.6.3)
|
18
|
+
rails-dom-testing (~> 2.0)
|
19
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
20
|
+
actionview (7.0.1)
|
21
|
+
activesupport (= 7.0.1)
|
22
|
+
builder (~> 3.1)
|
23
|
+
erubi (~> 1.4)
|
24
|
+
rails-dom-testing (~> 2.0)
|
25
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
26
|
+
activesupport (7.0.1)
|
27
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
28
|
+
i18n (>= 1.6, < 2)
|
29
|
+
minitest (>= 5.1)
|
30
|
+
tzinfo (~> 2.0)
|
31
|
+
appraisal (2.2.0)
|
32
|
+
bundler
|
33
|
+
rake
|
34
|
+
thor (>= 0.14.0)
|
35
|
+
builder (3.2.4)
|
36
|
+
concurrent-ruby (1.1.9)
|
37
|
+
coveralls (0.8.23)
|
38
|
+
json (>= 1.8, < 3)
|
39
|
+
simplecov (~> 0.16.1)
|
40
|
+
term-ansicolor (~> 1.3)
|
41
|
+
thor (>= 0.19.4, < 2.0)
|
42
|
+
tins (~> 1.6)
|
43
|
+
crass (1.0.6)
|
44
|
+
diff-lcs (1.4.4)
|
45
|
+
docile (1.4.0)
|
46
|
+
erubi (1.10.0)
|
47
|
+
i18n (1.8.11)
|
48
|
+
concurrent-ruby (~> 1.0)
|
49
|
+
json (2.6.1)
|
50
|
+
loofah (2.13.0)
|
51
|
+
crass (~> 1.0.2)
|
52
|
+
nokogiri (>= 1.5.9)
|
53
|
+
method_source (1.0.0)
|
54
|
+
mini_portile2 (2.7.1)
|
55
|
+
minitest (5.15.0)
|
56
|
+
nokogiri (1.13.1)
|
57
|
+
mini_portile2 (~> 2.7.0)
|
58
|
+
racc (~> 1.4)
|
59
|
+
racc (1.6.0)
|
60
|
+
rack (2.2.3)
|
61
|
+
rack-test (1.1.0)
|
62
|
+
rack (>= 1.0, < 3)
|
63
|
+
rails-dom-testing (2.0.3)
|
64
|
+
activesupport (>= 4.2.0)
|
65
|
+
nokogiri (>= 1.6)
|
66
|
+
rails-html-sanitizer (1.4.2)
|
67
|
+
loofah (~> 2.3)
|
68
|
+
railties (7.0.1)
|
69
|
+
actionpack (= 7.0.1)
|
70
|
+
activesupport (= 7.0.1)
|
71
|
+
method_source
|
72
|
+
rake (>= 12.2)
|
73
|
+
thor (~> 1.0)
|
74
|
+
zeitwerk (~> 2.5)
|
75
|
+
rake (13.0.6)
|
76
|
+
rspec (3.9.0)
|
77
|
+
rspec-core (~> 3.9.0)
|
78
|
+
rspec-expectations (~> 3.9.0)
|
79
|
+
rspec-mocks (~> 3.9.0)
|
80
|
+
rspec-core (3.9.1)
|
81
|
+
rspec-support (~> 3.9.1)
|
82
|
+
rspec-expectations (3.9.0)
|
83
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
84
|
+
rspec-support (~> 3.9.0)
|
85
|
+
rspec-mocks (3.9.1)
|
86
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
87
|
+
rspec-support (~> 3.9.0)
|
88
|
+
rspec-rails (3.9.1)
|
89
|
+
actionpack (>= 3.0)
|
90
|
+
activesupport (>= 3.0)
|
91
|
+
railties (>= 3.0)
|
92
|
+
rspec-core (~> 3.9.0)
|
93
|
+
rspec-expectations (~> 3.9.0)
|
94
|
+
rspec-mocks (~> 3.9.0)
|
95
|
+
rspec-support (~> 3.9.0)
|
96
|
+
rspec-support (3.9.2)
|
97
|
+
simplecov (0.16.1)
|
98
|
+
docile (~> 1.1)
|
99
|
+
json (>= 1.8, < 3)
|
100
|
+
simplecov-html (~> 0.10.0)
|
101
|
+
simplecov-html (0.10.2)
|
102
|
+
sync (0.5.0)
|
103
|
+
term-ansicolor (1.7.1)
|
104
|
+
tins (~> 1.0)
|
105
|
+
thor (1.2.1)
|
106
|
+
tins (1.24.1)
|
107
|
+
sync
|
108
|
+
tzinfo (2.0.4)
|
109
|
+
concurrent-ruby (~> 1.0)
|
110
|
+
zeitwerk (2.5.3)
|
111
|
+
|
112
|
+
PLATFORMS
|
113
|
+
ruby
|
114
|
+
|
115
|
+
DEPENDENCIES
|
116
|
+
actionpack (~> 7.0.0)
|
117
|
+
activesupport (~> 7.0.0)
|
118
|
+
appraisal (~> 2.2)
|
119
|
+
coveralls (~> 0.8)
|
120
|
+
railties (~> 7.0.0)
|
121
|
+
rake (> 12.0)
|
122
|
+
rspec (~> 3.6)
|
123
|
+
rspec-rails (~> 3.6)
|
124
|
+
versioncake!
|
125
|
+
|
126
|
+
BUNDLED WITH
|
127
|
+
2.2.15
|
@@ -4,8 +4,10 @@ module VersionCake
|
|
4
4
|
def execute(context, _status, headers, _response)
|
5
5
|
return if headers['Content-Type'].nil?
|
6
6
|
|
7
|
-
|
8
|
-
headers['Content-Type']
|
7
|
+
content_type = headers['Content-Type']
|
8
|
+
content_type << ';' unless headers['Content-Type'].end_with?(';')
|
9
|
+
|
10
|
+
headers['Content-Type'] = "#{content_type} #{version_key}=#{context.version.to_s}"
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -2,6 +2,10 @@ require 'active_support/core_ext/string/inflections.rb'
|
|
2
2
|
|
3
3
|
module VersionCake
|
4
4
|
class ExtractionStrategy
|
5
|
+
class InvalidStrategyError < StandardError
|
6
|
+
end
|
7
|
+
class InvalidVersionError < ArgumentError
|
8
|
+
end
|
5
9
|
|
6
10
|
def extract(request)
|
7
11
|
version = execute(request)
|
@@ -12,7 +16,7 @@ module VersionCake
|
|
12
16
|
elsif version_blank?(version)
|
13
17
|
nil
|
14
18
|
else
|
15
|
-
raise
|
19
|
+
raise InvalidVersionError, "Invalid format for version number."
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
@@ -28,7 +32,7 @@ module VersionCake
|
|
28
32
|
# If no version is found, nil should be returned. Any other results returned will raise
|
29
33
|
# an exception.
|
30
34
|
def execute(request)
|
31
|
-
raise
|
35
|
+
raise StandardError, "ExtractionStrategy requires execute to be implemented"
|
32
36
|
end
|
33
37
|
|
34
38
|
def self.list(*strategies)
|
@@ -44,24 +48,24 @@ module VersionCake
|
|
44
48
|
begin
|
45
49
|
VersionCake.const_get(strategy_name).new
|
46
50
|
rescue
|
47
|
-
raise
|
51
|
+
raise InvalidStrategyError, "Unknown VersionCake extraction strategy #{strategy_name}"
|
48
52
|
end
|
49
53
|
when Proc
|
50
54
|
if strategy.arity == 1
|
51
55
|
VersionCake::CustomStrategy.new(strategy)
|
52
56
|
else
|
53
|
-
raise
|
57
|
+
raise InvalidStrategyError, "Custom proc extraction strategy requires a single parameter"
|
54
58
|
end
|
55
59
|
when Object
|
56
60
|
if !strategy.methods.include?(:execute)
|
57
|
-
raise
|
61
|
+
raise InvalidStrategyError, "Custom extraction strategy requires an execute method"
|
58
62
|
elsif strategy.method(:execute).arity != 1
|
59
|
-
raise
|
63
|
+
raise InvalidStrategyError, "Custom extraction strategy requires an execute method with a single parameter"
|
60
64
|
else
|
61
65
|
VersionCake::CustomStrategy.new(strategy)
|
62
66
|
end
|
63
67
|
else
|
64
|
-
raise
|
68
|
+
raise InvalidStrategyError, "Invalid extraction strategy"
|
65
69
|
end
|
66
70
|
end
|
67
71
|
end
|
data/lib/versioncake/version.rb
CHANGED
@@ -1,91 +1,11 @@
|
|
1
1
|
require 'action_view'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
locale: ".",
|
12
|
-
formats: ".",
|
13
|
-
versions: ".",
|
14
|
-
variants: "+",
|
15
|
-
handlers: "."
|
16
|
-
})
|
17
|
-
Kernel::silence_warnings {
|
18
|
-
ActionView::PathResolver::DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:versions,}{+:variants,}{.:handlers,}"
|
19
|
-
}
|
20
|
-
elsif ActionPack::VERSION::MAJOR >= 4 && ActionPack::VERSION::MINOR >= 1 || ActionPack::VERSION::MAJOR >= 5
|
21
|
-
ActionView::PathResolver::EXTENSIONS.replace({
|
22
|
-
locale: ".",
|
23
|
-
formats: ".",
|
24
|
-
versions: ".",
|
25
|
-
variants: "+",
|
26
|
-
handlers: "."
|
27
|
-
})
|
28
|
-
|
29
|
-
def initialize(pattern = nil)
|
30
|
-
@pattern = pattern || ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:versions,}{.:handlers,}"
|
31
|
-
super()
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# The default extract handler expects that the handler is the last extension and
|
36
|
-
# the format is the next one. Since we are replacing the DEFAULT_PATTERN, we need to
|
37
|
-
# make sure that we extract the format from the correct position.
|
38
|
-
#
|
39
|
-
# The version may be stuck inbetween the format and the handler. This is actually pretty tricky
|
40
|
-
# because the version is optional and the locale is optional-which means when there are 3 'pieces'
|
41
|
-
# it may be the locale, format and handler or the format, version and handler. To check this, we will
|
42
|
-
# try one additional time if there are more pieces, which should cover all the cases:
|
43
|
-
#
|
44
|
-
# Cases:
|
45
|
-
# 1: assume version is in the extension, pieces = ['html','erb']
|
46
|
-
# 2: assume version is in the extension, pieces = ['html','v1','erb']
|
47
|
-
# 3: assume version is in the extension, pieces = ['en','html','erb']
|
48
|
-
# 4: assume version is in the extension, pieces = ['en','html','v1','erb']
|
49
|
-
#
|
50
|
-
def extract_handler_and_format(path, default_formats)
|
51
|
-
pieces = File.basename(path).split(".")
|
52
|
-
pieces.shift
|
53
|
-
|
54
|
-
extension = pieces.pop
|
55
|
-
if ActionPack::VERSION::MAJOR == 4
|
56
|
-
unless extension
|
57
|
-
message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
|
58
|
-
"but will change to RAW in the future."
|
59
|
-
ActiveSupport::Deprecation.warn message
|
60
|
-
end
|
61
|
-
end
|
62
|
-
handler = ActionView::Template.handler_for_extension(extension)
|
63
|
-
format = get_format_from_pieces(pieces, (ActionPack::VERSION::MAJOR == 4 ? ActionView::Template::Types : Mime))
|
64
|
-
|
65
|
-
[handler, format]
|
66
|
-
end
|
67
|
-
|
68
|
-
# If there are still pieces and we didn't find a valid format, we may
|
69
|
-
# have a version in the extension, so try one more time to pop the format.
|
70
|
-
def get_format_from_pieces(pieces, format_list)
|
71
|
-
format = nil
|
72
|
-
pieces.reverse.each do |piece|
|
73
|
-
if ActionView::PathResolver::EXTENSIONS.is_a?(Hash) &&
|
74
|
-
ActionView::PathResolver::EXTENSIONS.include?(:variants)
|
75
|
-
piece = piece.split(ActionView::PathResolver::EXTENSIONS[:variants], 2).first # remove variant from format
|
76
|
-
end
|
77
|
-
|
78
|
-
format = format_list[piece]
|
79
|
-
break unless format.nil?
|
80
|
-
end
|
81
|
-
format
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
ActionView::Template.class_eval do
|
86
|
-
# the identifier method name filters out numbers,
|
87
|
-
# but we want to preserve them for v1 etc.
|
88
|
-
def identifier_method_name #:nodoc:
|
89
|
-
inspect.gsub(/[^a-z0-9_]/, '_')
|
90
|
-
end
|
3
|
+
if ActionPack::VERSION::MAJOR >= 7
|
4
|
+
require_relative 'view_additions_rails7'
|
5
|
+
elsif ActionPack::VERSION::MAJOR >= 6
|
6
|
+
require_relative 'view_additions_rails6'
|
7
|
+
elsif ActionPack::VERSION::MAJOR >= 5
|
8
|
+
require_relative 'view_additions_rails5'
|
9
|
+
else
|
10
|
+
raise StandardError.new('Unsupported Rails version')
|
91
11
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
# register an addition detail for the lookup context to understand,
|
4
|
+
# this will allow us to have the versions available upon lookup in
|
5
|
+
# the resolver.
|
6
|
+
ActionView::LookupContext.register_detail(:versions) { [] }
|
7
|
+
|
8
|
+
ActionView::PathResolver.class_eval do
|
9
|
+
ActionView::PathResolver::EXTENSIONS.replace({
|
10
|
+
locale: ".",
|
11
|
+
formats: ".",
|
12
|
+
versions: ".",
|
13
|
+
variants: "+",
|
14
|
+
handlers: "."
|
15
|
+
})
|
16
|
+
|
17
|
+
def initialize(pattern = nil)
|
18
|
+
@pattern = pattern || ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:versions,}{.:handlers,}"
|
19
|
+
super()
|
20
|
+
end
|
21
|
+
|
22
|
+
# The default extract handler expects that the handler is the last extension and
|
23
|
+
# the format is the next one. Since we are replacing the DEFAULT_PATTERN, we need to
|
24
|
+
# make sure that we extract the format from the correct position.
|
25
|
+
#
|
26
|
+
# The version may be stuck inbetween the format and the handler. This is actually pretty tricky
|
27
|
+
# because the version is optional and the locale is optional-which means when there are 3 'pieces'
|
28
|
+
# it may be the locale, format and handler or the format, version and handler. To check this, we will
|
29
|
+
# try one additional time if there are more pieces, which should cover all the cases:
|
30
|
+
#
|
31
|
+
# Cases:
|
32
|
+
# 1: assume version is in the extension, pieces = ['html','erb']
|
33
|
+
# 2: assume version is in the extension, pieces = ['html','v1','erb']
|
34
|
+
# 3: assume version is in the extension, pieces = ['en','html','erb']
|
35
|
+
# 4: assume version is in the extension, pieces = ['en','html','v1','erb']
|
36
|
+
#
|
37
|
+
def extract_handler_and_format_and_variant(path, default_formats=nil)
|
38
|
+
pieces = File.basename(path).split('.'.freeze)
|
39
|
+
pieces.shift
|
40
|
+
|
41
|
+
extension = pieces.pop
|
42
|
+
|
43
|
+
handler = ActionView::Template.handler_for_extension(extension)
|
44
|
+
format, variant = get_format_and_variant_from_pieces(pieces, Mime)
|
45
|
+
format &&= ActionView::Template::Types[format]
|
46
|
+
|
47
|
+
[handler, format, variant]
|
48
|
+
end
|
49
|
+
|
50
|
+
# If there are still pieces and we didn't find a valid format, we may
|
51
|
+
# have a version in the extension, so try one more time to pop the format.
|
52
|
+
def get_format_and_variant_from_pieces(pieces, format_list)
|
53
|
+
variant, format = nil
|
54
|
+
pieces.reverse.each do |piece|
|
55
|
+
piece, variant = piece.split(ActionView::PathResolver::EXTENSIONS[:variants], 2)
|
56
|
+
|
57
|
+
format = format_list[piece]
|
58
|
+
break unless format.nil?
|
59
|
+
end
|
60
|
+
[format, variant]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ActionView::Template.class_eval do
|
65
|
+
# the identifier method name filters out numbers,
|
66
|
+
# but we want to preserve them for v1 etc.
|
67
|
+
def identifier_method_name #:nodoc:
|
68
|
+
inspect.gsub(/[^a-z0-9_]/, '_')
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
# register an addition detail for the lookup context to understand,
|
4
|
+
# this will allow us to have the versions available upon lookup in
|
5
|
+
# the resolver.
|
6
|
+
ActionView::LookupContext.register_detail(:versions){ [] }
|
7
|
+
|
8
|
+
ActionView::PathResolver.class_eval do
|
9
|
+
ActionView::PathResolver::EXTENSIONS.replace({
|
10
|
+
locale: ".",
|
11
|
+
formats: ".",
|
12
|
+
versions: ".",
|
13
|
+
variants: "+",
|
14
|
+
handlers: "."
|
15
|
+
})
|
16
|
+
Kernel::silence_warnings {
|
17
|
+
ActionView::PathResolver::DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:versions,}{+:variants,}{.:handlers,}"
|
18
|
+
}
|
19
|
+
|
20
|
+
# The default extract handler expects that the handler is the last extension and
|
21
|
+
# the format is the next one. Since we are replacing the DEFAULT_PATTERN, we need to
|
22
|
+
# make sure that we extract the format from the correct position.
|
23
|
+
#
|
24
|
+
# The version may be stuck inbetween the format and the handler. This is actually pretty tricky
|
25
|
+
# because the version is optional and the locale is optional-which means when there are 3 'pieces'
|
26
|
+
# it may be the locale, format and handler or the format, version and handler. To check this, we will
|
27
|
+
# try one additional time if there are more pieces, which should cover all the cases:
|
28
|
+
#
|
29
|
+
# Cases:
|
30
|
+
# 1: assume version is in the extension, pieces = ['html','erb']
|
31
|
+
# 2: assume version is in the extension, pieces = ['html','v1','erb']
|
32
|
+
# 3: assume version is in the extension, pieces = ['en','html','erb']
|
33
|
+
# 4: assume version is in the extension, pieces = ['en','html','v1','erb']
|
34
|
+
#
|
35
|
+
def extract_handler_and_format(path, default_formats)
|
36
|
+
pieces = File.basename(path).split(".")
|
37
|
+
pieces.shift
|
38
|
+
|
39
|
+
extension = pieces.pop
|
40
|
+
handler = ActionView::Template.handler_for_extension(extension)
|
41
|
+
format = get_format_from_pieces(pieces, Mime)
|
42
|
+
|
43
|
+
[handler, format]
|
44
|
+
end
|
45
|
+
|
46
|
+
# If there are still pieces and we didn't find a valid format, we may
|
47
|
+
# have a version in the extension, so try one more time to pop the format.
|
48
|
+
def get_format_from_pieces(pieces, format_list)
|
49
|
+
format = nil
|
50
|
+
pieces.reverse.each do |piece|
|
51
|
+
if ActionView::PathResolver::EXTENSIONS.is_a?(Hash) &&
|
52
|
+
ActionView::PathResolver::EXTENSIONS.include?(:variants)
|
53
|
+
piece = piece.split(ActionView::PathResolver::EXTENSIONS[:variants], 2).first # remove variant from format
|
54
|
+
end
|
55
|
+
|
56
|
+
format = format_list[piece]
|
57
|
+
break unless format.nil?
|
58
|
+
end
|
59
|
+
format
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ActionView::Template.class_eval do
|
64
|
+
# the identifier method name filters out numbers,
|
65
|
+
# but we want to preserve them for v1 etc.
|
66
|
+
def identifier_method_name #:nodoc:
|
67
|
+
inspect.gsub(/[^a-z0-9_]/, '_')
|
68
|
+
end
|
69
|
+
end
|