actionpack 3.1.12 → 3.2.0.rc1

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

Potentially problematic release.


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

Files changed (128) hide show
  1. data/CHANGELOG.md +5503 -108
  2. data/README.rdoc +3 -3
  3. data/lib/abstract_controller/asset_paths.rb +1 -1
  4. data/lib/abstract_controller/base.rb +1 -1
  5. data/lib/abstract_controller/callbacks.rb +102 -18
  6. data/lib/abstract_controller/helpers.rb +1 -1
  7. data/lib/abstract_controller/layouts.rb +116 -50
  8. data/lib/abstract_controller/logger.rb +1 -1
  9. data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
  10. data/lib/abstract_controller/rendering.rb +1 -6
  11. data/lib/abstract_controller/view_paths.rb +6 -5
  12. data/lib/action_controller.rb +0 -15
  13. data/lib/action_controller/caching.rb +0 -1
  14. data/lib/action_controller/caching/actions.rb +5 -6
  15. data/lib/action_controller/caching/fragments.rb +18 -18
  16. data/lib/action_controller/caching/pages.rb +7 -6
  17. data/lib/action_controller/caching/sweeping.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +8 -4
  19. data/lib/action_controller/metal.rb +7 -1
  20. data/lib/action_controller/metal/conditional_get.rb +49 -4
  21. data/lib/action_controller/metal/data_streaming.rb +17 -5
  22. data/lib/action_controller/metal/force_ssl.rb +8 -5
  23. data/lib/action_controller/metal/helpers.rb +7 -4
  24. data/lib/action_controller/metal/http_authentication.rb +9 -12
  25. data/lib/action_controller/metal/instrumentation.rb +9 -4
  26. data/lib/action_controller/metal/mime_responds.rb +4 -4
  27. data/lib/action_controller/metal/params_wrapper.rb +12 -8
  28. data/lib/action_controller/metal/redirecting.rb +7 -6
  29. data/lib/action_controller/metal/renderers.rb +9 -11
  30. data/lib/action_controller/metal/request_forgery_protection.rb +2 -1
  31. data/lib/action_controller/metal/rescue.rb +13 -0
  32. data/lib/action_controller/metal/responder.rb +11 -23
  33. data/lib/action_controller/metal/streaming.rb +0 -25
  34. data/lib/action_controller/railtie.rb +1 -0
  35. data/lib/action_controller/railties/paths.rb +4 -3
  36. data/lib/action_controller/record_identifier.rb +4 -4
  37. data/lib/action_controller/test_case.rb +60 -56
  38. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +6 -6
  39. data/lib/action_dispatch.rb +5 -1
  40. data/lib/action_dispatch/http/cache.rb +27 -15
  41. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  42. data/lib/action_dispatch/http/headers.rb +3 -5
  43. data/lib/action_dispatch/http/mime_negotiation.rb +2 -1
  44. data/lib/action_dispatch/http/mime_type.rb +7 -3
  45. data/lib/action_dispatch/http/mime_types.rb +12 -0
  46. data/lib/action_dispatch/http/parameter_filter.rb +3 -1
  47. data/lib/action_dispatch/http/parameters.rb +0 -4
  48. data/lib/action_dispatch/http/request.rb +18 -68
  49. data/lib/action_dispatch/http/response.rb +11 -32
  50. data/lib/action_dispatch/http/upload.rb +3 -14
  51. data/lib/action_dispatch/http/url.rb +1 -1
  52. data/lib/action_dispatch/middleware/callbacks.rb +1 -2
  53. data/lib/action_dispatch/middleware/cookies.rb +20 -16
  54. data/lib/action_dispatch/middleware/debug_exceptions.rb +82 -0
  55. data/lib/action_dispatch/middleware/exception_wrapper.rb +78 -0
  56. data/lib/action_dispatch/middleware/flash.rb +6 -9
  57. data/lib/action_dispatch/middleware/params_parser.rb +6 -11
  58. data/lib/action_dispatch/middleware/public_exceptions.rb +30 -0
  59. data/lib/action_dispatch/middleware/reloader.rb +38 -14
  60. data/lib/action_dispatch/middleware/remote_ip.rb +66 -36
  61. data/lib/action_dispatch/middleware/request_id.rb +39 -0
  62. data/lib/action_dispatch/middleware/session/abstract_store.rb +4 -16
  63. data/lib/action_dispatch/middleware/session/cache_store.rb +50 -0
  64. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
  65. data/lib/action_dispatch/middleware/show_exceptions.rb +58 -142
  66. data/lib/action_dispatch/middleware/static.rb +2 -10
  67. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  68. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +13 -8
  69. data/lib/action_dispatch/railtie.rb +15 -1
  70. data/lib/action_dispatch/routing.rb +1 -2
  71. data/lib/action_dispatch/routing/mapper.rb +108 -107
  72. data/lib/action_dispatch/routing/redirection.rb +63 -69
  73. data/lib/action_dispatch/routing/route_set.rb +75 -43
  74. data/lib/action_dispatch/routing/routes_proxy.rb +0 -4
  75. data/lib/action_dispatch/routing/url_for.rb +3 -3
  76. data/lib/action_dispatch/testing/assertions/response.rb +5 -7
  77. data/lib/action_dispatch/testing/assertions/routing.rb +10 -9
  78. data/lib/action_dispatch/testing/integration.rb +8 -25
  79. data/lib/action_dispatch/testing/test_process.rb +3 -2
  80. data/lib/action_dispatch/testing/test_request.rb +4 -23
  81. data/lib/action_pack/version.rb +3 -3
  82. data/lib/action_view.rb +1 -5
  83. data/lib/action_view/asset_paths.rb +7 -8
  84. data/lib/action_view/base.rb +7 -5
  85. data/lib/action_view/helpers/asset_paths.rb +1 -1
  86. data/lib/action_view/helpers/asset_tag_helper.rb +4 -8
  87. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +3 -0
  88. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  89. data/lib/action_view/helpers/capture_helper.rb +3 -3
  90. data/lib/action_view/helpers/controller_helper.rb +1 -1
  91. data/lib/action_view/helpers/date_helper.rb +26 -18
  92. data/lib/action_view/helpers/debug_helper.rb +1 -1
  93. data/lib/action_view/helpers/form_helper.rb +71 -13
  94. data/lib/action_view/helpers/form_options_helper.rb +65 -34
  95. data/lib/action_view/helpers/form_tag_helper.rb +24 -18
  96. data/lib/action_view/helpers/javascript_helper.rb +12 -3
  97. data/lib/action_view/helpers/number_helper.rb +3 -2
  98. data/lib/action_view/helpers/record_tag_helper.rb +51 -5
  99. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  100. data/lib/action_view/helpers/sanitize_helper.rb +6 -7
  101. data/lib/action_view/helpers/tag_helper.rb +1 -1
  102. data/lib/action_view/helpers/text_helper.rb +5 -4
  103. data/lib/action_view/helpers/url_helper.rb +19 -11
  104. data/lib/action_view/locale/en.yml +6 -0
  105. data/lib/action_view/log_subscriber.rb +1 -1
  106. data/lib/action_view/lookup_context.rb +123 -125
  107. data/lib/action_view/path_set.rb +60 -13
  108. data/lib/action_view/renderer/abstract_renderer.rb +16 -11
  109. data/lib/action_view/renderer/partial_renderer.rb +59 -40
  110. data/lib/action_view/renderer/template_renderer.rb +29 -17
  111. data/lib/action_view/template.rb +0 -1
  112. data/lib/action_view/template/error.rb +6 -5
  113. data/lib/action_view/template/handlers.rb +0 -6
  114. data/lib/action_view/template/handlers/builder.rb +10 -1
  115. data/lib/action_view/template/handlers/erb.rb +2 -2
  116. data/lib/action_view/template/resolver.rb +20 -31
  117. data/lib/action_view/test_case.rb +7 -10
  118. data/lib/sprockets/assets.rake +1 -1
  119. data/lib/sprockets/bootstrap.rb +3 -31
  120. data/lib/sprockets/compressors.rb +69 -7
  121. data/lib/sprockets/helpers/rails_helper.rb +6 -11
  122. data/lib/sprockets/railtie.rb +1 -0
  123. data/lib/sprockets/static_compiler.rb +0 -3
  124. metadata +57 -86
  125. checksums.yaml +0 -7
  126. data/lib/action_dispatch/middleware/closed_error.rb +0 -7
  127. data/lib/action_dispatch/routing/route.rb +0 -67
  128. data/lib/action_view/template/handler.rb +0 -49
@@ -1,11 +1,55 @@
1
1
  module ActionView #:nodoc:
2
2
  # = Action View PathSet
3
- class PathSet < Array #:nodoc:
4
- %w(initialize << concat insert push unshift).each do |method|
3
+ class PathSet #:nodoc:
4
+ include Enumerable
5
+
6
+ attr_reader :paths
7
+
8
+ def initialize(paths = [])
9
+ @paths = typecast paths
10
+ end
11
+
12
+ def initialize_copy(other)
13
+ @paths = other.paths.dup
14
+ self
15
+ end
16
+
17
+ def [](i)
18
+ paths[i]
19
+ end
20
+
21
+ def to_ary
22
+ paths.dup
23
+ end
24
+
25
+ def include?(item)
26
+ paths.include? item
27
+ end
28
+
29
+ def pop
30
+ paths.pop
31
+ end
32
+
33
+ def size
34
+ paths.size
35
+ end
36
+
37
+ def each(&block)
38
+ paths.each(&block)
39
+ end
40
+
41
+ def compact
42
+ PathSet.new paths.compact
43
+ end
44
+
45
+ def +(array)
46
+ PathSet.new(paths + array)
47
+ end
48
+
49
+ %w(<< concat push insert unshift).each do |method|
5
50
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
6
51
  def #{method}(*args)
7
- super
8
- typecast!
52
+ paths.#{method}(*typecast(args))
9
53
  end
10
54
  METHOD
11
55
  end
@@ -17,7 +61,7 @@ module ActionView #:nodoc:
17
61
  def find_all(path, prefixes = [], *args)
18
62
  prefixes = [prefixes] if String === prefixes
19
63
  prefixes.each do |prefix|
20
- each do |resolver|
64
+ paths.each do |resolver|
21
65
  templates = resolver.find_all(path, prefix, *args)
22
66
  return templates unless templates.empty?
23
67
  end
@@ -25,17 +69,20 @@ module ActionView #:nodoc:
25
69
  []
26
70
  end
27
71
 
28
- def exists?(*args)
29
- find_all(*args).any?
72
+ def exists?(path, prefixes, *args)
73
+ find_all(path, prefixes, *args).any?
30
74
  end
31
75
 
32
- protected
76
+ private
33
77
 
34
- def typecast!
35
- each_with_index do |path, i|
36
- path = path.to_s if path.is_a?(Pathname)
37
- next unless path.is_a?(String)
38
- self[i] = OptimizedFileSystemResolver.new(path)
78
+ def typecast(paths)
79
+ paths.map do |path|
80
+ case path
81
+ when Pathname, String
82
+ OptimizedFileSystemResolver.new path.to_s
83
+ else
84
+ path
85
+ end
39
86
  end
40
87
  end
41
88
  end
@@ -11,15 +11,22 @@ module ActionView
11
11
  raise NotImplementedError
12
12
  end
13
13
 
14
- # Checks if the given path contains a format and if so, change
15
- # the lookup context to take this new format into account.
16
- def wrap_formats(value)
17
- return yield unless value.is_a?(String)
18
-
19
- if value.sub!(formats_regexp, "")
20
- update_details(:formats => [$1.to_sym]){ yield }
21
- else
22
- yield
14
+ protected
15
+
16
+ def extract_details(options)
17
+ details = {}
18
+ @lookup_context.registered_details.each do |key|
19
+ next unless value = options[key]
20
+ details[key] = Array.wrap(value)
21
+ end
22
+ details
23
+ end
24
+
25
+ def extract_format(value, details)
26
+ if value.is_a?(String) && value.sub!(formats_regexp, "")
27
+ ActiveSupport::Deprecation.warn "Passing the format in the template name is deprecated. " \
28
+ "Please pass render with :formats => [:#{$1}] instead.", caller
29
+ details[:formats] ||= [$1.to_sym]
23
30
  end
24
31
  end
25
32
 
@@ -27,8 +34,6 @@ module ActionView
27
34
  @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/
28
35
  end
29
36
 
30
- protected
31
-
32
37
  def instrument(name, options={})
33
38
  ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield }
34
39
  end
@@ -27,7 +27,7 @@ module ActionView
27
27
  #
28
28
  # == The :as and :object options
29
29
  #
30
- # By default <tt>ActionView::Partials::PartialRenderer</tt> doesn't have any local variables.
30
+ # By default <tt>ActionView::PartialRenderer</tt> doesn't have any local variables.
31
31
  # The <tt>:object</tt> option can be used to pass an object to the partial. For instance:
32
32
  #
33
33
  # <%= render :partial => "account", :object => @buyer %>
@@ -82,16 +82,18 @@ module ActionView
82
82
  #
83
83
  # This will render the partial "advertisement/_ad.html.erb" regardless of which controller this is being called from.
84
84
  #
85
- # == Rendering objects with the RecordIdentifier
85
+ # == Rendering objects that respond to `to_partial_path`
86
86
  #
87
- # Instead of explicitly naming the location of a partial, you can also let the RecordIdentifier do the work if
88
- # you're following its conventions for RecordIdentifier#partial_path. Examples:
87
+ # Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work
88
+ # and pick the proper path by checking `to_proper_path` method. If the object passed to render is a collection,
89
+ # all objects must return the same path.
89
90
  #
90
- # # @account is an Account instance, so it uses the RecordIdentifier to replace
91
+ # # @account.to_partial_path returns 'accounts/account', so it can be used to replace:
91
92
  # # <%= render :partial => "accounts/account", :locals => { :account => @account} %>
92
93
  # <%= render :partial => @account %>
93
94
  #
94
- # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace
95
+ # # @posts is an array of Post instances, so every post record returns 'posts/post' on `to_partial_path`,
96
+ # # that's why we can replace:
95
97
  # # <%= render :partial => "posts/post", :collection => @posts %>
96
98
  # <%= render :partial => @posts %>
97
99
  #
@@ -106,13 +108,14 @@ module ActionView
106
108
  # # Instead of <%= render :partial => "account", :locals => { :account => @buyer } %>
107
109
  # <%= render "account", :account => @buyer %>
108
110
  #
109
- # # @account is an Account instance, so it uses the RecordIdentifier to replace
110
- # # <%= render :partial => "accounts/account", :locals => { :account => @account } %>
111
- # <%= render(@account) %>
111
+ # # @account.to_partial_path returns 'accounts/account', so it can be used to replace:
112
+ # # <%= render :partial => "accounts/account", :locals => { :account => @account} %>
113
+ # <%= render @account %>
112
114
  #
113
- # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace
115
+ # # @posts is an array of Post instances, so every post record returns 'posts/post' on `to_partial_path`,
116
+ # # that's why we can replace:
114
117
  # # <%= render :partial => "posts/post", :collection => @posts %>
115
- # <%= render(@posts) %>
118
+ # <%= render @posts %>
116
119
  #
117
120
  # == Rendering partials with layouts
118
121
  #
@@ -205,28 +208,26 @@ module ActionView
205
208
  # Deadline: <%= user.deadline %>
206
209
  # <%- end -%>
207
210
  # <% end %>
208
- class PartialRenderer < AbstractRenderer #:nodoc:
209
- PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} }
211
+ class PartialRenderer < AbstractRenderer
212
+ PARTIAL_NAMES = Hash.new { |h,k| h[k] = {} }
210
213
 
211
214
  def initialize(*)
212
215
  super
213
- @partial_names = PARTIAL_NAMES[@lookup_context.prefixes.first]
216
+ @context_prefix = @lookup_context.prefixes.first
217
+ @partial_names = PARTIAL_NAMES[@context_prefix]
214
218
  end
215
219
 
216
220
  def render(context, options, block)
217
221
  setup(context, options, block)
222
+ identifier = (@template = find_partial) ? @template.identifier : @path
218
223
 
219
- wrap_formats(@path) do
220
- identifier = ((@template = find_partial) ? @template.identifier : @path)
221
-
222
- if @collection
223
- instrument(:collection, :identifier => identifier || "collection", :count => @collection.size) do
224
- render_collection
225
- end
226
- else
227
- instrument(:partial, :identifier => identifier) do
228
- render_partial
229
- end
224
+ if @collection
225
+ instrument(:collection, :identifier => identifier || "collection", :count => @collection.size) do
226
+ render_collection
227
+ end
228
+ else
229
+ instrument(:partial, :identifier => identifier) do
230
+ render_partial
230
231
  end
231
232
  end
232
233
  end
@@ -270,6 +271,7 @@ module ActionView
270
271
  @options = options
271
272
  @locals = options[:locals] || {}
272
273
  @block = block
274
+ @details = extract_details(options)
273
275
 
274
276
  if String === partial
275
277
  @object = options[:object]
@@ -292,6 +294,13 @@ module ActionView
292
294
  paths.map! { |path| retrieve_variable(path).unshift(path) }
293
295
  end
294
296
 
297
+ if String === partial && @variable.to_s !~ /^[a-z_][a-zA-Z_0-9]*$/
298
+ raise ArgumentError.new("The partial name (#{partial}) is not a valid Ruby identifier; " +
299
+ "make sure your partial name starts with a letter or underscore, " +
300
+ "and is followed by any combinations of letters, numbers, or underscores.")
301
+ end
302
+
303
+ extract_format(@path, @details)
295
304
  self
296
305
  end
297
306
 
@@ -319,7 +328,7 @@ module ActionView
319
328
 
320
329
  def find_template(path=@path, locals=@locals.keys)
321
330
  prefixes = path.include?(?/) ? [] : @lookup_context.prefixes
322
- @lookup_context.find_template(path, prefixes, true, locals)
331
+ @lookup_context.find_template(path, prefixes, true, locals, @details)
323
332
  end
324
333
 
325
334
  def collection_with_template
@@ -355,27 +364,37 @@ module ActionView
355
364
  end
356
365
 
357
366
  def partial_path(object = @object)
358
- @partial_names[object.class.name] ||= begin
359
- object = object.to_model if object.respond_to?(:to_model)
360
- object.class.model_name.partial_path.dup.tap do |partial|
361
- path = @lookup_context.prefixes.first
362
- merge_path_into_partial(path, partial)
367
+ object = object.to_model if object.respond_to?(:to_model)
368
+
369
+ path = if object.respond_to?(:to_partial_path)
370
+ object.to_partial_path
371
+ else
372
+ klass = object.class
373
+ if klass.respond_to?(:model_name)
374
+ ActiveSupport::Deprecation.warn "ActiveModel-compatible objects whose classes return a #model_name that responds to #partial_path are deprecated. Please respond to #to_partial_path directly instead."
375
+ klass.model_name.partial_path
376
+ else
377
+ raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object that returns a valid partial path.")
363
378
  end
364
379
  end
380
+
381
+ @partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
365
382
  end
366
383
 
367
- def merge_path_into_partial(path, partial)
368
- if path.include?(?/) && partial.include?(?/)
369
- overlap = []
370
- path_array = File.dirname(path).split('/')
371
- partial_array = partial.split('/')[0..-3] # skip model dir & partial
384
+ def merge_prefix_into_object_path(prefix, object_path)
385
+ if prefix.include?(?/) && object_path.include?(?/)
386
+ prefixes = []
387
+ prefix_array = File.dirname(prefix).split('/')
388
+ object_path_array = object_path.split('/')[0..-3] # skip model dir & partial
372
389
 
373
- path_array.each_with_index do |dir, index|
374
- overlap << dir if dir == partial_array[index]
390
+ prefix_array.each_with_index do |dir, index|
391
+ break if dir == object_path_array[index]
392
+ prefixes << dir
375
393
  end
376
394
 
377
- partial.gsub!(/^#{overlap.join('/')}\//,'')
378
- partial.insert(0, "#{File.dirname(path)}/")
395
+ (prefixes << object_path).join("/")
396
+ else
397
+ object_path
379
398
  end
380
399
  end
381
400
 
@@ -4,13 +4,12 @@ require 'active_support/core_ext/array/wrap'
4
4
  module ActionView
5
5
  class TemplateRenderer < AbstractRenderer #:nodoc:
6
6
  def render(context, options)
7
- @view = context
8
-
9
- wrap_formats(options[:template] || options[:file]) do
10
- template = determine_template(options)
11
- freeze_formats(template.formats, true)
12
- render_template(template, options[:layout], options[:locals])
13
- end
7
+ @view = context
8
+ @details = extract_details(options)
9
+ extract_format(options[:file] || options[:template], @details)
10
+ template = determine_template(options)
11
+ freeze_formats(template.formats, true)
12
+ render_template(template, options[:layout], options[:locals])
14
13
  end
15
14
 
16
15
  # Determine the template to be rendered using the given options.
@@ -20,13 +19,13 @@ module ActionView
20
19
  if options.key?(:text)
21
20
  Template::Text.new(options[:text], formats.try(:first))
22
21
  elsif options.key?(:file)
23
- with_fallbacks { find_template(options[:file], nil, false, keys) }
22
+ with_fallbacks { find_template(options[:file], nil, false, keys, @details) }
24
23
  elsif options.key?(:inline)
25
24
  handler = Template.handler_for_extension(options[:type] || "erb")
26
25
  Template.new(options[:inline], "inline template", handler, :locals => keys)
27
26
  elsif options.key?(:template)
28
27
  options[:template].respond_to?(:render) ?
29
- options[:template] : find_template(options[:template], options[:prefixes], false, keys)
28
+ options[:template] : find_template(options[:template], options[:prefixes], false, keys, @details)
30
29
  end
31
30
  end
32
31
 
@@ -59,15 +58,28 @@ module ActionView
59
58
  # context object. If no layout is found, it checks if at least a layout with
60
59
  # the given name exists across all details before raising the error.
61
60
  def find_layout(layout, keys)
62
- begin
63
- with_layout_format do
64
- layout =~ /^\// ?
65
- with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys)
66
- end
67
- rescue ActionView::MissingTemplate
68
- update_details(:formats => nil) do
69
- raise unless template_exists?(layout)
61
+ with_layout_format { resolve_layout(layout, keys) }
62
+ end
63
+
64
+ def resolve_layout(layout, keys)
65
+ case layout
66
+ when String
67
+ begin
68
+ if layout =~ /^\//
69
+ with_fallbacks { find_template(layout, nil, false, keys, @details) }
70
+ else
71
+ find_template(layout, nil, false, keys, @details)
72
+ end
73
+ rescue ActionView::MissingTemplate
74
+ all_details = @details.merge(:formats => @lookup_context.default_formats)
75
+ raise unless template_exists?(layout, nil, false, keys, all_details)
70
76
  end
77
+ when Proc
78
+ resolve_layout(layout.call, keys)
79
+ when FalseClass
80
+ nil
81
+ else
82
+ layout
71
83
  end
72
84
  end
73
85
  end
@@ -91,7 +91,6 @@ module ActionView
91
91
 
92
92
  eager_autoload do
93
93
  autoload :Error
94
- autoload :Handler
95
94
  autoload :Handlers
96
95
  autoload :Text
97
96
  end
@@ -57,6 +57,7 @@ module ActionView
57
57
  attr_reader :original_exception, :backtrace
58
58
 
59
59
  def initialize(template, assigns, original_exception)
60
+ super(original_exception.message)
60
61
  @template, @assigns, @original_exception = template, assigns.dup, original_exception
61
62
  @sub_templates = nil
62
63
  @backtrace = original_exception.backtrace
@@ -66,10 +67,6 @@ module ActionView
66
67
  @template.identifier
67
68
  end
68
69
 
69
- def message
70
- original_exception.message
71
- end
72
-
73
70
  def sub_template_message
74
71
  if @sub_templates
75
72
  "Trace of template inclusion: " +
@@ -92,10 +89,14 @@ module ActionView
92
89
  line_counter = start_on_line
93
90
  return unless source_code = source_code[start_on_line..end_on_line]
94
91
 
95
- source_code.sum do |line|
92
+ extract = source_code.sum do |line|
96
93
  line_counter += 1
97
94
  "#{indent}#{line_counter}: #{line}\n"
98
95
  end
96
+
97
+ extract.encode! if extract.respond_to?(:encode!)
98
+
99
+ extract
99
100
  end
100
101
 
101
102
  def sub_template_of(template_path)
@@ -41,12 +41,6 @@ module ActionView #:nodoc:
41
41
  @@default_template_handlers = klass
42
42
  end
43
43
 
44
- def handler_class_for_extension(extension)
45
- ActiveSupport::Deprecation.warn "handler_class_for_extension is deprecated. " <<
46
- "Please use handler_for_extension instead", caller
47
- handler_for_extension(extension)
48
- end
49
-
50
44
  def handler_for_extension(extension)
51
45
  registered_template_handler(extension) || @@default_template_handlers
52
46
  end
@@ -6,12 +6,21 @@ module ActionView
6
6
  self.default_format = Mime::XML
7
7
 
8
8
  def call(template)
9
- require 'builder'
9
+ require_engine
10
10
  "xml = ::Builder::XmlMarkup.new(:indent => 2);" +
11
11
  "self.output_buffer = xml.target!;" +
12
12
  template.source +
13
13
  ";xml.target!;"
14
14
  end
15
+
16
+ protected
17
+
18
+ def require_engine
19
+ @required ||= begin
20
+ require "builder"
21
+ true
22
+ end
23
+ end
15
24
  end
16
25
  end
17
26
  end