actionview 5.1.4 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +199 -168
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -5
  5. data/lib/action_view.rb +10 -4
  6. data/lib/action_view/base.rb +87 -23
  7. data/lib/action_view/buffers.rb +17 -0
  8. data/lib/action_view/cache_expiry.rb +52 -0
  9. data/lib/action_view/context.rb +7 -11
  10. data/lib/action_view/dependency_tracker.rb +12 -4
  11. data/lib/action_view/digestor.rb +24 -23
  12. data/lib/action_view/flows.rb +2 -1
  13. data/lib/action_view/gem_version.rb +4 -2
  14. data/lib/action_view/helpers.rb +4 -2
  15. data/lib/action_view/helpers/active_model_helper.rb +9 -4
  16. data/lib/action_view/helpers/asset_tag_helper.rb +220 -57
  17. data/lib/action_view/helpers/asset_url_helper.rb +28 -23
  18. data/lib/action_view/helpers/atom_feed_helper.rb +5 -2
  19. data/lib/action_view/helpers/cache_helper.rb +39 -28
  20. data/lib/action_view/helpers/capture_helper.rb +13 -7
  21. data/lib/action_view/helpers/controller_helper.rb +3 -1
  22. data/lib/action_view/helpers/csp_helper.rb +26 -0
  23. data/lib/action_view/helpers/csrf_helper.rb +5 -3
  24. data/lib/action_view/helpers/date_helper.rb +78 -33
  25. data/lib/action_view/helpers/debug_helper.rb +4 -2
  26. data/lib/action_view/helpers/form_helper.rb +357 -106
  27. data/lib/action_view/helpers/form_options_helper.rb +45 -39
  28. data/lib/action_view/helpers/form_tag_helper.rb +42 -27
  29. data/lib/action_view/helpers/javascript_helper.rb +28 -12
  30. data/lib/action_view/helpers/number_helper.rb +16 -8
  31. data/lib/action_view/helpers/output_safety_helper.rb +3 -1
  32. data/lib/action_view/helpers/rendering_helper.rb +20 -9
  33. data/lib/action_view/helpers/sanitize_helper.rb +15 -19
  34. data/lib/action_view/helpers/tag_helper.rb +100 -24
  35. data/lib/action_view/helpers/tags.rb +3 -1
  36. data/lib/action_view/helpers/tags/base.rb +30 -21
  37. data/lib/action_view/helpers/tags/check_box.rb +3 -2
  38. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  39. data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -1
  40. data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
  41. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -1
  42. data/lib/action_view/helpers/tags/collection_select.rb +3 -1
  43. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  44. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  45. data/lib/action_view/helpers/tags/date_select.rb +5 -4
  46. data/lib/action_view/helpers/tags/datetime_field.rb +3 -2
  47. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  48. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  49. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  50. data/lib/action_view/helpers/tags/file_field.rb +2 -0
  51. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -1
  52. data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
  53. data/lib/action_view/helpers/tags/label.rb +6 -5
  54. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  55. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  56. data/lib/action_view/helpers/tags/password_field.rb +2 -0
  57. data/lib/action_view/helpers/tags/placeholderable.rb +2 -0
  58. data/lib/action_view/helpers/tags/radio_button.rb +3 -2
  59. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  60. data/lib/action_view/helpers/tags/search_field.rb +2 -0
  61. data/lib/action_view/helpers/tags/select.rb +4 -3
  62. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  63. data/lib/action_view/helpers/tags/text_area.rb +3 -1
  64. data/lib/action_view/helpers/tags/text_field.rb +3 -2
  65. data/lib/action_view/helpers/tags/time_field.rb +3 -2
  66. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  67. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  68. data/lib/action_view/helpers/tags/translator.rb +3 -6
  69. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  70. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  71. data/lib/action_view/helpers/text_helper.rb +11 -10
  72. data/lib/action_view/helpers/translation_helper.rb +102 -52
  73. data/lib/action_view/helpers/url_helper.rb +150 -32
  74. data/lib/action_view/layouts.rb +15 -15
  75. data/lib/action_view/log_subscriber.rb +32 -15
  76. data/lib/action_view/lookup_context.rb +67 -39
  77. data/lib/action_view/model_naming.rb +2 -0
  78. data/lib/action_view/path_set.rb +5 -12
  79. data/lib/action_view/railtie.rb +46 -21
  80. data/lib/action_view/record_identifier.rb +4 -3
  81. data/lib/action_view/renderer/abstract_renderer.rb +144 -11
  82. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  83. data/lib/action_view/renderer/object_renderer.rb +34 -0
  84. data/lib/action_view/renderer/partial_renderer.rb +33 -283
  85. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +64 -17
  86. data/lib/action_view/renderer/renderer.rb +61 -4
  87. data/lib/action_view/renderer/streaming_template_renderer.rb +14 -8
  88. data/lib/action_view/renderer/template_renderer.rb +36 -26
  89. data/lib/action_view/rendering.rb +57 -38
  90. data/lib/action_view/routing_url_for.rb +15 -12
  91. data/lib/action_view/tasks/cache_digests.rake +2 -0
  92. data/lib/action_view/template.rb +69 -76
  93. data/lib/action_view/template/error.rb +32 -18
  94. data/lib/action_view/template/handlers.rb +4 -2
  95. data/lib/action_view/template/handlers/builder.rb +5 -6
  96. data/lib/action_view/template/handlers/erb.rb +20 -19
  97. data/lib/action_view/template/handlers/erb/erubi.rb +17 -9
  98. data/lib/action_view/template/handlers/html.rb +3 -1
  99. data/lib/action_view/template/handlers/raw.rb +4 -2
  100. data/lib/action_view/template/html.rb +8 -7
  101. data/lib/action_view/template/inline.rb +22 -0
  102. data/lib/action_view/template/raw_file.rb +25 -0
  103. data/lib/action_view/template/renderable.rb +24 -0
  104. data/lib/action_view/template/resolver.rb +194 -152
  105. data/lib/action_view/template/sources.rb +13 -0
  106. data/lib/action_view/template/sources/file.rb +17 -0
  107. data/lib/action_view/template/text.rb +5 -4
  108. data/lib/action_view/template/types.rb +3 -1
  109. data/lib/action_view/test_case.rb +38 -30
  110. data/lib/action_view/testing/resolvers.rb +20 -27
  111. data/lib/action_view/unbound_template.rb +31 -0
  112. data/lib/action_view/version.rb +2 -0
  113. data/lib/action_view/view_paths.rb +61 -40
  114. data/lib/assets/compiled/rails-ujs.js +84 -23
  115. metadata +34 -23
  116. data/lib/action_view/helpers/record_tag_helper.rb +0 -21
  117. data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +0 -9
  118. data/lib/action_view/template/handlers/erb/erubis.rb +0 -81
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ extend ActiveSupport::Autoload
7
+
8
+ eager_autoload do
9
+ autoload :File
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ class File
7
+ def initialize(filename)
8
+ @filename = filename
9
+ end
10
+
11
+ def to_s
12
+ ::File.binread @filename
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,12 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView #:nodoc:
2
4
  # = Action View Text Template
3
- class Template
5
+ class Template #:nodoc:
4
6
  class Text #:nodoc:
5
7
  attr_accessor :type
6
8
 
7
9
  def initialize(string)
8
10
  @string = string.to_s
9
- @type = Types[:text]
10
11
  end
11
12
 
12
13
  def identifier
@@ -23,8 +24,8 @@ module ActionView #:nodoc:
23
24
  to_str
24
25
  end
25
26
 
26
- def formats
27
- [@type.ref]
27
+ def format
28
+ :text
28
29
  end
29
30
  end
30
31
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
4
 
3
5
  module ActionView
4
- class Template
6
+ class Template #:nodoc:
5
7
  class Types
6
8
  class Type
7
9
  SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
@@ -1,4 +1,6 @@
1
- require "active_support/core_ext/module/remove_method"
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
2
4
  require "action_controller"
3
5
  require "action_controller/test_case"
4
6
  require "action_view"
@@ -14,11 +16,12 @@ module ActionView
14
16
  attr_accessor :request, :response, :params
15
17
 
16
18
  class << self
17
- attr_writer :controller_path
19
+ # Overrides AbstractController::Base#controller_path
20
+ attr_accessor :controller_path
18
21
  end
19
22
 
20
23
  def controller_path=(path)
21
- self.class.controller_path = (path)
24
+ self.class.controller_path = path
22
25
  end
23
26
 
24
27
  def initialize
@@ -71,10 +74,11 @@ module ActionView
71
74
  def helper_method(*methods)
72
75
  # Almost a duplicate from ActionController::Helpers
73
76
  methods.flatten.each do |method|
74
- _helpers.module_eval <<-end_eval
77
+ _helpers_for_modification.module_eval <<-end_eval, __FILE__, __LINE__ + 1
75
78
  def #{method}(*args, &block) # def current_user(*args, &block)
76
- _test_case.send(%(#{method}), *args, &block) # _test_case.send(%(current_user), *args, &block)
79
+ _test_case.send(:'#{method}', *args, &block) # _test_case.send(:'current_user', *args, &block)
77
80
  end # end
81
+ ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
78
82
  end_eval
79
83
  end
80
84
  end
@@ -91,7 +95,6 @@ module ActionView
91
95
  end
92
96
 
93
97
  private
94
-
95
98
  def include_helper_modules!
96
99
  helper(helper_class) if helper_class
97
100
  include _helpers
@@ -99,15 +102,17 @@ module ActionView
99
102
  end
100
103
 
101
104
  def setup_with_controller
102
- @controller = ActionView::TestCase::TestController.new
105
+ controller_class = Class.new(ActionView::TestCase::TestController)
106
+ @controller = controller_class.new
103
107
  @request = @controller.request
108
+ @view_flow = ActionView::OutputFlow.new
104
109
  # empty string ensures buffer has UTF-8 encoding as
105
110
  # new without arguments returns ASCII-8BIT encoded buffer like String#new
106
111
  @output_buffer = ActiveSupport::SafeBuffer.new ""
107
- @rendered = ""
112
+ @rendered = +""
108
113
 
109
- make_test_case_available_to_view!
110
- say_no_to_protect_against_forgery!
114
+ test_case_instance = self
115
+ controller_class.define_method(:_test_case) { test_case_instance }
111
116
  end
112
117
 
113
118
  def config
@@ -157,34 +162,24 @@ module ActionView
157
162
  included do
158
163
  setup :setup_with_controller
159
164
  ActiveSupport.run_load_hooks(:action_view_test_case, self)
160
- end
161
165
 
162
- private
163
-
164
- # Need to experiment if this priority is the best one: rendered => output_buffer
165
- def document_root_element
166
- Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
167
- end
168
-
169
- def say_no_to_protect_against_forgery!
170
- _helpers.module_eval do
171
- remove_possible_method :protect_against_forgery?
166
+ helper do
172
167
  def protect_against_forgery?
173
168
  false
174
169
  end
175
- end
176
- end
177
170
 
178
- def make_test_case_available_to_view!
179
- test_case_instance = self
180
- _helpers.module_eval do
181
- unless private_method_defined?(:_test_case)
182
- define_method(:_test_case) { test_case_instance }
183
- private :_test_case
171
+ def _test_case
172
+ controller._test_case
184
173
  end
185
174
  end
186
175
  end
187
176
 
177
+ private
178
+ # Need to experiment if this priority is the best one: rendered => output_buffer
179
+ def document_root_element
180
+ Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
181
+ end
182
+
188
183
  module Locals
189
184
  attr_accessor :rendered_views
190
185
 
@@ -244,6 +239,7 @@ module ActionView
244
239
  :@test_passed,
245
240
  :@view,
246
241
  :@view_context_class,
242
+ :@view_flow,
247
243
  :@_subscribers,
248
244
  :@html_document
249
245
  ]
@@ -266,7 +262,7 @@ module ActionView
266
262
  begin
267
263
  routes = @controller.respond_to?(:_routes) && @controller._routes
268
264
  rescue
269
- # Dont call routes, if there is an error on _routes call
265
+ # Don't call routes, if there is an error on _routes call
270
266
  end
271
267
 
272
268
  if routes &&
@@ -277,6 +273,18 @@ module ActionView
277
273
  super
278
274
  end
279
275
  end
276
+
277
+ def respond_to_missing?(name, include_private = false)
278
+ begin
279
+ routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes
280
+ rescue
281
+ # Don't call routes, if there is an error on _routes call
282
+ end
283
+
284
+ routes &&
285
+ (routes.named_routes.route_defined?(name) ||
286
+ routes.mounted_helpers.method_defined?(name))
287
+ end
280
288
  end
281
289
 
282
290
  include Behavior
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_view/template/resolver"
2
4
 
3
5
  module ActionView #:nodoc:
@@ -5,12 +7,15 @@ module ActionView #:nodoc:
5
7
  # file system. This is used internally by Rails' own test suite, and is
6
8
  # useful for testing extensions that have no way of knowing what the file
7
9
  # system will look like at runtime.
8
- class FixtureResolver < PathResolver
9
- attr_reader :hash
10
-
11
- def initialize(hash = {}, pattern = nil)
12
- super(pattern)
10
+ class FixtureResolver < OptimizedFileSystemResolver
11
+ def initialize(hash = {})
12
+ super("")
13
13
  @hash = hash
14
+ @path = ""
15
+ end
16
+
17
+ def data
18
+ @hash
14
19
  end
15
20
 
16
21
  def to_s
@@ -18,35 +23,23 @@ module ActionView #:nodoc:
18
23
  end
19
24
 
20
25
  private
21
-
22
- def query(path, exts, _, _)
23
- query = ""
24
- EXTENSIONS.each_key do |ext|
25
- query << "(" << exts[ext].map { |e| e && Regexp.escape(".#{e}") }.join("|") << "|)"
26
- end
27
- query = /^(#{Regexp.escape(path)})#{query}$/
28
-
29
- templates = []
30
- @hash.each do |_path, array|
31
- source, updated_at = array
32
- next unless query.match?(_path)
33
- handler, format, variant = extract_handler_and_format_and_variant(_path)
34
- templates << Template.new(source, _path, handler,
35
- virtual_path: path.virtual,
36
- format: format,
37
- variant: variant,
38
- updated_at: updated_at
39
- )
26
+ def find_candidate_template_paths(path)
27
+ @hash.keys.select do |fixture|
28
+ fixture.start_with?(path.virtual)
29
+ end.map do |fixture|
30
+ "/#{fixture}"
40
31
  end
32
+ end
41
33
 
42
- templates.sort_by { |t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
34
+ def source_for_template(template)
35
+ @hash[template[1..template.size]]
43
36
  end
44
37
  end
45
38
 
46
39
  class NullResolver < PathResolver
47
- def query(path, exts, _, _)
40
+ def query(path, exts, _, locals, cache:)
48
41
  handler, format, variant = extract_handler_and_format_and_variant(path)
49
- [ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: format, variant: variant)]
42
+ [ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: format, variant: variant, locals: locals)]
50
43
  end
51
44
  end
52
45
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+
5
+ module ActionView
6
+ class UnboundTemplate
7
+ def initialize(source, identifier, handler, options)
8
+ @source = source
9
+ @identifier = identifier
10
+ @handler = handler
11
+ @options = options
12
+
13
+ @templates = Concurrent::Map.new(initial_capacity: 2)
14
+ end
15
+
16
+ def bind_locals(locals)
17
+ @templates[locals] ||= build_template(locals)
18
+ end
19
+
20
+ private
21
+ def build_template(locals)
22
+ options = @options.merge(locals: locals)
23
+ Template.new(
24
+ @source,
25
+ @identifier,
26
+ @handler,
27
+ **options
28
+ )
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "gem_version"
2
4
 
3
5
  module ActionView
@@ -1,17 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module ViewPaths
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :_view_paths
7
- self._view_paths = ActionView::PathSet.new
8
- _view_paths.freeze
8
+ ViewPaths.set_view_paths(self, ActionView::PathSet.new.freeze)
9
9
  end
10
10
 
11
11
  delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
12
12
  :locale, :locale=, to: :lookup_context
13
13
 
14
14
  module ClassMethods
15
+ def _view_paths
16
+ ViewPaths.get_view_paths(self)
17
+ end
18
+
19
+ def _view_paths=(paths)
20
+ ViewPaths.set_view_paths(self, paths)
21
+ end
22
+
15
23
  def _prefixes # :nodoc:
16
24
  @_prefixes ||= begin
17
25
  return local_prefixes if superclass.abstract?
@@ -20,8 +28,41 @@ module ActionView
20
28
  end
21
29
  end
22
30
 
23
- private
31
+ # Append a path to the list of view paths for this controller.
32
+ #
33
+ # ==== Parameters
34
+ # * <tt>path</tt> - If a String is provided, it gets converted into
35
+ # the default view path. You may also provide a custom view path
36
+ # (see ActionView::PathSet for more information)
37
+ def append_view_path(path)
38
+ self._view_paths = view_paths + Array(path)
39
+ end
40
+
41
+ # Prepend a path to the list of view paths for this controller.
42
+ #
43
+ # ==== Parameters
44
+ # * <tt>path</tt> - If a String is provided, it gets converted into
45
+ # the default view path. You may also provide a custom view path
46
+ # (see ActionView::PathSet for more information)
47
+ def prepend_view_path(path)
48
+ self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
49
+ end
24
50
 
51
+ # A list of all of the default view paths for this controller.
52
+ def view_paths
53
+ _view_paths
54
+ end
55
+
56
+ # Set the view paths.
57
+ #
58
+ # ==== Parameters
59
+ # * <tt>paths</tt> - If a PathSet is provided, use that;
60
+ # otherwise, process the parameter into a PathSet.
61
+ def view_paths=(paths)
62
+ self._view_paths = ActionView::PathSet.new(Array(paths))
63
+ end
64
+
65
+ private
25
66
  # Override this method in your controller if you want to change paths prefixes for finding views.
26
67
  # Prefixes defined here will still be added to parents' <tt>._prefixes</tt>.
27
68
  def local_prefixes
@@ -29,6 +70,22 @@ module ActionView
29
70
  end
30
71
  end
31
72
 
73
+ # :stopdoc:
74
+ @all_view_paths = {}
75
+
76
+ def self.get_view_paths(klass)
77
+ @all_view_paths[klass] || get_view_paths(klass.superclass)
78
+ end
79
+
80
+ def self.set_view_paths(klass, paths)
81
+ @all_view_paths[klass] = paths
82
+ end
83
+
84
+ def self.all_view_paths
85
+ @all_view_paths.values.uniq
86
+ end
87
+ # :startdoc:
88
+
32
89
  # The prefixes used in render "foo" shortcuts.
33
90
  def _prefixes # :nodoc:
34
91
  self.class._prefixes
@@ -65,41 +122,5 @@ module ActionView
65
122
  def prepend_view_path(path)
66
123
  lookup_context.view_paths.unshift(*path)
67
124
  end
68
-
69
- module ClassMethods
70
- # Append a path to the list of view paths for this controller.
71
- #
72
- # ==== Parameters
73
- # * <tt>path</tt> - If a String is provided, it gets converted into
74
- # the default view path. You may also provide a custom view path
75
- # (see ActionView::PathSet for more information)
76
- def append_view_path(path)
77
- self._view_paths = view_paths + Array(path)
78
- end
79
-
80
- # Prepend a path to the list of view paths for this controller.
81
- #
82
- # ==== Parameters
83
- # * <tt>path</tt> - If a String is provided, it gets converted into
84
- # the default view path. You may also provide a custom view path
85
- # (see ActionView::PathSet for more information)
86
- def prepend_view_path(path)
87
- self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
88
- end
89
-
90
- # A list of all of the default view paths for this controller.
91
- def view_paths
92
- _view_paths
93
- end
94
-
95
- # Set the view paths.
96
- #
97
- # ==== Parameters
98
- # * <tt>paths</tt> - If a PathSet is provided, use that;
99
- # otherwise, process the parameter into a PathSet.
100
- def view_paths=(paths)
101
- self._view_paths = ActionView::PathSet.new(Array(paths))
102
- end
103
- end
104
125
  end
105
126
  end