actionpack 3.2.22.5 → 4.0.0.beta1

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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +641 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller.rb +1 -8
  6. data/lib/abstract_controller/asset_paths.rb +2 -2
  7. data/lib/abstract_controller/base.rb +39 -37
  8. data/lib/abstract_controller/callbacks.rb +101 -82
  9. data/lib/abstract_controller/collector.rb +7 -3
  10. data/lib/abstract_controller/helpers.rb +23 -11
  11. data/lib/abstract_controller/layouts.rb +68 -73
  12. data/lib/abstract_controller/logger.rb +1 -2
  13. data/lib/abstract_controller/rendering.rb +22 -13
  14. data/lib/abstract_controller/translation.rb +16 -1
  15. data/lib/abstract_controller/url_for.rb +6 -6
  16. data/lib/abstract_controller/view_paths.rb +1 -1
  17. data/lib/action_controller.rb +15 -6
  18. data/lib/action_controller/base.rb +46 -22
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/caching/fragments.rb +23 -53
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  23. data/lib/action_controller/log_subscriber.rb +11 -8
  24. data/lib/action_controller/metal.rb +16 -30
  25. data/lib/action_controller/metal/conditional_get.rb +76 -32
  26. data/lib/action_controller/metal/data_streaming.rb +20 -26
  27. data/lib/action_controller/metal/exceptions.rb +19 -6
  28. data/lib/action_controller/metal/flash.rb +24 -9
  29. data/lib/action_controller/metal/force_ssl.rb +32 -9
  30. data/lib/action_controller/metal/head.rb +25 -4
  31. data/lib/action_controller/metal/helpers.rb +6 -9
  32. data/lib/action_controller/metal/hide_actions.rb +1 -2
  33. data/lib/action_controller/metal/http_authentication.rb +105 -87
  34. data/lib/action_controller/metal/implicit_render.rb +1 -1
  35. data/lib/action_controller/metal/instrumentation.rb +2 -1
  36. data/lib/action_controller/metal/live.rb +141 -0
  37. data/lib/action_controller/metal/mime_responds.rb +161 -47
  38. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  39. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  40. data/lib/action_controller/metal/redirecting.rb +15 -20
  41. data/lib/action_controller/metal/renderers.rb +11 -9
  42. data/lib/action_controller/metal/rendering.rb +8 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  44. data/lib/action_controller/metal/responder.rb +20 -19
  45. data/lib/action_controller/metal/streaming.rb +12 -18
  46. data/lib/action_controller/metal/strong_parameters.rb +516 -0
  47. data/lib/action_controller/metal/testing.rb +13 -18
  48. data/lib/action_controller/metal/url_for.rb +27 -25
  49. data/lib/action_controller/model_naming.rb +12 -0
  50. data/lib/action_controller/railtie.rb +33 -17
  51. data/lib/action_controller/railties/helpers.rb +22 -0
  52. data/lib/action_controller/record_identifier.rb +18 -72
  53. data/lib/action_controller/test_case.rb +215 -123
  54. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  55. data/lib/action_dispatch.rb +27 -19
  56. data/lib/action_dispatch/http/cache.rb +63 -11
  57. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  59. data/lib/action_dispatch/http/headers.rb +27 -19
  60. data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
  61. data/lib/action_dispatch/http/mime_type.rb +145 -113
  62. data/lib/action_dispatch/http/mime_types.rb +1 -1
  63. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  64. data/lib/action_dispatch/http/parameters.rb +12 -5
  65. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  66. data/lib/action_dispatch/http/request.rb +49 -18
  67. data/lib/action_dispatch/http/response.rb +129 -35
  68. data/lib/action_dispatch/http/upload.rb +60 -17
  69. data/lib/action_dispatch/http/url.rb +53 -31
  70. data/lib/action_dispatch/journey.rb +5 -0
  71. data/lib/action_dispatch/journey/backwards.rb +5 -0
  72. data/lib/action_dispatch/journey/formatter.rb +146 -0
  73. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  74. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  75. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  76. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  77. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  78. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  79. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  80. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  81. data/lib/action_dispatch/journey/parser.rb +206 -0
  82. data/lib/action_dispatch/journey/parser.y +47 -0
  83. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  84. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  85. data/lib/action_dispatch/journey/route.rb +116 -0
  86. data/lib/action_dispatch/journey/router.rb +164 -0
  87. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  88. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  89. data/lib/action_dispatch/journey/routes.rb +75 -0
  90. data/lib/action_dispatch/journey/scanner.rb +61 -0
  91. data/lib/action_dispatch/journey/visitors.rb +189 -0
  92. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  93. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  94. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  95. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  96. data/lib/action_dispatch/middleware/cookies.rb +168 -57
  97. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
  99. data/lib/action_dispatch/middleware/flash.rb +58 -58
  100. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
  102. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  103. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  104. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  110. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  111. data/lib/action_dispatch/middleware/stack.rb +6 -1
  112. data/lib/action_dispatch/middleware/static.rb +5 -24
  113. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  114. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  116. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  117. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  122. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  123. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  124. data/lib/action_dispatch/railtie.rb +16 -6
  125. data/lib/action_dispatch/request/session.rb +181 -0
  126. data/lib/action_dispatch/routing.rb +41 -40
  127. data/lib/action_dispatch/routing/inspector.rb +240 -0
  128. data/lib/action_dispatch/routing/mapper.rb +501 -273
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  130. data/lib/action_dispatch/routing/redirection.rb +46 -29
  131. data/lib/action_dispatch/routing/route_set.rb +203 -164
  132. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  133. data/lib/action_dispatch/routing/url_for.rb +48 -33
  134. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  135. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  136. data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
  137. data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
  138. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  139. data/lib/action_dispatch/testing/integration.rb +41 -22
  140. data/lib/action_dispatch/testing/test_process.rb +9 -6
  141. data/lib/action_dispatch/testing/test_request.rb +7 -3
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_pack/version.rb +4 -4
  144. data/lib/action_view.rb +17 -8
  145. data/lib/action_view/base.rb +15 -34
  146. data/lib/action_view/buffers.rb +1 -1
  147. data/lib/action_view/context.rb +4 -4
  148. data/lib/action_view/dependency_tracker.rb +91 -0
  149. data/lib/action_view/digestor.rb +85 -0
  150. data/lib/action_view/flows.rb +1 -4
  151. data/lib/action_view/helpers.rb +2 -4
  152. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  153. data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
  154. data/lib/action_view/helpers/asset_url_helper.rb +354 -0
  155. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  156. data/lib/action_view/helpers/cache_helper.rb +150 -18
  157. data/lib/action_view/helpers/capture_helper.rb +42 -29
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  159. data/lib/action_view/helpers/date_helper.rb +268 -247
  160. data/lib/action_view/helpers/debug_helper.rb +10 -11
  161. data/lib/action_view/helpers/form_helper.rb +904 -547
  162. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  163. data/lib/action_view/helpers/form_tag_helper.rb +188 -88
  164. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  165. data/lib/action_view/helpers/number_helper.rb +148 -354
  166. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  167. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  168. data/lib/action_view/helpers/rendering_helper.rb +2 -4
  169. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  170. data/lib/action_view/helpers/tag_helper.rb +43 -37
  171. data/lib/action_view/helpers/tags.rb +39 -0
  172. data/lib/action_view/helpers/tags/base.rb +148 -0
  173. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  174. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  175. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  176. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  177. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  178. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  179. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  180. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  181. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  182. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  183. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  184. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  185. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  186. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  187. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  188. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  189. data/lib/action_view/helpers/tags/label.rb +65 -0
  190. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  191. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  192. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  193. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  194. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  195. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  196. data/lib/action_view/helpers/tags/select.rb +41 -0
  197. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  198. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  199. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  200. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  201. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  202. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  203. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  204. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  205. data/lib/action_view/helpers/text_helper.rb +126 -113
  206. data/lib/action_view/helpers/translation_helper.rb +32 -16
  207. data/lib/action_view/helpers/url_helper.rb +200 -271
  208. data/lib/action_view/locale/en.yml +1 -105
  209. data/lib/action_view/log_subscriber.rb +6 -4
  210. data/lib/action_view/lookup_context.rb +15 -39
  211. data/lib/action_view/model_naming.rb +12 -0
  212. data/lib/action_view/path_set.rb +9 -39
  213. data/lib/action_view/railtie.rb +6 -22
  214. data/lib/action_view/record_identifier.rb +84 -0
  215. data/lib/action_view/renderer/abstract_renderer.rb +10 -19
  216. data/lib/action_view/renderer/partial_renderer.rb +144 -81
  217. data/lib/action_view/renderer/renderer.rb +2 -19
  218. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  219. data/lib/action_view/renderer/template_renderer.rb +14 -13
  220. data/lib/action_view/routing_url_for.rb +107 -0
  221. data/lib/action_view/template.rb +22 -21
  222. data/lib/action_view/template/error.rb +22 -12
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/handlers/builder.rb +1 -1
  225. data/lib/action_view/template/handlers/erb.rb +11 -16
  226. data/lib/action_view/template/handlers/raw.rb +11 -0
  227. data/lib/action_view/template/resolver.rb +111 -83
  228. data/lib/action_view/template/text.rb +12 -8
  229. data/lib/action_view/template/types.rb +57 -0
  230. data/lib/action_view/test_case.rb +66 -43
  231. data/lib/action_view/testing/resolvers.rb +3 -2
  232. data/lib/action_view/vendor/html-scanner.rb +20 -0
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  235. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
  236. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
  237. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  238. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  239. metadata +135 -125
  240. data/lib/action_controller/caching/actions.rb +0 -185
  241. data/lib/action_controller/caching/pages.rb +0 -187
  242. data/lib/action_controller/caching/sweeping.rb +0 -97
  243. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  244. data/lib/action_controller/metal/compatibility.rb +0 -65
  245. data/lib/action_controller/metal/session_management.rb +0 -14
  246. data/lib/action_controller/railties/paths.rb +0 -25
  247. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  248. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  249. data/lib/action_dispatch/middleware/head.rb +0 -18
  250. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  251. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  252. data/lib/action_view/asset_paths.rb +0 -142
  253. data/lib/action_view/helpers/asset_paths.rb +0 -7
  254. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  255. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  256. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  257. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  258. data/lib/sprockets/assets.rake +0 -99
  259. data/lib/sprockets/bootstrap.rb +0 -37
  260. data/lib/sprockets/compressors.rb +0 -83
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  263. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  264. data/lib/sprockets/railtie.rb +0 -62
  265. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,30 +1,30 @@
1
1
  require 'action_dispatch/http/request'
2
2
  require 'action_dispatch/middleware/exception_wrapper'
3
+ require 'action_dispatch/routing/inspector'
3
4
 
4
5
  module ActionDispatch
5
6
  # This middleware is responsible for logging exceptions and
6
7
  # showing a debugging page in case the request is local.
7
8
  class DebugExceptions
8
- RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
9
+ RESCUES_TEMPLATE_PATH = File.expand_path('../templates', __FILE__)
9
10
 
10
- def initialize(app)
11
- @app = app
11
+ def initialize(app, routes_app = nil)
12
+ @app = app
13
+ @routes_app = routes_app
12
14
  end
13
15
 
14
16
  def call(env)
15
- begin
16
- response = @app.call(env)
17
-
18
- if response[1]['X-Cascade'] == 'pass'
19
- body = response[2]
20
- body.close if body.respond_to?(:close)
21
- raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
22
- end
23
- rescue Exception => exception
24
- raise exception if env['action_dispatch.show_exceptions'] == false
17
+ _, headers, body = response = @app.call(env)
18
+
19
+ if headers['X-Cascade'] == 'pass'
20
+ body.close if body.respond_to?(:close)
21
+ raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
25
22
  end
26
23
 
27
- exception ? render_exception(env, exception) : response
24
+ response
25
+ rescue Exception => exception
26
+ raise exception if env['action_dispatch.show_exceptions'] == false
27
+ render_exception(env, exception)
28
28
  end
29
29
 
30
30
  private
@@ -39,9 +39,12 @@ module ActionDispatch
39
39
  :exception => wrapper.exception,
40
40
  :application_trace => wrapper.application_trace,
41
41
  :framework_trace => wrapper.framework_trace,
42
- :full_trace => wrapper.full_trace
42
+ :full_trace => wrapper.full_trace,
43
+ :routes_inspector => routes_inspector(exception),
44
+ :source_extract => wrapper.source_extract,
45
+ :line_number => wrapper.line_number,
46
+ :file => wrapper.file
43
47
  )
44
-
45
48
  file = "rescues/#{wrapper.rescue_template}"
46
49
  body = template.render(:template => file, :layout => 'rescues/layout')
47
50
  render(wrapper.status_code, body)
@@ -76,7 +79,13 @@ module ActionDispatch
76
79
  end
77
80
 
78
81
  def stderr_logger
79
- @stderr_logger ||= Logger.new($stderr)
82
+ @stderr_logger ||= ActiveSupport::Logger.new($stderr)
83
+ end
84
+
85
+ def routes_inspector(exception)
86
+ if @routes_app.respond_to?(:routes) && (exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error))
87
+ ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
88
+ end
80
89
  end
81
90
  end
82
91
  end
@@ -1,5 +1,5 @@
1
1
  require 'action_controller/metal/exceptions'
2
- require 'active_support/core_ext/exception'
2
+ require 'active_support/core_ext/class/attribute_accessors'
3
3
 
4
4
  module ActionDispatch
5
5
  class ExceptionWrapper
@@ -10,7 +10,10 @@ module ActionDispatch
10
10
  'AbstractController::ActionNotFound' => :not_found,
11
11
  'ActionController::MethodNotAllowed' => :method_not_allowed,
12
12
  'ActionController::NotImplemented' => :not_implemented,
13
- 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
13
+ 'ActionController::UnknownFormat' => :not_acceptable,
14
+ 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity,
15
+ 'ActionController::BadRequest' => :bad_request,
16
+ 'ActionController::ParameterMissing' => :bad_request
14
17
  )
15
18
 
16
19
  cattr_accessor :rescue_templates
@@ -22,7 +25,7 @@ module ActionDispatch
22
25
  'ActionView::Template::Error' => 'template_error'
23
26
  )
24
27
 
25
- attr_reader :env, :exception
28
+ attr_reader :env, :exception, :line_number, :file
26
29
 
27
30
  def initialize(env, exception)
28
31
  @env = env
@@ -53,6 +56,15 @@ module ActionDispatch
53
56
  Rack::Utils.status_code(@@rescue_responses[class_name])
54
57
  end
55
58
 
59
+ def source_extract
60
+ if application_trace && trace = application_trace.first
61
+ file, line, _ = trace.split(":")
62
+ @file = file
63
+ @line_number = line.to_i
64
+ source_fragment(@file, @line_number)
65
+ end
66
+ end
67
+
56
68
  private
57
69
 
58
70
  def original_exception(exception)
@@ -78,5 +90,17 @@ module ActionDispatch
78
90
  def backtrace_cleaner
79
91
  @backtrace_cleaner ||= @env['action_dispatch.backtrace_cleaner']
80
92
  end
93
+
94
+ def source_fragment(path, line)
95
+ return unless Rails.respond_to?(:root) && Rails.root
96
+ full_path = Rails.root.join(path)
97
+ if File.exists?(full_path)
98
+ File.open(full_path, "r") do |file|
99
+ start = [line - 3, 0].max
100
+ lines = file.each_line.drop(start).take(6)
101
+ Hash[*(start+1..(lines.count+start)).zip(lines).flatten]
102
+ end
103
+ end
104
+ end
81
105
  end
82
106
  end
@@ -1,23 +1,23 @@
1
1
  module ActionDispatch
2
- class Request
2
+ class Request < Rack::Request
3
3
  # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
4
4
  # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
5
5
  # to put a new one.
6
6
  def flash
7
- @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new)
7
+ @env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"])
8
8
  end
9
9
  end
10
10
 
11
11
  # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed
12
12
  # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
13
13
  # action that sets <tt>flash[:notice] = "Post successfully created"</tt> before redirecting to a display action that can
14
- # then expose the flash to its template. Actually, that exposure is automatically done. Example:
14
+ # then expose the flash to its template. Actually, that exposure is automatically done.
15
15
  #
16
16
  # class PostsController < ActionController::Base
17
17
  # def create
18
18
  # # save post
19
19
  # flash[:notice] = "Post successfully created"
20
- # redirect_to posts_path(@post)
20
+ # redirect_to @post
21
21
  # end
22
22
  #
23
23
  # def show
@@ -59,28 +59,41 @@ module ActionDispatch
59
59
  @flash[k]
60
60
  end
61
61
 
62
- # Convenience accessor for flash.now[:alert]=
62
+ # Convenience accessor for <tt>flash.now[:alert]=</tt>.
63
63
  def alert=(message)
64
64
  self[:alert] = message
65
65
  end
66
66
 
67
- # Convenience accessor for flash.now[:notice]=
67
+ # Convenience accessor for <tt>flash.now[:notice]=</tt>.
68
68
  def notice=(message)
69
69
  self[:notice] = message
70
70
  end
71
71
  end
72
72
 
73
- # Implementation detail: please do not change the signature of the
74
- # FlashHash class. Doing that will likely affect all Rails apps in
75
- # production as the FlashHash currently stored in their sessions will
76
- # become invalid.
77
73
  class FlashHash
78
74
  include Enumerable
79
75
 
80
- def initialize #:nodoc:
81
- @used = Set.new
82
- @closed = false
83
- @flashes = {}
76
+ def self.from_session_value(value)
77
+ flash = case value
78
+ when FlashHash # Rails 3.1, 3.2
79
+ new(value.instance_variable_get(:@flashes), value.instance_variable_get(:@used))
80
+ when Hash # Rails 4.0
81
+ new(value['flashes'], value['discard'])
82
+ else
83
+ new
84
+ end
85
+
86
+ flash.tap(&:sweep)
87
+ end
88
+
89
+ def to_session_value
90
+ return nil if empty?
91
+ {'discard' => @discard.to_a, 'flashes' => @flashes}
92
+ end
93
+
94
+ def initialize(flashes = {}, discard = []) #:nodoc:
95
+ @discard = Set.new(discard)
96
+ @flashes = flashes
84
97
  @now = nil
85
98
  end
86
99
 
@@ -92,8 +105,8 @@ module ActionDispatch
92
105
  super
93
106
  end
94
107
 
95
- def []=(k, v) #:nodoc:
96
- keep(k)
108
+ def []=(k, v)
109
+ @discard.delete k
97
110
  @flashes[k] = v
98
111
  end
99
112
 
@@ -102,7 +115,7 @@ module ActionDispatch
102
115
  end
103
116
 
104
117
  def update(h) #:nodoc:
105
- h.keys.each { |k| keep(k) }
118
+ @discard.subtract h.keys
106
119
  @flashes.update h
107
120
  self
108
121
  end
@@ -116,6 +129,7 @@ module ActionDispatch
116
129
  end
117
130
 
118
131
  def delete(key)
132
+ @discard.delete key
119
133
  @flashes.delete key
120
134
  self
121
135
  end
@@ -129,6 +143,7 @@ module ActionDispatch
129
143
  end
130
144
 
131
145
  def clear
146
+ @discard.clear
132
147
  @flashes.clear
133
148
  end
134
149
 
@@ -139,7 +154,7 @@ module ActionDispatch
139
154
  alias :merge! :update
140
155
 
141
156
  def replace(h) #:nodoc:
142
- @used = Set.new
157
+ @discard.clear
143
158
  @flashes.replace h
144
159
  self
145
160
  end
@@ -154,6 +169,14 @@ module ActionDispatch
154
169
  # vanish when the current action is done.
155
170
  #
156
171
  # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
172
+ #
173
+ # Also, brings two convenience accessors:
174
+ #
175
+ # flash.now.alert = "Beware now!"
176
+ # # Equivalent to flash.now[:alert] = "Beware now!"
177
+ #
178
+ # flash.now.notice = "Good luck now!"
179
+ # # Equivalent to flash.now[:notice] = "Good luck now!"
157
180
  def now
158
181
  @now ||= FlashNow.new(self)
159
182
  end
@@ -163,7 +186,8 @@ module ActionDispatch
163
186
  # flash.keep # keeps the entire flash
164
187
  # flash.keep(:notice) # keeps only the "notice" entry, the rest of the flash is discarded
165
188
  def keep(k = nil)
166
- use(k, false)
189
+ @discard.subtract Array(k || keys)
190
+ k ? self[k] : self
167
191
  end
168
192
 
169
193
  # Marks the entire flash or a single flash entry to be discarded by the end of the current action:
@@ -171,63 +195,42 @@ module ActionDispatch
171
195
  # flash.discard # discard the entire flash at the end of the current action
172
196
  # flash.discard(:warning) # discard only the "warning" entry at the end of the current action
173
197
  def discard(k = nil)
174
- use(k)
198
+ @discard.merge Array(k || keys)
199
+ k ? self[k] : self
175
200
  end
176
201
 
177
202
  # Mark for removal entries that were kept, and delete unkept ones.
178
203
  #
179
204
  # This method is called automatically by filters, so you generally don't need to care about it.
180
205
  def sweep #:nodoc:
181
- keys.each do |k|
182
- unless @used.include?(k)
183
- @used << k
184
- else
185
- delete(k)
186
- @used.delete(k)
187
- end
188
- end
189
-
190
- # clean up after keys that could have been left over by calling reject! or shift on the flash
191
- (@used - keys).each{ |k| @used.delete(k) }
206
+ @discard.each { |k| @flashes.delete k }
207
+ @discard.replace @flashes.keys
192
208
  end
193
209
 
194
- # Convenience accessor for flash[:alert]
210
+ # Convenience accessor for <tt>flash[:alert]</tt>.
195
211
  def alert
196
212
  self[:alert]
197
213
  end
198
214
 
199
- # Convenience accessor for flash[:alert]=
215
+ # Convenience accessor for <tt>flash[:alert]=</tt>.
200
216
  def alert=(message)
201
217
  self[:alert] = message
202
218
  end
203
219
 
204
- # Convenience accessor for flash[:notice]
220
+ # Convenience accessor for <tt>flash[:notice]</tt>.
205
221
  def notice
206
222
  self[:notice]
207
223
  end
208
224
 
209
- # Convenience accessor for flash[:notice]=
225
+ # Convenience accessor for <tt>flash[:notice]=</tt>.
210
226
  def notice=(message)
211
227
  self[:notice] = message
212
228
  end
213
229
 
214
230
  protected
215
-
216
- def now_is_loaded?
217
- !!@now
218
- end
219
-
220
- # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
221
- # use() # marks the entire flash as used
222
- # use('msg') # marks the "msg" entry as used
223
- # use(nil, false) # marks the entire flash as unused (keeps it around for one more action)
224
- # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
225
- # Returns the single value for the key you asked to be marked (un)used or the FlashHash itself
226
- # if no key is passed.
227
- def use(key = nil, used = true)
228
- Array(key || keys).each { |k| used ? @used << k : @used.delete(k) }
229
- return key ? self[key] : self
230
- end
231
+ def now_is_loaded?
232
+ @now
233
+ end
231
234
  end
232
235
 
233
236
  def initialize(app)
@@ -235,18 +238,14 @@ module ActionDispatch
235
238
  end
236
239
 
237
240
  def call(env)
238
- if (session = env['rack.session']) && (flash = session['flash'])
239
- flash.sweep
240
- end
241
-
242
241
  @app.call(env)
243
242
  ensure
244
- session = env['rack.session'] || {}
243
+ session = Request::Session.find(env) || {}
245
244
  flash_hash = env[KEY]
246
245
 
247
246
  if flash_hash
248
247
  if !flash_hash.empty? || session.key?('flash')
249
- session["flash"] = flash_hash
248
+ session["flash"] = flash_hash.to_session_value
250
249
  new_hash = flash_hash.dup
251
250
  else
252
251
  new_hash = flash_hash
@@ -255,7 +254,8 @@ module ActionDispatch
255
254
  env[KEY] = new_hash
256
255
  end
257
256
 
258
- if session.key?('flash') && session['flash'].empty?
257
+ if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
258
+ session.key?('flash') && session['flash'].nil?
259
259
  session.delete('flash')
260
260
  end
261
261
  end
@@ -4,10 +4,16 @@ require 'active_support/core_ext/hash/indifferent_access'
4
4
 
5
5
  module ActionDispatch
6
6
  class ParamsParser
7
- DEFAULT_PARSERS = {
8
- Mime::XML => :xml_simple,
9
- Mime::JSON => :json
10
- }
7
+ class ParseError < StandardError
8
+ attr_reader :original_exception
9
+
10
+ def initialize(message, original_exception)
11
+ super(message)
12
+ @original_exception = original_exception
13
+ end
14
+ end
15
+
16
+ DEFAULT_PARSERS = { Mime::JSON => :json }
11
17
 
12
18
  def initialize(app, parsers = {})
13
19
  @app, @parsers = app, DEFAULT_PARSERS.merge(parsers)
@@ -27,49 +33,28 @@ module ActionDispatch
27
33
 
28
34
  return false if request.content_length.zero?
29
35
 
30
- mime_type = content_type_from_legacy_post_data_format_header(env) ||
31
- request.content_mime_type
32
-
33
- strategy = @parsers[mime_type]
36
+ strategy = @parsers[request.content_mime_type]
34
37
 
35
38
  return false unless strategy
36
39
 
37
40
  case strategy
38
41
  when Proc
39
42
  strategy.call(request.raw_post)
40
- when :xml_simple, :xml_node
41
- data = request.deep_munge(Hash.from_xml(request.body.read) || {})
42
- request.body.rewind if request.body.respond_to?(:rewind)
43
- data.with_indifferent_access
44
- when :yaml
45
- YAML.load(request.raw_post)
46
43
  when :json
47
44
  data = ActiveSupport::JSON.decode(request.body)
48
- request.body.rewind if request.body.respond_to?(:rewind)
49
45
  data = {:_json => data} unless data.is_a?(Hash)
50
46
  request.deep_munge(data).with_indifferent_access
51
47
  else
52
48
  false
53
49
  end
54
- rescue Exception => e # YAML, XML or Ruby code block errors
50
+ rescue Exception => e # JSON or Ruby code block errors
55
51
  logger(env).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
56
52
 
57
- raise e
58
- end
59
-
60
- def content_type_from_legacy_post_data_format_header(env)
61
- if x_post_format = env['HTTP_X_POST_DATA_FORMAT']
62
- case x_post_format.to_s.downcase
63
- when 'yaml' then return Mime::YAML
64
- when 'xml' then return Mime::XML
65
- end
66
- end
67
-
68
- nil
53
+ raise ParseError.new(e.message, e)
69
54
  end
70
55
 
71
56
  def logger(env)
72
- env['action_dispatch.logger'] || Logger.new($stderr)
57
+ env['action_dispatch.logger'] || ActiveSupport::Logger.new($stderr)
73
58
  end
74
59
  end
75
60
  end