actionpack 4.2.10 → 7.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 (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,19 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
1
5
  module ActionController
6
+ # # Action Controller Implicit Render
7
+ #
8
+ # Handles implicit rendering for a controller action that does not explicitly
9
+ # respond with `render`, `respond_to`, `redirect`, or `head`.
10
+ #
11
+ # For API controllers, the implicit response is always `204 No Content`.
12
+ #
13
+ # For all other controllers, we use these heuristics to decide whether to render
14
+ # a template, raise an error for a missing template, or respond with `204 No
15
+ # Content`:
16
+ #
17
+ # First, if we DO find a template, it's rendered. Template lookup accounts for
18
+ # the action name, locales, format, variant, template handlers, and more (see
19
+ # `render` for details).
20
+ #
21
+ # Second, if we DON'T find a template but the controller action does have
22
+ # templates for other formats, variants, etc., then we trust that you meant to
23
+ # provide a template for this response, too, and we raise
24
+ # ActionController::UnknownFormat with an explanation.
25
+ #
26
+ # Third, if we DON'T find a template AND the request is a page load in a web
27
+ # browser (technically, a non-XHR GET request for an HTML response) where you
28
+ # reasonably expect to have rendered a template, then we raise
29
+ # ActionController::MissingExactTemplate with an explanation.
30
+ #
31
+ # Finally, if we DON'T find a template AND the request isn't a browser page
32
+ # load, then we implicitly respond with `204 No Content`.
2
33
  module ImplicitRender
3
- def send_action(method, *args)
4
- ret = super
5
- default_render unless performed?
6
- ret
7
- end
34
+ # :stopdoc:
35
+ include BasicImplicitRender
36
+
37
+ def default_render
38
+ if template_exists?(action_name.to_s, _prefixes, variants: request.variant)
39
+ render
40
+ elsif any_templates?(action_name.to_s, _prefixes)
41
+ message = "#{self.class.name}\##{action_name} is missing a template " \
42
+ "for this request format and variant.\n" \
43
+ "\nrequest.formats: #{request.formats.map(&:to_s).inspect}" \
44
+ "\nrequest.variant: #{request.variant.inspect}"
8
45
 
9
- def default_render(*args)
10
- render(*args)
46
+ raise ActionController::UnknownFormat, message
47
+ elsif interactive_browser_request?
48
+ message = "#{self.class.name}\##{action_name} is missing a template for request formats: #{request.formats.map(&:to_s).join(',')}"
49
+ raise ActionController::MissingExactTemplate.new(message, self.class, action_name)
50
+ else
51
+ logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger
52
+ super
53
+ end
11
54
  end
12
55
 
13
56
  def method_for_action(action_name)
14
57
  super || if template_exists?(action_name.to_s, _prefixes)
15
- "default_render"
16
- end
58
+ "default_render"
59
+ end
17
60
  end
61
+
62
+ private
63
+ def interactive_browser_request?
64
+ request.get? && request.format == Mime[:html] && !request.xhr?
65
+ end
18
66
  end
19
67
  end
@@ -1,44 +1,32 @@
1
- require 'benchmark'
2
- require 'abstract_controller/logger'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "benchmark"
6
+ require "abstract_controller/logger"
3
7
 
4
8
  module ActionController
5
- # Adds instrumentation to several ends in ActionController::Base. It also provides
6
- # some hooks related with process_action, this allows an ORM like Active Record
7
- # and/or DataMapper to plug in ActionController and show related information.
9
+ # # Action Controller Instrumentation
10
+ #
11
+ # Adds instrumentation to several ends in ActionController::Base. It also
12
+ # provides some hooks related with process_action. This allows an ORM like
13
+ # Active Record and/or DataMapper to plug in ActionController and show related
14
+ # information.
8
15
  #
9
16
  # Check ActiveRecord::Railties::ControllerRuntime for an example.
10
17
  module Instrumentation
11
18
  extend ActiveSupport::Concern
12
19
 
13
20
  include AbstractController::Logger
14
- include ActionController::RackDelegation
15
21
 
16
22
  attr_internal :view_runtime
17
23
 
18
- def process_action(*args)
19
- raw_payload = {
20
- :controller => self.class.name,
21
- :action => self.action_name,
22
- :params => request.filtered_parameters,
23
- :format => request.format.try(:ref),
24
- :method => request.request_method,
25
- :path => (request.fullpath rescue "unknown")
26
- }
27
-
28
- ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)
29
-
30
- ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
31
- begin
32
- result = super
33
- payload[:status] = response.status
34
- result
35
- ensure
36
- append_info_to_payload(payload)
37
- end
38
- end
24
+ def initialize(...) # :nodoc:
25
+ super
26
+ self.view_runtime = nil
39
27
  end
40
28
 
41
- def render(*args)
29
+ def render(*)
42
30
  render_output = nil
43
31
  self.view_runtime = cleanup_view_runtime do
44
32
  Benchmark.ms { render_output = super }
@@ -46,9 +34,9 @@ module ActionController
46
34
  render_output
47
35
  end
48
36
 
49
- def send_file(path, options={})
37
+ def send_file(path, options = {})
50
38
  ActiveSupport::Notifications.instrument("send_file.action_controller",
51
- options.merge(:path => path)) do
39
+ options.merge(path: path)) do
52
40
  super
53
41
  end
54
42
  end
@@ -59,8 +47,8 @@ module ActionController
59
47
  end
60
48
  end
61
49
 
62
- def redirect_to(*args)
63
- ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload|
50
+ def redirect_to(*)
51
+ ActiveSupport::Notifications.instrument("redirect_to.action_controller", request: request) do |payload|
64
52
  result = super
65
53
  payload[:status] = response.status
66
54
  payload[:location] = response.filtered_location
@@ -68,42 +56,66 @@ module ActionController
68
56
  end
69
57
  end
70
58
 
71
- private
59
+ private
60
+ def process_action(*)
61
+ ActiveSupport::ExecutionContext[:controller] = self
72
62
 
73
- # A hook invoked every time a before callback is halted.
74
- def halted_callback_hook(filter)
75
- ActiveSupport::Notifications.instrument("halted_callback.action_controller", :filter => filter)
76
- end
63
+ raw_payload = {
64
+ controller: self.class.name,
65
+ action: action_name,
66
+ request: request,
67
+ params: request.filtered_parameters,
68
+ headers: request.headers,
69
+ format: request.format.ref,
70
+ method: request.request_method,
71
+ path: request.filtered_path
72
+ }
77
73
 
78
- # A hook which allows you to clean up any time taken into account in
79
- # views wrongly, like database querying time.
80
- #
81
- # def cleanup_view_runtime
82
- # super - time_taken_in_something_expensive
83
- # end
84
- #
85
- # :api: plugin
86
- def cleanup_view_runtime #:nodoc:
87
- yield
88
- end
74
+ ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload)
89
75
 
90
- # Every time after an action is processed, this method is invoked
91
- # with the payload, so you can add more information.
92
- # :api: plugin
93
- def append_info_to_payload(payload) #:nodoc:
94
- payload[:view_runtime] = view_runtime
95
- end
76
+ ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
77
+ result = super
78
+ payload[:response] = response
79
+ payload[:status] = response.status
80
+ result
81
+ rescue => error
82
+ payload[:status] = ActionDispatch::ExceptionWrapper.status_code_for_exception(error.class.name)
83
+ raise
84
+ ensure
85
+ append_info_to_payload(payload)
86
+ end
87
+ end
96
88
 
97
- module ClassMethods
98
- # A hook which allows other frameworks to log what happened during
99
- # controller process action. This method should return an array
100
- # with the messages to be added.
101
- # :api: plugin
102
- def log_process_action(payload) #:nodoc:
103
- messages, view_runtime = [], payload[:view_runtime]
104
- messages << ("Views: %.1fms" % view_runtime.to_f) if view_runtime
105
- messages
89
+ # A hook invoked every time a before callback is halted.
90
+ def halted_callback_hook(filter, _)
91
+ ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
92
+ end
93
+
94
+ # A hook which allows you to clean up any time, wrongly taken into account in
95
+ # views, like database querying time.
96
+ #
97
+ # def cleanup_view_runtime
98
+ # super - time_taken_in_something_expensive
99
+ # end
100
+ def cleanup_view_runtime # :doc:
101
+ yield
102
+ end
103
+
104
+ # Every time after an action is processed, this method is invoked with the
105
+ # payload, so you can add more information.
106
+ def append_info_to_payload(payload) # :doc:
107
+ payload[:view_runtime] = view_runtime
108
+ end
109
+
110
+ module ClassMethods
111
+ # A hook which allows other frameworks to log what happened during controller
112
+ # process action. This method should return an array with the messages to be
113
+ # added.
114
+ def log_process_action(payload) # :nodoc:
115
+ messages, view_runtime = [], payload[:view_runtime]
116
+ messages << ("Views: %.1fms" % view_runtime.to_f) if view_runtime
117
+ messages
118
+ end
106
119
  end
107
- end
108
120
  end
109
121
  end