versioncake 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +33 -0
  3. data/Appraisals +9 -3
  4. data/CHANGELOG.md +42 -1
  5. data/Gemfile.lock +31 -29
  6. data/README.md +13 -11
  7. data/SECURITY.md +9 -0
  8. data/gemfiles/rails5.0.gemfile.lock +77 -72
  9. data/gemfiles/rails5.2.gemfile.lock +66 -62
  10. data/gemfiles/rails6.0.gemfile +3 -3
  11. data/gemfiles/rails6.0.gemfile.lock +73 -67
  12. data/gemfiles/rails7.0.gemfile +9 -0
  13. data/gemfiles/rails7.0.gemfile.lock +127 -0
  14. data/lib/versioncake/controller_additions.rb +0 -6
  15. data/lib/versioncake/railtie.rb +9 -0
  16. data/lib/versioncake/response_strategy/http_content_type_strategy.rb +4 -2
  17. data/lib/versioncake/strategies/extraction_strategy.rb +11 -7
  18. data/lib/versioncake/version.rb +1 -1
  19. data/lib/versioncake/version_checker.rb +2 -1
  20. data/lib/versioncake/version_context_service.rb +1 -1
  21. data/lib/versioncake/versioned_request.rb +1 -1
  22. data/lib/versioncake/view_additions.rb +8 -88
  23. data/lib/versioncake/view_additions_rails5.rb +70 -0
  24. data/lib/versioncake/view_additions_rails6.rb +69 -0
  25. data/lib/versioncake/view_additions_rails7.rb +155 -0
  26. data/lib/versioncake.rb +3 -1
  27. data/spec/integration/controller/unversioned_controller_spec.rb +1 -1
  28. data/spec/integration/view/render_spec.rb +8 -1
  29. data/spec/integration/view/view_additions_rails5_spec.rb +67 -0
  30. data/spec/integration/view/view_additions_rails6_spec.rb +44 -0
  31. data/spec/integration/view/view_additions_rails7_spec.rb +76 -0
  32. data/spec/unit/strategies/extraction_strategy_spec.rb +2 -2
  33. data/spec/unit/version_checker_spec.rb +1 -1
  34. data/spec/unit/versioned_request_spec.rb +0 -7
  35. data/versioncake.gemspec +5 -5
  36. metadata +29 -20
  37. data/.travis.yml +0 -20
  38. data/spec/integration/view/view_additions_spec.rb +0 -42
@@ -2,8 +2,8 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "actionpack", "~> 5.2.0"
6
- gem "activesupport", "~> 5.2.0"
7
- gem "railties", "~> 5.2.0"
5
+ gem "actionpack", "~> 6.0.0"
6
+ gem "activesupport", "~> 6.0.0"
7
+ gem "railties", "~> 6.0.0"
8
8
 
9
9
  gemspec path: "../"
@@ -1,122 +1,128 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- versioncake (3.4.0)
5
- actionpack (>= 5.0)
6
- activesupport (>= 5.0)
7
- railties (>= 5.0)
8
- tzinfo
4
+ versioncake (4.1.0)
5
+ actionpack (> 5.0)
6
+ activesupport (> 5.0)
7
+ railties (> 5.0)
8
+ tzinfo (> 1.2)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- actionpack (5.2.4.1)
14
- actionview (= 5.2.4.1)
15
- activesupport (= 5.2.4.1)
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.2)
20
- actionview (5.2.4.1)
21
- activesupport (= 5.2.4.1)
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.0, >= 1.0.3)
26
- activesupport (5.2.4.1)
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
- appraisal (2.2.0)
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.6)
37
- coveralls (0.8.21)
37
+ concurrent-ruby (1.1.9)
38
+ coveralls (0.8.23)
38
39
  json (>= 1.8, < 3)
39
- simplecov (~> 0.14.1)
40
+ simplecov (~> 0.16.1)
40
41
  term-ansicolor (~> 1.3)
41
- thor (~> 0.19.4)
42
+ thor (>= 0.19.4, < 2.0)
42
43
  tins (~> 1.6)
43
44
  crass (1.0.6)
44
- diff-lcs (1.3)
45
- docile (1.1.5)
46
- erubi (1.9.0)
47
- i18n (1.8.2)
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.2.0)
50
- loofah (2.4.0)
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.9.2)
54
- mini_portile2 (2.4.0)
55
- minitest (5.14.0)
56
- nokogiri (1.10.9)
57
- mini_portile2 (~> 2.4.0)
58
- rack (2.2.2)
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.3.0)
67
+ rails-html-sanitizer (1.4.2)
65
68
  loofah (~> 2.3)
66
- railties (5.2.4.1)
67
- actionpack (= 5.2.4.1)
68
- activesupport (= 5.2.4.1)
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.19.0, < 2.0)
72
- rake (13.0.1)
73
- rspec (3.7.0)
74
- rspec-core (~> 3.7.0)
75
- rspec-expectations (~> 3.7.0)
76
- rspec-mocks (~> 3.7.0)
77
- rspec-core (3.7.1)
78
- rspec-support (~> 3.7.0)
79
- rspec-expectations (3.7.0)
74
+ thor (>= 0.20.3, < 2.0)
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.3)
81
+ rspec-support (~> 3.9.3)
82
+ rspec-expectations (3.9.4)
80
83
  diff-lcs (>= 1.2.0, < 2.0)
81
- rspec-support (~> 3.7.0)
82
- rspec-mocks (3.7.0)
84
+ rspec-support (~> 3.9.0)
85
+ rspec-mocks (3.9.1)
83
86
  diff-lcs (>= 1.2.0, < 2.0)
84
- rspec-support (~> 3.7.0)
85
- rspec-rails (3.7.2)
87
+ rspec-support (~> 3.9.0)
88
+ rspec-rails (3.9.1)
86
89
  actionpack (>= 3.0)
87
90
  activesupport (>= 3.0)
88
91
  railties (>= 3.0)
89
- rspec-core (~> 3.7.0)
90
- rspec-expectations (~> 3.7.0)
91
- rspec-mocks (~> 3.7.0)
92
- rspec-support (~> 3.7.0)
93
- rspec-support (3.7.1)
94
- simplecov (0.14.1)
95
- docile (~> 1.1.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.4)
97
+ simplecov (0.16.1)
98
+ docile (~> 1.1)
96
99
  json (>= 1.8, < 3)
97
100
  simplecov-html (~> 0.10.0)
98
101
  simplecov-html (0.10.2)
99
- term-ansicolor (1.6.0)
102
+ sync (0.5.0)
103
+ term-ansicolor (1.7.1)
100
104
  tins (~> 1.0)
101
- thor (0.19.4)
105
+ thor (1.2.1)
102
106
  thread_safe (0.3.6)
103
- tins (1.15.0)
104
- tzinfo (1.2.6)
107
+ tins (1.31.0)
108
+ sync
109
+ tzinfo (1.2.9)
105
110
  thread_safe (~> 0.1)
111
+ zeitwerk (2.5.3)
106
112
 
107
113
  PLATFORMS
108
114
  ruby
109
115
 
110
116
  DEPENDENCIES
111
- actionpack (~> 5.2.0)
112
- activesupport (~> 5.2.0)
113
- appraisal
114
- coveralls
115
- railties (~> 5.2.0)
116
- rake
117
- rspec
118
- rspec-rails
117
+ actionpack (~> 6.0.0)
118
+ activesupport (~> 6.0.0)
119
+ appraisal (~> 2.2)
120
+ coveralls (~> 0.8)
121
+ railties (~> 6.0.0)
122
+ rake (> 12.0)
123
+ rspec (~> 3.6)
124
+ rspec-rails (~> 3.6)
119
125
  versioncake!
120
126
 
121
127
  BUNDLED WITH
122
- 1.17.2
128
+ 2.2.15
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 7.0.0"
6
+ gem "activesupport", "~> 7.0.0"
7
+ gem "railties", "~> 7.0.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,127 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ versioncake (4.1.0)
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
@@ -83,9 +83,3 @@ module VersionCake
83
83
  end
84
84
  end
85
85
  end
86
-
87
- ActionController::Base.send(:include, VersionCake::ControllerAdditions)
88
-
89
- if defined?(ActionController::API)
90
- ActionController::API.send(:include, VersionCake::ControllerAdditions)
91
- end
@@ -0,0 +1,9 @@
1
+ require 'rails/railtie'
2
+
3
+ class Railtie < ::Rails::Railtie
4
+ initializer :versioncake do
5
+ ActiveSupport.on_load :action_controller do
6
+ include VersionCake::ControllerAdditions
7
+ end
8
+ end
9
+ end
@@ -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
- headers['Content-Type'] << ';' unless headers['Content-Type'].end_with? ';'
8
- headers['Content-Type'] << " #{version_key}=#{context.version.to_s}"
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 Exception, "Invalid format for version number."
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 Exception, "ExtractionStrategy requires execute to be implemented"
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 Exception, "Unknown VersionCake extraction strategy #{strategy_name}"
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 Exception, "Custom proc extraction strategy requires a single parameter"
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 Exception, "Custom extraction strategy requires an execute method"
61
+ raise InvalidStrategyError, "Custom extraction strategy requires an execute method"
58
62
  elsif strategy.method(:execute).arity != 1
59
- raise Exception, "Custom extraction strategy requires an execute method with a single parameter"
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 Exception, "Invalid extration strategy"
68
+ raise InvalidStrategyError, "Invalid extraction strategy"
65
69
  end
66
70
  end
67
71
  end
@@ -1,3 +1,3 @@
1
1
  module VersionCake
2
- VERSION = '4.0.0'
2
+ VERSION = '4.1.0'
3
3
  end
@@ -2,7 +2,8 @@ module VersionCake
2
2
  class VersionChecker
3
3
  attr_reader :result
4
4
  def initialize(version, resource)
5
- @version, @resource = resource, version
5
+ @version = version
6
+ @resource = resource
6
7
  end
7
8
 
8
9
  def execute
@@ -43,7 +43,7 @@ module VersionCake
43
43
  private
44
44
 
45
45
  def check_version(resource, version)
46
- VersionCake::VersionChecker.new(resource, version).execute
46
+ VersionCake::VersionChecker.new(version, resource).execute
47
47
  end
48
48
 
49
49
  def find_resource(uri)
@@ -15,7 +15,7 @@ module VersionCake
15
15
  else
16
16
  @version = extracted_version
17
17
  end
18
- rescue Exception
18
+ rescue VersionCake::ExtractionStrategy::InvalidVersionError
19
19
  @failed = true
20
20
  end
21
21
  end
@@ -1,91 +1,11 @@
1
1
  require 'action_view'
2
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
- if ActionPack::VERSION::MAJOR >= 6
10
- ActionView::PathResolver::EXTENSIONS.replace({
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