actionview 6.0.0.beta1 → 6.1.4

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +273 -119
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -3
  5. data/lib/action_view/base.rb +81 -15
  6. data/lib/action_view/cache_expiry.rb +52 -0
  7. data/lib/action_view/context.rb +0 -5
  8. data/lib/action_view/dependency_tracker.rb +10 -4
  9. data/lib/action_view/digestor.rb +11 -19
  10. data/lib/action_view/flows.rb +0 -1
  11. data/lib/action_view/gem_version.rb +3 -3
  12. data/lib/action_view/helpers/active_model_helper.rb +0 -1
  13. data/lib/action_view/helpers/asset_tag_helper.rb +62 -22
  14. data/lib/action_view/helpers/asset_url_helper.rb +6 -4
  15. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  16. data/lib/action_view/helpers/cache_helper.rb +16 -23
  17. data/lib/action_view/helpers/csp_helper.rb +4 -2
  18. data/lib/action_view/helpers/date_helper.rb +5 -6
  19. data/lib/action_view/helpers/form_helper.rb +70 -34
  20. data/lib/action_view/helpers/form_options_helper.rb +10 -18
  21. data/lib/action_view/helpers/form_tag_helper.rb +12 -9
  22. data/lib/action_view/helpers/javascript_helper.rb +7 -5
  23. data/lib/action_view/helpers/number_helper.rb +9 -8
  24. data/lib/action_view/helpers/output_safety_helper.rb +1 -1
  25. data/lib/action_view/helpers/rendering_helper.rb +17 -7
  26. data/lib/action_view/helpers/sanitize_helper.rb +10 -16
  27. data/lib/action_view/helpers/tag_helper.rb +94 -19
  28. data/lib/action_view/helpers/tags/base.rb +10 -7
  29. data/lib/action_view/helpers/tags/check_box.rb +0 -1
  30. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
  31. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
  32. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
  33. data/lib/action_view/helpers/tags/color_field.rb +0 -1
  34. data/lib/action_view/helpers/tags/date_field.rb +1 -2
  35. data/lib/action_view/helpers/tags/date_select.rb +2 -3
  36. data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
  37. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
  38. data/lib/action_view/helpers/tags/label.rb +4 -1
  39. data/lib/action_view/helpers/tags/month_field.rb +1 -2
  40. data/lib/action_view/helpers/tags/radio_button.rb +0 -1
  41. data/lib/action_view/helpers/tags/select.rb +1 -2
  42. data/lib/action_view/helpers/tags/text_field.rb +0 -1
  43. data/lib/action_view/helpers/tags/time_field.rb +1 -2
  44. data/lib/action_view/helpers/tags/week_field.rb +1 -2
  45. data/lib/action_view/helpers/text_helper.rb +2 -3
  46. data/lib/action_view/helpers/translation_helper.rb +98 -51
  47. data/lib/action_view/helpers/url_helper.rb +124 -16
  48. data/lib/action_view/layouts.rb +8 -10
  49. data/lib/action_view/log_subscriber.rb +26 -11
  50. data/lib/action_view/lookup_context.rb +59 -31
  51. data/lib/action_view/path_set.rb +3 -12
  52. data/lib/action_view/railtie.rb +39 -41
  53. data/lib/action_view/record_identifier.rb +0 -1
  54. data/lib/action_view/renderer/abstract_renderer.rb +142 -11
  55. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  56. data/lib/action_view/renderer/object_renderer.rb +34 -0
  57. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +35 -29
  58. data/lib/action_view/renderer/partial_renderer.rb +21 -273
  59. data/lib/action_view/renderer/renderer.rb +59 -4
  60. data/lib/action_view/renderer/streaming_template_renderer.rb +9 -7
  61. data/lib/action_view/renderer/template_renderer.rb +35 -27
  62. data/lib/action_view/rendering.rb +49 -29
  63. data/lib/action_view/routing_url_for.rb +1 -1
  64. data/lib/action_view/template/error.rb +30 -15
  65. data/lib/action_view/template/handlers/builder.rb +2 -2
  66. data/lib/action_view/template/handlers/erb/erubi.rb +15 -9
  67. data/lib/action_view/template/handlers/erb.rb +14 -19
  68. data/lib/action_view/template/handlers/html.rb +1 -1
  69. data/lib/action_view/template/handlers/raw.rb +2 -2
  70. data/lib/action_view/template/handlers.rb +1 -1
  71. data/lib/action_view/template/html.rb +5 -6
  72. data/lib/action_view/template/inline.rb +22 -0
  73. data/lib/action_view/template/raw_file.rb +25 -0
  74. data/lib/action_view/template/renderable.rb +24 -0
  75. data/lib/action_view/template/resolver.rb +141 -140
  76. data/lib/action_view/template/sources/file.rb +17 -0
  77. data/lib/action_view/template/sources.rb +13 -0
  78. data/lib/action_view/template/text.rb +2 -3
  79. data/lib/action_view/template.rb +49 -75
  80. data/lib/action_view/test_case.rb +20 -28
  81. data/lib/action_view/testing/resolvers.rb +18 -27
  82. data/lib/action_view/unbound_template.rb +31 -0
  83. data/lib/action_view/view_paths.rb +59 -38
  84. data/lib/action_view.rb +7 -2
  85. data/lib/assets/compiled/rails-ujs.js +25 -16
  86. metadata +30 -18
@@ -1,16 +1,13 @@
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
3
  require "thread"
4
+ require "delegate"
6
5
 
7
6
  module ActionView
8
7
  # = Action View Template
9
8
  class Template
10
9
  extend ActiveSupport::Autoload
11
10
 
12
- mattr_accessor :finalize_compiled_template_methods, default: true
13
-
14
11
  # === Encodings in ActionView::Template
15
12
  #
16
13
  # ActionView::Template is one of a few sources of potential
@@ -105,41 +102,37 @@ module ActionView
105
102
 
106
103
  eager_autoload do
107
104
  autoload :Error
105
+ autoload :RawFile
106
+ autoload :Renderable
108
107
  autoload :Handlers
109
108
  autoload :HTML
109
+ autoload :Inline
110
+ autoload :Sources
110
111
  autoload :Text
111
112
  autoload :Types
112
113
  end
113
114
 
114
115
  extend Template::Handlers
115
116
 
116
- attr_accessor :locals, :formats, :variants, :virtual_path
117
-
118
- attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
119
-
120
- # This finalizer is needed (and exactly with a proc inside another proc)
121
- # otherwise templates leak in development.
122
- Finalizer = proc do |method_name, mod| # :nodoc:
123
- proc do
124
- mod.module_eval do
125
- remove_possible_method method_name
126
- end
127
- end
128
- end
129
-
130
- def initialize(source, identifier, handler, details)
131
- format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
117
+ attr_reader :identifier, :handler
118
+ attr_reader :variable, :format, :variant, :locals, :virtual_path
132
119
 
120
+ def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
133
121
  @source = source
134
122
  @identifier = identifier
135
123
  @handler = handler
136
124
  @compiled = false
137
- @original_encoding = nil
138
- @locals = details[:locals] || []
139
- @virtual_path = details[:virtual_path]
140
- @updated_at = details[:updated_at] || Time.now
141
- @formats = Array(format).map { |f| f.respond_to?(:ref) ? f.ref : f }
142
- @variants = [details[:variant]]
125
+ @locals = locals
126
+ @virtual_path = virtual_path
127
+
128
+ @variable = if @virtual_path
129
+ base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
130
+ base =~ /\A_?(.*?)(?:\.\w+)*\z/
131
+ $1.to_sym
132
+ end
133
+
134
+ @format = format
135
+ @variant = variant
143
136
  @compile_mutex = Mutex.new
144
137
  end
145
138
 
@@ -155,40 +148,29 @@ module ActionView
155
148
  # This method is instrumented as "!render_template.action_view". Notice that
156
149
  # we use a bang in this instrumentation because you don't want to
157
150
  # consume this in production. This is only slow if it's being listened to.
158
- def render(view, locals, buffer = nil, &block)
151
+ def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
159
152
  instrument_render_template do
160
153
  compile!(view)
161
- view.send(method_name, locals, buffer, &block)
154
+ view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
162
155
  end
163
156
  rescue => e
164
157
  handle_render_error(view, e)
165
158
  end
166
159
 
167
160
  def type
168
- @type ||= Types[@formats.first] if @formats.first
161
+ @type ||= Types[format]
169
162
  end
170
163
 
171
- # Receives a view object and return a template similar to self by using @virtual_path.
172
- #
173
- # This method is useful if you have a template object but it does not contain its source
174
- # anymore since it was already compiled. In such cases, all you need to do is to call
175
- # refresh passing in the view object.
176
- #
177
- # Notice this method raises an error if the template to be refreshed does not have a
178
- # virtual path set (true just for inline templates).
179
- def refresh(view)
180
- raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
181
- lookup = view.lookup_context
182
- pieces = @virtual_path.split("/")
183
- name = pieces.pop
184
- partial = !!name.sub!(/^_/, "")
185
- lookup.disable_cache do
186
- lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
187
- end
164
+ def short_identifier
165
+ @short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
188
166
  end
189
167
 
190
168
  def inspect
191
- @inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier
169
+ "#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
170
+ end
171
+
172
+ def source
173
+ @source.to_s
192
174
  end
193
175
 
194
176
  # This method is responsible for properly setting the encoding of the
@@ -202,7 +184,9 @@ module ActionView
202
184
  # before passing the source on to the template engine, leaving a
203
185
  # blank line in its stead.
204
186
  def encode!
205
- return unless source.encoding == Encoding::BINARY
187
+ source = self.source
188
+
189
+ return source unless source.encoding == Encoding::BINARY
206
190
 
207
191
  # Look for # encoding: *. If we find one, we'll encode the
208
192
  # String in that encoding, otherwise, we'll use the
@@ -240,16 +224,15 @@ module ActionView
240
224
  # to ensure that references to the template object can be marshalled as well. This means forgoing
241
225
  # the marshalling of the compiler mutex and instantiating that again on unmarshalling.
242
226
  def marshal_dump # :nodoc:
243
- [ @source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants ]
227
+ [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
244
228
  end
245
229
 
246
230
  def marshal_load(array) # :nodoc:
247
- @source, @identifier, @handler, @compiled, @original_encoding, @locals, @virtual_path, @updated_at, @formats, @variants = *array
231
+ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
248
232
  @compile_mutex = Mutex.new
249
233
  end
250
234
 
251
235
  private
252
-
253
236
  # Compile a template. This method ensures a template is compiled
254
237
  # just once and removes the source after it is compiled.
255
238
  def compile!(view)
@@ -264,19 +247,12 @@ module ActionView
264
247
  # re-compilation
265
248
  return if @compiled
266
249
 
267
- if view.is_a?(ActionView::CompiledTemplates)
268
- mod = ActionView::CompiledTemplates
269
- else
270
- mod = view.singleton_class
271
- end
250
+ mod = view.compiled_method_container
272
251
 
273
252
  instrument("!compile_template") do
274
253
  compile(mod)
275
254
  end
276
255
 
277
- # Just discard the source if we have a virtual path. This
278
- # means we can get the template back.
279
- @source = nil if @virtual_path
280
256
  @compiled = true
281
257
  end
282
258
  end
@@ -294,16 +270,15 @@ module ActionView
294
270
  # In general, this means that templates will be UTF-8 inside of Rails,
295
271
  # regardless of the original source encoding.
296
272
  def compile(mod)
297
- encode!
298
- code = @handler.call(self)
273
+ source = encode!
274
+ code = @handler.call(self, source)
299
275
 
300
276
  # Make sure that the resulting String to be eval'd is in the
301
277
  # encoding of the code
278
+ original_source = source
302
279
  source = +<<-end_src
303
280
  def #{method_name}(local_assigns, output_buffer)
304
- _old_virtual_path, @virtual_path = @virtual_path, #{@virtual_path.inspect};_old_output_buffer = @output_buffer;#{locals_code};#{code}
305
- ensure
306
- @virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
281
+ @virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
307
282
  end
308
283
  end_src
309
284
 
@@ -318,12 +293,16 @@ module ActionView
318
293
  # handler is valid in the default_internal. This is for handlers
319
294
  # that handle encoding but screw up
320
295
  unless source.valid_encoding?
321
- raise WrongEncodingError.new(@source, Encoding.default_internal)
296
+ raise WrongEncodingError.new(source, Encoding.default_internal)
322
297
  end
323
298
 
324
- mod.module_eval(source, identifier, 0)
325
- if finalize_compiled_template_methods
326
- ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])
299
+ begin
300
+ mod.module_eval(source, identifier, 0)
301
+ rescue SyntaxError
302
+ # Account for when code in the template is not syntactically valid; e.g. if we're using
303
+ # ERB and the user writes <%= foo( %>, attempting to call a helper `foo` and interpolate
304
+ # the result into the template, but missing an end parenthesis.
305
+ raise SyntaxErrorInTemplate.new(self, original_source)
327
306
  end
328
307
  end
329
308
 
@@ -332,12 +311,7 @@ module ActionView
332
311
  e.sub_template_of(self)
333
312
  raise e
334
313
  else
335
- template = self
336
- unless template.source
337
- template = refresh(view)
338
- template.encode!
339
- end
340
- raise Template::Error.new(template)
314
+ raise Template::Error.new(self)
341
315
  end
342
316
  end
343
317
 
@@ -360,7 +334,7 @@ module ActionView
360
334
  end
361
335
 
362
336
  def identifier_method_name
363
- inspect.tr("^a-z_", "_")
337
+ short_identifier.tr("^a-z_", "_")
364
338
  end
365
339
 
366
340
  def instrument(action, &block) # :doc:
@@ -16,11 +16,12 @@ module ActionView
16
16
  attr_accessor :request, :response, :params
17
17
 
18
18
  class << self
19
- attr_writer :controller_path
19
+ # Overrides AbstractController::Base#controller_path
20
+ attr_accessor :controller_path
20
21
  end
21
22
 
22
23
  def controller_path=(path)
23
- self.class.controller_path = (path)
24
+ self.class.controller_path = path
24
25
  end
25
26
 
26
27
  def initialize
@@ -73,10 +74,11 @@ module ActionView
73
74
  def helper_method(*methods)
74
75
  # Almost a duplicate from ActionController::Helpers
75
76
  methods.flatten.each do |method|
76
- _helpers.module_eval <<-end_eval, __FILE__, __LINE__ + 1
77
+ _helpers_for_modification.module_eval <<-end_eval, __FILE__, __LINE__ + 1
77
78
  def #{method}(*args, &block) # def current_user(*args, &block)
78
- _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)
79
80
  end # end
81
+ ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
80
82
  end_eval
81
83
  end
82
84
  end
@@ -93,7 +95,6 @@ module ActionView
93
95
  end
94
96
 
95
97
  private
96
-
97
98
  def include_helper_modules!
98
99
  helper(helper_class) if helper_class
99
100
  include _helpers
@@ -101,7 +102,8 @@ module ActionView
101
102
  end
102
103
 
103
104
  def setup_with_controller
104
- @controller = ActionView::TestCase::TestController.new
105
+ controller_class = Class.new(ActionView::TestCase::TestController)
106
+ @controller = controller_class.new
105
107
  @request = @controller.request
106
108
  @view_flow = ActionView::OutputFlow.new
107
109
  # empty string ensures buffer has UTF-8 encoding as
@@ -109,8 +111,8 @@ module ActionView
109
111
  @output_buffer = ActiveSupport::SafeBuffer.new ""
110
112
  @rendered = +""
111
113
 
112
- make_test_case_available_to_view!
113
- say_no_to_protect_against_forgery!
114
+ test_case_instance = self
115
+ controller_class.define_method(:_test_case) { test_case_instance }
114
116
  end
115
117
 
116
118
  def config
@@ -160,34 +162,24 @@ module ActionView
160
162
  included do
161
163
  setup :setup_with_controller
162
164
  ActiveSupport.run_load_hooks(:action_view_test_case, self)
163
- end
164
-
165
- private
166
-
167
- # Need to experiment if this priority is the best one: rendered => output_buffer
168
- def document_root_element
169
- Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
170
- end
171
165
 
172
- def say_no_to_protect_against_forgery!
173
- _helpers.module_eval do
174
- silence_redefinition_of_method :protect_against_forgery?
166
+ helper do
175
167
  def protect_against_forgery?
176
168
  false
177
169
  end
178
- end
179
- end
180
170
 
181
- def make_test_case_available_to_view!
182
- test_case_instance = self
183
- _helpers.module_eval do
184
- unless private_method_defined?(:_test_case)
185
- define_method(:_test_case) { test_case_instance }
186
- private :_test_case
171
+ def _test_case
172
+ controller._test_case
187
173
  end
188
174
  end
189
175
  end
190
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
+
191
183
  module Locals
192
184
  attr_accessor :rendered_views
193
185
 
@@ -284,7 +276,7 @@ module ActionView
284
276
 
285
277
  def respond_to_missing?(name, include_private = false)
286
278
  begin
287
- routes = @controller.respond_to?(:_routes) && @controller._routes
279
+ routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes
288
280
  rescue
289
281
  # Don't call routes, if there is an error on _routes call
290
282
  end
@@ -7,12 +7,15 @@ module ActionView #:nodoc:
7
7
  # file system. This is used internally by Rails' own test suite, and is
8
8
  # useful for testing extensions that have no way of knowing what the file
9
9
  # system will look like at runtime.
10
- class FixtureResolver < PathResolver
11
- attr_reader :hash
12
-
13
- def initialize(hash = {}, pattern = nil)
14
- super(pattern)
10
+ class FixtureResolver < OptimizedFileSystemResolver
11
+ def initialize(hash = {})
12
+ super("")
15
13
  @hash = hash
14
+ @path = ""
15
+ end
16
+
17
+ def data
18
+ @hash
16
19
  end
17
20
 
18
21
  def to_s
@@ -20,35 +23,23 @@ module ActionView #:nodoc:
20
23
  end
21
24
 
22
25
  private
23
-
24
- def query(path, exts, _, _)
25
- query = +""
26
- EXTENSIONS.each_key do |ext|
27
- query << "(" << exts[ext].map { |e| e && Regexp.escape(".#{e}") }.join("|") << "|)"
28
- end
29
- query = /^(#{Regexp.escape(path)})#{query}$/
30
-
31
- templates = []
32
- @hash.each do |_path, array|
33
- source, updated_at = array
34
- next unless query.match?(_path)
35
- handler, format, variant = extract_handler_and_format_and_variant(_path)
36
- templates << Template.new(source, _path, handler,
37
- virtual_path: path.virtual,
38
- format: format,
39
- variant: variant,
40
- updated_at: updated_at
41
- )
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}"
42
31
  end
32
+ end
43
33
 
44
- templates.sort_by { |t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
34
+ def source_for_template(template)
35
+ @hash[template[1..template.size]]
45
36
  end
46
37
  end
47
38
 
48
39
  class NullResolver < PathResolver
49
- def query(path, exts, _, _)
40
+ def query(path, exts, _, locals, cache:)
50
41
  handler, format, variant = extract_handler_and_format_and_variant(path)
51
- [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)]
52
43
  end
53
44
  end
54
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
@@ -5,13 +5,21 @@ module ActionView
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- class_attribute :_view_paths, default: ActionView::PathSet.new.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
24
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
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
data/lib/action_view.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2019 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2020 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -35,7 +35,6 @@ module ActionView
35
35
  eager_autoload do
36
36
  autoload :Base
37
37
  autoload :Context
38
- autoload :CompiledTemplates, "action_view/context"
39
38
  autoload :Digestor
40
39
  autoload :Helpers
41
40
  autoload :LookupContext
@@ -45,12 +44,15 @@ module ActionView
45
44
  autoload :Rendering
46
45
  autoload :RoutingUrlFor
47
46
  autoload :Template
47
+ autoload :UnboundTemplate
48
48
  autoload :ViewPaths
49
49
 
50
50
  autoload_under "renderer" do
51
51
  autoload :Renderer
52
52
  autoload :AbstractRenderer
53
53
  autoload :PartialRenderer
54
+ autoload :CollectionRenderer
55
+ autoload :ObjectRenderer
54
56
  autoload :TemplateRenderer
55
57
  autoload :StreamingTemplateRenderer
56
58
  end
@@ -58,6 +60,7 @@ module ActionView
58
60
  autoload_at "action_view/template/resolver" do
59
61
  autoload :Resolver
60
62
  autoload :PathResolver
63
+ autoload :FileSystemResolver
61
64
  autoload :OptimizedFileSystemResolver
62
65
  autoload :FallbackFileSystemResolver
63
66
  end
@@ -77,10 +80,12 @@ module ActionView
77
80
  autoload :ActionViewError
78
81
  autoload :EncodingError
79
82
  autoload :TemplateError
83
+ autoload :SyntaxErrorInTemplate
80
84
  autoload :WrongEncodingError
81
85
  end
82
86
  end
83
87
 
88
+ autoload :CacheExpiry
84
89
  autoload :TestCase
85
90
 
86
91
  def self.eager_load!