actionview 6.0.3.1 → 6.1.0.rc2

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +160 -209
  3. data/MIT-LICENSE +1 -1
  4. data/lib/action_view.rb +4 -1
  5. data/lib/action_view/base.rb +21 -52
  6. data/lib/action_view/cache_expiry.rb +1 -2
  7. data/lib/action_view/context.rb +0 -1
  8. data/lib/action_view/dependency_tracker.rb +10 -4
  9. data/lib/action_view/digestor.rb +3 -2
  10. data/lib/action_view/gem_version.rb +3 -3
  11. data/lib/action_view/helpers/asset_tag_helper.rb +40 -15
  12. data/lib/action_view/helpers/asset_url_helper.rb +6 -4
  13. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  14. data/lib/action_view/helpers/cache_helper.rb +10 -16
  15. data/lib/action_view/helpers/date_helper.rb +4 -4
  16. data/lib/action_view/helpers/form_helper.rb +59 -17
  17. data/lib/action_view/helpers/form_options_helper.rb +7 -16
  18. data/lib/action_view/helpers/form_tag_helper.rb +2 -1
  19. data/lib/action_view/helpers/javascript_helper.rb +3 -3
  20. data/lib/action_view/helpers/number_helper.rb +6 -6
  21. data/lib/action_view/helpers/rendering_helper.rb +11 -3
  22. data/lib/action_view/helpers/tag_helper.rb +92 -17
  23. data/lib/action_view/helpers/tags/base.rb +9 -5
  24. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  25. data/lib/action_view/helpers/tags/date_select.rb +2 -2
  26. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
  27. data/lib/action_view/helpers/tags/label.rb +4 -0
  28. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  29. data/lib/action_view/helpers/tags/select.rb +1 -1
  30. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  31. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  32. data/lib/action_view/helpers/text_helper.rb +1 -1
  33. data/lib/action_view/helpers/translation_helper.rb +94 -49
  34. data/lib/action_view/helpers/url_helper.rb +107 -13
  35. data/lib/action_view/layouts.rb +3 -2
  36. data/lib/action_view/log_subscriber.rb +26 -10
  37. data/lib/action_view/lookup_context.rb +3 -18
  38. data/lib/action_view/path_set.rb +0 -3
  39. data/lib/action_view/railtie.rb +35 -46
  40. data/lib/action_view/renderer/abstract_renderer.rb +93 -14
  41. data/lib/action_view/renderer/collection_renderer.rb +192 -0
  42. data/lib/action_view/renderer/object_renderer.rb +34 -0
  43. data/lib/action_view/renderer/partial_renderer.rb +20 -282
  44. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +25 -26
  45. data/lib/action_view/renderer/renderer.rb +44 -1
  46. data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
  47. data/lib/action_view/renderer/template_renderer.rb +15 -12
  48. data/lib/action_view/rendering.rb +3 -1
  49. data/lib/action_view/routing_url_for.rb +1 -1
  50. data/lib/action_view/template.rb +9 -49
  51. data/lib/action_view/template/handlers.rb +0 -26
  52. data/lib/action_view/template/handlers/erb.rb +10 -14
  53. data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
  54. data/lib/action_view/template/html.rb +1 -11
  55. data/lib/action_view/template/raw_file.rb +0 -3
  56. data/lib/action_view/template/renderable.rb +24 -0
  57. data/lib/action_view/template/resolver.rb +82 -40
  58. data/lib/action_view/template/text.rb +0 -3
  59. data/lib/action_view/test_case.rb +18 -25
  60. data/lib/action_view/testing/resolvers.rb +10 -31
  61. data/lib/action_view/unbound_template.rb +3 -3
  62. data/lib/action_view/view_paths.rb +34 -36
  63. metadata +17 -14
@@ -62,7 +62,50 @@ module ActionView
62
62
  end
63
63
 
64
64
  def render_partial_to_object(context, options, &block) #:nodoc:
65
- PartialRenderer.new(@lookup_context).render(context, options, block)
65
+ partial = options[:partial]
66
+ if String === partial
67
+ collection = collection_from_options(options)
68
+
69
+ if collection
70
+ # Collection + Partial
71
+ renderer = CollectionRenderer.new(@lookup_context, options)
72
+ renderer.render_collection_with_partial(collection, partial, context, block)
73
+ else
74
+ if options.key?(:object)
75
+ # Object + Partial
76
+ renderer = ObjectRenderer.new(@lookup_context, options)
77
+ renderer.render_object_with_partial(options[:object], partial, context, block)
78
+ else
79
+ # Partial
80
+ renderer = PartialRenderer.new(@lookup_context, options)
81
+ renderer.render(partial, context, block)
82
+ end
83
+ end
84
+ else
85
+ collection = collection_from_object(partial) || collection_from_options(options)
86
+
87
+ if collection
88
+ # Collection + Derived Partial
89
+ renderer = CollectionRenderer.new(@lookup_context, options)
90
+ renderer.render_collection_derive_partial(collection, context, block)
91
+ else
92
+ # Object + Derived Partial
93
+ renderer = ObjectRenderer.new(@lookup_context, options)
94
+ renderer.render_object_derive_partial(partial, context, block)
95
+ end
96
+ end
66
97
  end
98
+
99
+ private
100
+ def collection_from_options(options)
101
+ if options.key?(:collection)
102
+ collection = options[:collection]
103
+ collection || []
104
+ end
105
+ end
106
+
107
+ def collection_from_object(object)
108
+ object if object.respond_to?(:to_ary)
109
+ end
67
110
  end
68
111
  end
@@ -62,7 +62,11 @@ module ActionView
62
62
  output = ActionView::StreamingBuffer.new(buffer)
63
63
  yielder = lambda { |*name| view._layout_for(*name) }
64
64
 
65
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
65
+ ActiveSupport::Notifications.instrument(
66
+ "render_template.action_view",
67
+ identifier: template.identifier,
68
+ layout: layout && layout.virtual_path
69
+ ) do
66
70
  outer_config = I18n.config
67
71
  fiber = Fiber.new do
68
72
  I18n.config = outer_config
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/try"
4
-
5
3
  module ActionView
6
4
  class TemplateRenderer < AbstractRenderer #:nodoc:
7
5
  def render(context, options)
@@ -28,8 +26,7 @@ module ActionView
28
26
  if File.exist?(options[:file])
29
27
  Template::RawFile.new(options[:file])
30
28
  else
31
- ActiveSupport::Deprecation.warn "render file: should be given the absolute path to a file"
32
- @lookup_context.with_fallbacks.find_template(options[:file], nil, false, keys, @details)
29
+ raise ArgumentError, "`render file:` should be given the absolute path to a file. '#{options[:file]}' was given instead"
33
30
  end
34
31
  elsif options.key?(:inline)
35
32
  handler = Template.handler_for_extension(options[:type] || "erb")
@@ -39,6 +36,8 @@ module ActionView
39
36
  @lookup_context.formats.first
40
37
  end
41
38
  Template::Inline.new(options[:inline], "inline template", handler, locals: keys, format: format)
39
+ elsif options.key?(:renderable)
40
+ Template::Renderable.new(options[:renderable])
42
41
  elsif options.key?(:template)
43
42
  if options[:template].respond_to?(:render)
44
43
  options[:template]
@@ -54,7 +53,11 @@ module ActionView
54
53
  # supplied as well.
55
54
  def render_template(view, template, layout_name, locals)
56
55
  render_with_layout(view, template, layout_name, locals) do |layout|
57
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
56
+ ActiveSupport::Notifications.instrument(
57
+ "render_template.action_view",
58
+ identifier: template.identifier,
59
+ layout: layout && layout.virtual_path
60
+ ) do
58
61
  template.render(view, locals) { |*name| view._layout_for(*name) }
59
62
  end
60
63
  end
@@ -62,15 +65,16 @@ module ActionView
62
65
 
63
66
  def render_with_layout(view, template, path, locals)
64
67
  layout = path && find_layout(path, locals.keys, [formats.first])
65
- content = yield(layout)
66
68
 
67
69
  body = if layout
68
- view.view_flow.set(:layout, content)
69
- layout.render(view, locals) { |*name| view._layout_for(*name) }
70
+ ActiveSupport::Notifications.instrument("render_layout.action_view", identifier: layout.identifier) do
71
+ view.view_flow.set(:layout, yield(layout))
72
+ layout.render(view, locals) { |*name| view._layout_for(*name) }
73
+ end
70
74
  else
71
- content
75
+ yield
72
76
  end
73
- build_rendered_template(body, template, layout)
77
+ build_rendered_template(body, template)
74
78
  end
75
79
 
76
80
  # This is the method which actually finds the layout using details in the lookup
@@ -88,8 +92,7 @@ module ActionView
88
92
  when String
89
93
  begin
90
94
  if layout.start_with?("/")
91
- ActiveSupport::Deprecation.warn "Rendering layouts from an absolute path is deprecated."
92
- @lookup_context.with_fallbacks.find_template(layout, nil, false, [], details)
95
+ raise ArgumentError, "Rendering layouts from an absolute path is not supported."
93
96
  else
94
97
  @lookup_context.find_template(layout, nil, false, [], details)
95
98
  end
@@ -33,7 +33,7 @@ module ActionView
33
33
  super
34
34
  end
35
35
 
36
- # Overwrite process to setup I18n proxy.
36
+ # Overwrite process to set up I18n proxy.
37
37
  def process(*) #:nodoc:
38
38
  old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context)
39
39
  super
@@ -144,6 +144,8 @@ module ActionView
144
144
  else
145
145
  if action.respond_to?(:permitted?) && action.permitted?
146
146
  options = action
147
+ elsif action.respond_to?(:render_in)
148
+ options[:renderable] = action
147
149
  else
148
150
  options[:partial] = action
149
151
  end
@@ -105,7 +105,7 @@ module ActionView
105
105
  end
106
106
  else
107
107
  method = _generate_paths_by_default ? :path : :url
108
- builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(method)
108
+ builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.public_send(method)
109
109
 
110
110
  case options
111
111
  when Symbol
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/try"
4
- require "active_support/core_ext/kernel/singleton_class"
5
- require "active_support/deprecation"
6
3
  require "thread"
7
4
  require "delegate"
8
5
 
@@ -11,14 +8,6 @@ module ActionView
11
8
  class Template
12
9
  extend ActiveSupport::Autoload
13
10
 
14
- def self.finalize_compiled_template_methods
15
- ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods is deprecated and has no effect"
16
- end
17
-
18
- def self.finalize_compiled_template_methods=(_)
19
- ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods= is deprecated and has no effect"
20
- end
21
-
22
11
  # === Encodings in ActionView::Template
23
12
  #
24
13
  # ActionView::Template is one of a few sources of potential
@@ -114,6 +103,7 @@ module ActionView
114
103
  eager_autoload do
115
104
  autoload :Error
116
105
  autoload :RawFile
106
+ autoload :Renderable
117
107
  autoload :Handlers
118
108
  autoload :HTML
119
109
  autoload :Inline
@@ -124,15 +114,10 @@ module ActionView
124
114
 
125
115
  extend Template::Handlers
126
116
 
127
- attr_reader :identifier, :handler, :original_encoding, :updated_at
117
+ attr_reader :identifier, :handler
128
118
  attr_reader :variable, :format, :variant, :locals, :virtual_path
129
119
 
130
- def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil, updated_at: nil)
131
- unless locals
132
- ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
133
- locals = []
134
- end
135
-
120
+ def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
136
121
  @source = source
137
122
  @identifier = identifier
138
123
  @handler = handler
@@ -141,32 +126,16 @@ module ActionView
141
126
  @virtual_path = virtual_path
142
127
 
143
128
  @variable = if @virtual_path
144
- base = @virtual_path[-1] == "/" ? "" : ::File.basename(@virtual_path)
129
+ base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
145
130
  base =~ /\A_?(.*?)(?:\.\w+)*\z/
146
131
  $1.to_sym
147
132
  end
148
133
 
149
- if updated_at
150
- ActiveSupport::Deprecation.warn "ActionView::Template#updated_at is deprecated"
151
- @updated_at = updated_at
152
- else
153
- @updated_at = Time.now
154
- end
155
134
  @format = format
156
135
  @variant = variant
157
136
  @compile_mutex = Mutex.new
158
137
  end
159
138
 
160
- deprecate :original_encoding
161
- deprecate :updated_at
162
- deprecate def virtual_path=(_); end
163
- deprecate def locals=(_); end
164
- deprecate def formats=(_); end
165
- deprecate def formats; Array(format); end
166
- deprecate def variants=(_); end
167
- deprecate def variants; [variant]; end
168
- deprecate def refresh(_); self; end
169
-
170
139
  # Returns whether the underlying handler supports streaming. If so,
171
140
  # a streaming buffer *may* be passed when it starts rendering.
172
141
  def supports_streaming?
@@ -179,10 +148,10 @@ module ActionView
179
148
  # This method is instrumented as "!render_template.action_view". Notice that
180
149
  # we use a bang in this instrumentation because you don't want to
181
150
  # consume this in production. This is only slow if it's being listened to.
182
- def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
151
+ def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
183
152
  instrument_render_template do
184
153
  compile!(view)
185
- view._run(method_name, self, locals, buffer, &block)
154
+ view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
186
155
  end
187
156
  rescue => e
188
157
  handle_render_error(view, e)
@@ -193,7 +162,7 @@ module ActionView
193
162
  end
194
163
 
195
164
  def short_identifier
196
- @short_identifier ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier
165
+ @short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
197
166
  end
198
167
 
199
168
  def inspect
@@ -255,11 +224,11 @@ module ActionView
255
224
  # to ensure that references to the template object can be marshalled as well. This means forgoing
256
225
  # the marshalling of the compiler mutex and instantiating that again on unmarshalling.
257
226
  def marshal_dump # :nodoc:
258
- [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
227
+ [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
259
228
  end
260
229
 
261
230
  def marshal_load(array) # :nodoc:
262
- @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
231
+ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
263
232
  @compile_mutex = Mutex.new
264
233
  end
265
234
 
@@ -288,15 +257,6 @@ module ActionView
288
257
  end
289
258
  end
290
259
 
291
- class LegacyTemplate < DelegateClass(Template) # :nodoc:
292
- attr_reader :source
293
-
294
- def initialize(template, source)
295
- super(template)
296
- @source = source
297
- end
298
- end
299
-
300
260
  # Among other things, this method is responsible for properly setting
301
261
  # the encoding of the compiled template.
302
262
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/deprecation"
4
-
5
3
  module ActionView #:nodoc:
6
4
  # = Action View Template Handlers
7
5
  class Template #:nodoc:
@@ -26,35 +24,11 @@ module ActionView #:nodoc:
26
24
  @@template_extensions ||= @@template_handlers.keys
27
25
  end
28
26
 
29
- class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
30
- def call(view, source)
31
- __getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
32
- end
33
- end
34
-
35
27
  # Register an object that knows how to handle template files with the given
36
28
  # extensions. This can be used to implement new template types.
37
29
  # The handler must respond to +:call+, which will be passed the template
38
30
  # and should return the rendered template as a String.
39
31
  def register_template_handler(*extensions, handler)
40
- params = if handler.is_a?(Proc)
41
- handler.parameters
42
- else
43
- handler.method(:call).parameters
44
- end
45
-
46
- unless params.find_all { |type, _| type == :req || type == :opt }.length >= 2
47
- ActiveSupport::Deprecation.warn <<~eowarn
48
- Single arity template handlers are deprecated. Template handlers must
49
- now accept two parameters, the view object and the source for the view object.
50
- Change:
51
- >> #{handler}.call(#{params.map(&:last).join(", ")})
52
- To:
53
- >> #{handler}.call(#{params.map(&:last).join(", ")}, source)
54
- eowarn
55
- handler = LegacyHandlerWrapper.new(handler)
56
- end
57
-
58
32
  raise(ArgumentError, "Extension is required") if extensions.empty?
59
33
  extensions.each do |extension|
60
34
  @@template_handlers[extension.to_sym] = handler
@@ -16,16 +16,6 @@ module ActionView
16
16
  # Do not escape templates of these mime types.
17
17
  class_attribute :escape_ignore_list, default: ["text/plain"]
18
18
 
19
- [self, singleton_class].each do |base|
20
- base.alias_method :escape_whitelist, :escape_ignore_list
21
- base.alias_method :escape_whitelist=, :escape_ignore_list=
22
-
23
- base.deprecate(
24
- escape_whitelist: "use #escape_ignore_list instead",
25
- :escape_whitelist= => "use #escape_ignore_list= instead"
26
- )
27
- end
28
-
29
19
  ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
30
20
 
31
21
  def self.call(template, source)
@@ -45,7 +35,7 @@ module ActionView
45
35
  # wrong, we can still find an encoding tag
46
36
  # (<%# encoding %>) inside the String using a regular
47
37
  # expression
48
- template_source = source.dup.force_encoding(Encoding::ASCII_8BIT)
38
+ template_source = source.b
49
39
 
50
40
  erb = template_source.gsub(ENCODING_TAG, "")
51
41
  encoding = $2
@@ -55,11 +45,17 @@ module ActionView
55
45
  # Always make sure we return a String in the default_internal
56
46
  erb.encode!
57
47
 
58
- self.class.erb_implementation.new(
59
- erb,
48
+ options = {
60
49
  escape: (self.class.escape_ignore_list.include? template.type),
61
50
  trim: (self.class.erb_trim_mode == "-")
62
- ).src
51
+ }
52
+
53
+ if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
54
+ options[:preamble] = "@output_buffer.safe_append='<!-- BEGIN #{template.short_identifier} -->';"
55
+ options[:postamble] = "@output_buffer.safe_append='<!-- END #{template.short_identifier} -->';@output_buffer.to_s"
56
+ end
57
+
58
+ self.class.erb_implementation.new(erb, options).src
63
59
  end
64
60
 
65
61
  private
@@ -13,9 +13,11 @@ module ActionView
13
13
 
14
14
  # Dup properties so that we don't modify argument
15
15
  properties = Hash[properties]
16
- properties[:preamble] = ""
17
- properties[:postamble] = "@output_buffer.to_s"
18
- properties[:bufvar] = "@output_buffer"
16
+
17
+ properties[:bufvar] ||= "@output_buffer"
18
+ properties[:preamble] ||= ""
19
+ properties[:postamble] ||= "#{properties[:bufvar]}.to_s"
20
+
19
21
  properties[:escapefunc] = ""
20
22
 
21
23
  super
@@ -37,7 +39,7 @@ module ActionView
37
39
  if text == "\n"
38
40
  @newline_pending += 1
39
41
  else
40
- src << "@output_buffer.safe_append='"
42
+ src << bufvar << ".safe_append='"
41
43
  src << "\n" * @newline_pending if @newline_pending > 0
42
44
  src << text.gsub(/['\\]/, '\\\\\&')
43
45
  src << "'.freeze;"
@@ -52,9 +54,9 @@ module ActionView
52
54
  flush_newline_if_pending(src)
53
55
 
54
56
  if (indicator == "==") || @escape
55
- src << "@output_buffer.safe_expr_append="
57
+ src << bufvar << ".safe_expr_append="
56
58
  else
57
- src << "@output_buffer.append="
59
+ src << bufvar << ".append="
58
60
  end
59
61
 
60
62
  if BLOCK_EXPR.match?(code)
@@ -76,7 +78,7 @@ module ActionView
76
78
 
77
79
  def flush_newline_if_pending(src)
78
80
  if @newline_pending > 0
79
- src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
81
+ src << bufvar << ".safe_append='#{"\n" * @newline_pending}'.freeze;"
80
82
  @newline_pending = 0
81
83
  end
82
84
  end
@@ -1,19 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/deprecation"
4
-
5
3
  module ActionView #:nodoc:
6
4
  # = Action View HTML Template
7
5
  class Template #:nodoc:
8
6
  class HTML #:nodoc:
9
7
  attr_reader :type
10
8
 
11
- def initialize(string, type = nil)
12
- unless type
13
- ActiveSupport::Deprecation.warn "ActionView::Template::HTML#initialize requires a type parameter"
14
- type = :html
15
- end
16
-
9
+ def initialize(string, type)
17
10
  @string = string.to_s
18
11
  @type = type
19
12
  end
@@ -35,9 +28,6 @@ module ActionView #:nodoc:
35
28
  def format
36
29
  @type
37
30
  end
38
-
39
- def formats; Array(format); end
40
- deprecate :formats
41
31
  end
42
32
  end
43
33
  end