actionpack 1.13.6 → 2.0.0

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 (317) hide show
  1. data/CHANGELOG +1400 -20
  2. data/MIT-LICENSE +1 -1
  3. data/README +5 -5
  4. data/RUNNING_UNIT_TESTS +4 -5
  5. data/Rakefile +5 -6
  6. data/install.rb +2 -2
  7. data/lib/action_controller.rb +11 -15
  8. data/lib/action_controller/assertions.rb +12 -25
  9. data/lib/action_controller/assertions/dom_assertions.rb +18 -4
  10. data/lib/action_controller/assertions/model_assertions.rb +8 -1
  11. data/lib/action_controller/assertions/response_assertions.rb +35 -12
  12. data/lib/action_controller/assertions/routing_assertions.rb +56 -12
  13. data/lib/action_controller/assertions/selector_assertions.rb +105 -38
  14. data/lib/action_controller/assertions/tag_assertions.rb +28 -15
  15. data/lib/action_controller/base.rb +318 -250
  16. data/lib/action_controller/benchmarking.rb +33 -29
  17. data/lib/action_controller/caching.rb +130 -64
  18. data/lib/action_controller/cgi_ext.rb +16 -0
  19. data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
  20. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  21. data/lib/action_controller/cgi_ext/session.rb +73 -0
  22. data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
  23. data/lib/action_controller/cgi_process.rb +34 -57
  24. data/lib/action_controller/components.rb +19 -36
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/dispatcher.rb +195 -0
  27. data/lib/action_controller/filters.rb +35 -34
  28. data/lib/action_controller/flash.rb +30 -35
  29. data/lib/action_controller/helpers.rb +121 -47
  30. data/lib/action_controller/http_authentication.rb +126 -0
  31. data/lib/action_controller/integration.rb +105 -101
  32. data/lib/action_controller/layout.rb +59 -47
  33. data/lib/action_controller/mime_responds.rb +57 -68
  34. data/lib/action_controller/mime_type.rb +43 -80
  35. data/lib/action_controller/mime_types.rb +20 -0
  36. data/lib/action_controller/polymorphic_routes.rb +88 -0
  37. data/lib/action_controller/record_identifier.rb +91 -0
  38. data/lib/action_controller/request.rb +553 -88
  39. data/lib/action_controller/request_forgery_protection.rb +126 -0
  40. data/lib/action_controller/request_profiler.rb +138 -0
  41. data/lib/action_controller/rescue.rb +185 -69
  42. data/lib/action_controller/resources.rb +211 -172
  43. data/lib/action_controller/response.rb +49 -8
  44. data/lib/action_controller/routing.rb +359 -236
  45. data/lib/action_controller/routing_optimisation.rb +119 -0
  46. data/lib/action_controller/session/active_record_store.rb +3 -2
  47. data/lib/action_controller/session/cookie_store.rb +161 -0
  48. data/lib/action_controller/session/mem_cache_store.rb +9 -16
  49. data/lib/action_controller/session_management.rb +17 -8
  50. data/lib/action_controller/streaming.rb +6 -3
  51. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  52. data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
  53. data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
  54. data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
  55. data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
  56. data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
  57. data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
  58. data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
  59. data/lib/action_controller/test_case.rb +53 -0
  60. data/lib/action_controller/test_process.rb +59 -46
  61. data/lib/action_controller/url_rewriter.rb +48 -24
  62. data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
  65. data/lib/action_controller/verification.rb +27 -21
  66. data/lib/action_pack.rb +1 -1
  67. data/lib/action_pack/version.rb +4 -4
  68. data/lib/action_view.rb +2 -3
  69. data/lib/action_view/base.rb +218 -63
  70. data/lib/action_view/compiled_templates.rb +1 -2
  71. data/lib/action_view/helpers/active_record_helper.rb +35 -17
  72. data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
  73. data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
  74. data/lib/action_view/helpers/benchmark_helper.rb +12 -5
  75. data/lib/action_view/helpers/cache_helper.rb +29 -0
  76. data/lib/action_view/helpers/capture_helper.rb +97 -63
  77. data/lib/action_view/helpers/date_helper.rb +295 -35
  78. data/lib/action_view/helpers/debug_helper.rb +6 -2
  79. data/lib/action_view/helpers/form_helper.rb +354 -111
  80. data/lib/action_view/helpers/form_options_helper.rb +171 -109
  81. data/lib/action_view/helpers/form_tag_helper.rb +332 -76
  82. data/lib/action_view/helpers/javascript_helper.rb +35 -11
  83. data/lib/action_view/helpers/javascripts/controls.js +484 -354
  84. data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
  85. data/lib/action_view/helpers/javascripts/effects.js +396 -364
  86. data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
  87. data/lib/action_view/helpers/number_helper.rb +84 -60
  88. data/lib/action_view/helpers/prototype_helper.rb +419 -43
  89. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  90. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  91. data/lib/action_view/helpers/sanitize_helper.rb +223 -0
  92. data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
  93. data/lib/action_view/helpers/tag_helper.rb +69 -39
  94. data/lib/action_view/helpers/text_helper.rb +221 -148
  95. data/lib/action_view/helpers/url_helper.rb +283 -165
  96. data/lib/action_view/partials.rb +134 -62
  97. data/lib/action_view/template_error.rb +4 -12
  98. data/lib/actionpack.rb +1 -0
  99. data/test/abstract_unit.rb +21 -1
  100. data/test/action_view_test.rb +26 -0
  101. data/test/active_record_unit.rb +12 -20
  102. data/test/activerecord/active_record_store_test.rb +2 -2
  103. data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
  104. data/test/controller/action_pack_assertions_test.rb +21 -152
  105. data/test/controller/addresses_render_test.rb +2 -7
  106. data/test/controller/assert_select_test.rb +120 -14
  107. data/test/controller/base_test.rb +11 -13
  108. data/test/controller/caching_test.rb +125 -5
  109. data/test/controller/capture_test.rb +23 -16
  110. data/test/controller/cgi_test.rb +66 -391
  111. data/test/controller/components_test.rb +31 -42
  112. data/test/controller/content_type_test.rb +1 -1
  113. data/test/controller/cookie_test.rb +42 -14
  114. data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
  115. data/test/controller/dispatcher_test.rb +123 -0
  116. data/test/controller/fake_models.rb +5 -0
  117. data/test/controller/filters_test.rb +44 -7
  118. data/test/controller/flash_test.rb +46 -2
  119. data/test/controller/fragment_store_setting_test.rb +10 -8
  120. data/test/controller/helper_test.rb +19 -2
  121. data/test/controller/html-scanner/document_test.rb +124 -0
  122. data/test/controller/html-scanner/node_test.rb +69 -0
  123. data/test/controller/html-scanner/sanitizer_test.rb +250 -0
  124. data/test/controller/html-scanner/tag_node_test.rb +239 -0
  125. data/test/controller/html-scanner/text_node_test.rb +51 -0
  126. data/test/controller/html-scanner/tokenizer_test.rb +125 -0
  127. data/test/controller/http_authentication_test.rb +54 -0
  128. data/test/controller/integration_test.rb +12 -26
  129. data/test/controller/layout_test.rb +64 -12
  130. data/test/controller/mime_responds_test.rb +193 -38
  131. data/test/controller/mime_type_test.rb +30 -8
  132. data/test/controller/new_render_test.rb +104 -22
  133. data/test/controller/polymorphic_routes_test.rb +98 -0
  134. data/test/controller/record_identifier_test.rb +103 -0
  135. data/test/controller/redirect_test.rb +120 -18
  136. data/test/controller/render_test.rb +195 -45
  137. data/test/controller/request_forgery_protection_test.rb +217 -0
  138. data/test/controller/request_test.rb +545 -27
  139. data/test/controller/rescue_test.rb +501 -0
  140. data/test/controller/resources_test.rb +258 -132
  141. data/test/controller/routing_test.rb +502 -106
  142. data/test/controller/selector_test.rb +5 -5
  143. data/test/controller/send_file_test.rb +17 -7
  144. data/test/controller/session/cookie_store_test.rb +246 -0
  145. data/test/controller/session/mem_cache_store_test.rb +182 -0
  146. data/test/controller/session_fixation_test.rb +8 -11
  147. data/test/controller/session_management_test.rb +7 -7
  148. data/test/controller/test_test.rb +150 -38
  149. data/test/controller/url_rewriter_test.rb +87 -12
  150. data/test/controller/verification_test.rb +11 -0
  151. data/test/controller/view_paths_test.rb +137 -0
  152. data/test/controller/webservice_test.rb +11 -75
  153. data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
  154. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  155. data/test/fixtures/developer.rb +2 -0
  156. data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
  157. data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
  158. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  159. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  160. data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
  161. data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
  162. data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
  163. data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
  164. data/test/fixtures/multipart/binary_file +0 -0
  165. data/test/fixtures/multipart/bracketed_param +5 -0
  166. data/test/fixtures/override/test/hello_world.erb +1 -0
  167. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  168. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  169. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  170. data/test/fixtures/post_test/post/index.html.erb +1 -0
  171. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  172. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  173. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  174. data/test/fixtures/public/404.html +1 -0
  175. data/test/fixtures/public/500.html +1 -0
  176. data/test/fixtures/public/javascripts/application.js +0 -1
  177. data/test/fixtures/public/javascripts/bank.js +1 -0
  178. data/test/fixtures/public/javascripts/robber.js +1 -0
  179. data/test/fixtures/public/stylesheets/bank.css +1 -0
  180. data/test/fixtures/public/stylesheets/robber.css +1 -0
  181. data/test/fixtures/replies.yml +2 -0
  182. data/test/fixtures/reply.rb +2 -1
  183. data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
  184. data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
  185. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  186. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  187. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  188. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  189. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  190. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  191. data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
  192. data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
  193. data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
  194. data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
  195. data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
  196. data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
  197. data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
  198. data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
  199. data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
  200. data/test/fixtures/test/_hash_greeting.erb +1 -0
  201. data/test/fixtures/test/_hash_object.erb +2 -0
  202. data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
  203. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  204. data/test/fixtures/test/_partial.erb +1 -0
  205. data/test/fixtures/test/_partial.html.erb +1 -0
  206. data/test/fixtures/test/_partial.js.erb +1 -0
  207. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  208. data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
  209. data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
  210. data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
  211. data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
  212. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  213. data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
  214. data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
  215. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  216. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  217. data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  218. data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
  219. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  220. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  221. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  222. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  223. data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
  224. data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
  225. data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
  226. data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
  227. data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
  228. data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
  229. data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
  230. data/test/fixtures/test/list.erb +1 -0
  231. data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
  232. data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
  233. data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  234. data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
  235. data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
  236. data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
  237. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  238. data/test/fixtures/topic.rb +1 -1
  239. data/test/template/active_record_helper_test.rb +67 -20
  240. data/test/template/asset_tag_helper_test.rb +222 -54
  241. data/test/template/atom_feed_helper_test.rb +101 -0
  242. data/test/template/benchmark_helper_test.rb +2 -2
  243. data/test/template/compiled_templates_test.rb +76 -32
  244. data/test/template/date_helper_test.rb +125 -9
  245. data/test/template/form_helper_test.rb +326 -33
  246. data/test/template/form_options_helper_test.rb +822 -15
  247. data/test/template/form_tag_helper_test.rb +96 -30
  248. data/test/template/javascript_helper_test.rb +61 -13
  249. data/test/template/number_helper_test.rb +12 -11
  250. data/test/template/prototype_helper_test.rb +185 -24
  251. data/test/template/sanitize_helper_test.rb +49 -0
  252. data/test/template/scriptaculous_helper_test.rb +9 -3
  253. data/test/template/tag_helper_test.rb +13 -2
  254. data/test/template/text_helper_test.rb +38 -52
  255. data/test/template/url_helper_test.rb +216 -46
  256. metadata +144 -116
  257. data/examples/.htaccess +0 -24
  258. data/examples/address_book/index.rhtml +0 -33
  259. data/examples/address_book/layout.rhtml +0 -8
  260. data/examples/address_book_controller.cgi +0 -9
  261. data/examples/address_book_controller.fcgi +0 -6
  262. data/examples/address_book_controller.rb +0 -52
  263. data/examples/address_book_controller.rbx +0 -4
  264. data/examples/benchmark.rb +0 -52
  265. data/examples/benchmark_with_ar.fcgi +0 -89
  266. data/examples/blog_controller.cgi +0 -53
  267. data/examples/debate/index.rhtml +0 -14
  268. data/examples/debate/new_topic.rhtml +0 -22
  269. data/examples/debate/topic.rhtml +0 -32
  270. data/examples/debate_controller.cgi +0 -57
  271. data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
  272. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
  273. data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
  274. data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
  275. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
  276. data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
  277. data/lib/action_controller/deprecated_dependencies.rb +0 -65
  278. data/lib/action_controller/deprecated_redirects.rb +0 -17
  279. data/lib/action_controller/deprecated_request_methods.rb +0 -34
  280. data/lib/action_controller/macros/auto_complete.rb +0 -53
  281. data/lib/action_controller/macros/in_place_editing.rb +0 -33
  282. data/lib/action_controller/pagination.rb +0 -408
  283. data/lib/action_controller/scaffolding.rb +0 -189
  284. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
  285. data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
  286. data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
  287. data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
  288. data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
  289. data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
  290. data/lib/action_controller/vendor/xml_node.rb +0 -97
  291. data/lib/action_view/helpers/deprecated_helper.rb +0 -37
  292. data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
  293. data/lib/action_view/helpers/pagination_helper.rb +0 -86
  294. data/test/activerecord/active_record_assertions_test.rb +0 -92
  295. data/test/activerecord/pagination_test.rb +0 -165
  296. data/test/controller/deprecated_instance_variables_test.rb +0 -48
  297. data/test/controller/raw_post_test.rb +0 -68
  298. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
  299. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
  300. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
  301. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
  302. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
  303. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
  304. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
  305. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
  306. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
  307. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
  308. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
  309. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
  310. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
  311. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
  312. data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
  313. data/test/fixtures/test/_hash_object.rhtml +0 -1
  314. data/test/fixtures/test/list.rhtml +0 -1
  315. data/test/template/deprecated_helper_test.rb +0 -36
  316. data/test/template/deprecated_instance_variables_test.rb +0 -43
  317. data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -23,18 +23,19 @@ module ActionController #:nodoc:
23
23
  # * <tt>domain</tt> - the domain for which this cookie applies.
24
24
  # * <tt>expires</tt> - the time at which this cookie expires, as a +Time+ object.
25
25
  # * <tt>secure</tt> - whether this cookie is a secure cookie or not (default to false).
26
- # Secure cookies are only transmitted to HTTPS servers.
26
+ # Secure cookies are only transmitted to HTTPS servers.
27
+ # * <tt>http_only</tt> - whether this cookie is accessible via scripting or only HTTP (defaults to false).
28
+
27
29
  module Cookies
30
+ def self.included(base)
31
+ base.helper_method :cookies
32
+ end
33
+
28
34
  protected
29
35
  # Returns the cookie container, which operates as described above.
30
36
  def cookies
31
37
  CookieJar.new(self)
32
38
  end
33
-
34
- # Deprecated cookie writer method
35
- def cookie(*options)
36
- response.headers['cookie'] << CGI::Cookie.new(*options)
37
- end
38
39
  end
39
40
 
40
41
  class CookieJar < Hash #:nodoc:
@@ -44,8 +45,8 @@ module ActionController #:nodoc:
44
45
  update(@cookies)
45
46
  end
46
47
 
47
- # Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using either the cookie method
48
- # or cookies[]= (for simple name/value cookies without options).
48
+ # Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using cookies[]=
49
+ # (for simple name/value cookies without options).
49
50
  def [](name)
50
51
  cookie = @cookies[name.to_s]
51
52
  if cookie && cookie.respond_to?(:value)
@@ -80,4 +81,4 @@ module ActionController #:nodoc:
80
81
  @controller.response.headers["cookie"] << cookie
81
82
  end
82
83
  end
83
- end
84
+ end
@@ -0,0 +1,195 @@
1
+ module ActionController
2
+ # Dispatches requests to the appropriate controller and takes care of
3
+ # reloading the app after each request when Dependencies.load? is true.
4
+ class Dispatcher
5
+ class << self
6
+ # Backward-compatible class method takes CGI-specific args. Deprecated
7
+ # in favor of Dispatcher.new(output, request, response).dispatch!
8
+ def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
9
+ new(output).dispatch_cgi(cgi, session_options)
10
+ end
11
+
12
+ # Declare a block to be called before each dispatch.
13
+ # Run in the order declared.
14
+ def before_dispatch(*method_names, &block)
15
+ callbacks[:before].concat method_names
16
+ callbacks[:before] << block if block_given?
17
+ end
18
+
19
+ # Declare a block to be called after each dispatch.
20
+ # Run in reverse of the order declared.
21
+ def after_dispatch(*method_names, &block)
22
+ callbacks[:after].concat method_names
23
+ callbacks[:after] << block if block_given?
24
+ end
25
+
26
+ # Add a preparation callback. Preparation callbacks are run before every
27
+ # request in development mode, and before the first request in production
28
+ # mode.
29
+ #
30
+ # An optional identifier may be supplied for the callback. If provided,
31
+ # to_prepare may be called again with the same identifier to replace the
32
+ # existing callback. Passing an identifier is a suggested practice if the
33
+ # code adding a preparation block may be reloaded.
34
+ def to_prepare(identifier = nil, &block)
35
+ # Already registered: update the existing callback
36
+ if identifier
37
+ if callback = callbacks[:prepare].assoc(identifier)
38
+ callback[1] = block
39
+ else
40
+ callbacks[:prepare] << [identifier, block]
41
+ end
42
+ else
43
+ callbacks[:prepare] << block
44
+ end
45
+ end
46
+
47
+ # If the block raises, send status code as a last-ditch response.
48
+ def failsafe_response(fallback_output, status, originating_exception = nil)
49
+ yield
50
+ rescue Exception => exception
51
+ begin
52
+ log_failsafe_exception(status, originating_exception || exception)
53
+ body = failsafe_response_body(status)
54
+ fallback_output.write "Status: #{status}\r\nContent-Type: text/html\r\n\r\n#{body}"
55
+ nil
56
+ rescue Exception => failsafe_error # Logger or IO errors
57
+ $stderr.puts "Error during failsafe response: #{failsafe_error}"
58
+ $stderr.puts "(originally #{originating_exception})" if originating_exception
59
+ end
60
+ end
61
+
62
+ private
63
+ def failsafe_response_body(status)
64
+ error_path = "#{error_file_path}/#{status.to_s[0..3]}.html"
65
+
66
+ if File.exist?(error_path)
67
+ File.read(error_path)
68
+ else
69
+ "<html><body><h1>#{status}</h1></body></html>"
70
+ end
71
+ end
72
+
73
+ def log_failsafe_exception(status, exception)
74
+ message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: #{status}\n"
75
+ message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
76
+ failsafe_logger.fatal message
77
+ end
78
+
79
+ def failsafe_logger
80
+ if defined?(::RAILS_DEFAULT_LOGGER) && !::RAILS_DEFAULT_LOGGER.nil?
81
+ ::RAILS_DEFAULT_LOGGER
82
+ else
83
+ Logger.new($stderr)
84
+ end
85
+ end
86
+ end
87
+
88
+ cattr_accessor :error_file_path
89
+ self.error_file_path = "#{::RAILS_ROOT}/public" if defined? ::RAILS_ROOT
90
+
91
+ cattr_accessor :callbacks
92
+ self.callbacks = Hash.new { |h, k| h[k] = [] }
93
+
94
+ cattr_accessor :unprepared
95
+ self.unprepared = true
96
+
97
+
98
+ before_dispatch :reload_application
99
+ before_dispatch :prepare_application
100
+ after_dispatch :flush_logger
101
+ after_dispatch :cleanup_application
102
+
103
+ if defined? ActiveRecord
104
+ to_prepare :activerecord_instantiate_observers do
105
+ ActiveRecord::Base.instantiate_observers
106
+ end
107
+ end
108
+
109
+ def initialize(output, request = nil, response = nil)
110
+ @output, @request, @response = output, request, response
111
+ end
112
+
113
+ def dispatch
114
+ run_callbacks :before
115
+ handle_request
116
+ rescue Exception => exception
117
+ failsafe_rescue exception
118
+ ensure
119
+ run_callbacks :after, :reverse_each
120
+ end
121
+
122
+ def dispatch_cgi(cgi, session_options)
123
+ if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
124
+ @request = CgiRequest.new(cgi, session_options)
125
+ @response = CgiResponse.new(cgi)
126
+ dispatch
127
+ end
128
+ rescue Exception => exception
129
+ failsafe_rescue exception
130
+ end
131
+
132
+ def reload_application
133
+ if Dependencies.load?
134
+ Routing::Routes.reload
135
+ self.unprepared = true
136
+ end
137
+ end
138
+
139
+ def prepare_application(force = false)
140
+ begin
141
+ require_dependency 'application' unless defined?(::ApplicationController)
142
+ rescue LoadError => error
143
+ raise unless error.message =~ /application\.rb/
144
+ end
145
+
146
+ ActiveRecord::Base.verify_active_connections! if defined?(ActiveRecord)
147
+
148
+ if unprepared || force
149
+ run_callbacks :prepare
150
+ self.unprepared = false
151
+ end
152
+ end
153
+
154
+ # Cleanup the application by clearing out loaded classes so they can
155
+ # be reloaded on the next request without restarting the server.
156
+ def cleanup_application(force = false)
157
+ if Dependencies.load? || force
158
+ ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
159
+ Dependencies.clear
160
+ ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
161
+ end
162
+ end
163
+
164
+ def flush_logger
165
+ RAILS_DEFAULT_LOGGER.flush if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush)
166
+ end
167
+
168
+ protected
169
+ def handle_request
170
+ @controller = Routing::Routes.recognize(@request)
171
+ @controller.process(@request, @response).out(@output)
172
+ end
173
+
174
+ def run_callbacks(kind, enumerator = :each)
175
+ callbacks[kind].send!(enumerator) do |callback|
176
+ case callback
177
+ when Proc; callback.call(self)
178
+ when String, Symbol; send!(callback)
179
+ when Array; callback[1].call(self)
180
+ else raise ArgumentError, "Unrecognized callback #{callback.inspect}"
181
+ end
182
+ end
183
+ end
184
+
185
+ def failsafe_rescue(exception)
186
+ self.class.failsafe_response(@output, '500 Internal Server Error', exception) do
187
+ if @controller ||= defined?(::ApplicationController) ? ::ApplicationController : Base
188
+ @controller.process_with_exception(@request, @response, exception).out(@output)
189
+ else
190
+ raise exception
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -1,11 +1,13 @@
1
1
  module ActionController #:nodoc:
2
2
  module Filters #:nodoc:
3
3
  def self.included(base)
4
- base.extend(ClassMethods)
5
- base.send(:include, ActionController::Filters::InstanceMethods)
4
+ base.class_eval do
5
+ extend ClassMethods
6
+ include ActionController::Filters::InstanceMethods
7
+ end
6
8
  end
7
9
 
8
- # Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do
10
+ # Filters enable controllers to run shared pre- and post-processing code for its actions. These filters can be used to do
9
11
  # authentication, caching, or auditing before the intended action is performed. Or to do localization or output
10
12
  # compression after the action has been performed. Filters have access to the request, response, and all the instance
11
13
  # variables set by other filters in the chain or by the action (in the case of after filters).
@@ -34,7 +36,7 @@ module ActionController #:nodoc:
34
36
  # end
35
37
  #
36
38
  # Now any actions performed on the BankController will have the audit method called before. On the VaultController,
37
- # first the audit method is called, then the verify_credentials method. If the audit method returns false, then
39
+ # first the audit method is called, then the verify_credentials method. If the audit method renders or redirects, then
38
40
  # verify_credentials and the intended action are never called.
39
41
  #
40
42
  # == Filter types
@@ -63,7 +65,7 @@ module ActionController #:nodoc:
63
65
  # Or just as a quick test. It works like this:
64
66
  #
65
67
  # class WeblogController < ActionController::Base
66
- # before_filter { |controller| false if controller.params["stop_action"] }
68
+ # before_filter { |controller| head(400) if controller.params["stop_action"] }
67
69
  # end
68
70
  #
69
71
  # As you can see, the block expects to be passed the controller after it has assigned the request to the internal variables.
@@ -88,7 +90,7 @@ module ActionController #:nodoc:
88
90
  # prepend_before_filter :ensure_items_in_cart, :ensure_items_in_stock
89
91
  #
90
92
  # The filter chain for the CheckoutController is now <tt>:ensure_items_in_cart, :ensure_items_in_stock,</tt>
91
- # <tt>:verify_open_shop</tt>. So if either of the ensure filters return false, we'll never get around to see if the shop
93
+ # <tt>:verify_open_shop</tt>. So if either of the ensure filters renders or redirects, we'll never get around to see if the shop
92
94
  # is open or not.
93
95
  #
94
96
  # You may pass multiple filter arguments of each type as well as a filter block.
@@ -140,23 +142,20 @@ module ActionController #:nodoc:
140
142
  # around_filter Authorizer.new
141
143
  #
142
144
  # class Authorizer
143
- # # This will run before the action. Returning false aborts the action.
145
+ # # This will run before the action. Redirecting aborts the action.
144
146
  # def before(controller)
145
- # if user.authorized?
146
- # return true
147
- # else
148
- # redirect_to login_url
149
- # return false
147
+ # unless user.authorized?
148
+ # redirect_to(login_url)
150
149
  # end
151
150
  # end
152
151
  #
153
- # # This will run after the action if and only if before returned true.
152
+ # # This will run after the action if and only if before did not render or redirect.
154
153
  # def after(controller)
155
154
  # end
156
155
  # end
157
156
  #
158
157
  # If the filter has before and after methods, the before method will be
159
- # called before the action. If before returns false, the filter chain is
158
+ # called before the action. If before renders or redirects, the filter chain is
160
159
  # halted and after will not be run. See Filter Chain Halting below for
161
160
  # an example.
162
161
  #
@@ -216,8 +215,8 @@ module ActionController #:nodoc:
216
215
  # <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
217
216
  # before a controller action is run. This is useful, for example, to deny
218
217
  # access to unauthenticated users or to redirect from http to https.
219
- # Simply return false from the filter or call render or redirect.
220
- # After filters will not be executed if the filter chain is halted.
218
+ # Simply call render or redirect. After filters will not be executed if the filter
219
+ # chain is halted.
221
220
  #
222
221
  # Around filters halt the request unless the action block is called.
223
222
  # Given these filters
@@ -242,9 +241,9 @@ module ActionController #:nodoc:
242
241
  # #after (actual filter code is run, unless the around filter does not yield)
243
242
  #
244
243
  # If #around returns before yielding, #after will still not be run. The #before
245
- # filter and controller action will not be run. If #before returns false,
244
+ # filter and controller action will not be run. If #before renders or redirects,
246
245
  # the second half of #around and will still run but #after and the
247
- # action will not. If #around does not yield, #after will not be run.
246
+ # action will not. If #around fails to yield, #after will not be run.
248
247
  module ClassMethods
249
248
  # The passed <tt>filters</tt> will be appended to the filter_chain and
250
249
  # will execute before the action on this controller is performed.
@@ -439,8 +438,9 @@ module ActionController #:nodoc:
439
438
 
440
439
  def run(controller)
441
440
  # only filters returning false are halted.
442
- if false == @filter.call(controller)
443
- controller.send :halt_filter_chain, @filter, :returned_false
441
+ @filter.call(controller)
442
+ if controller.send!(:performed?)
443
+ controller.send!(:halt_filter_chain, @filter, :rendered_or_redirected)
444
444
  end
445
445
  end
446
446
 
@@ -466,7 +466,7 @@ module ActionController #:nodoc:
466
466
 
467
467
  class SymbolFilter < Filter #:nodoc:
468
468
  def call(controller, &block)
469
- controller.send(@filter, &block)
469
+ controller.send!(@filter, &block)
470
470
  end
471
471
  end
472
472
 
@@ -601,7 +601,7 @@ module ActionController #:nodoc:
601
601
 
602
602
  def extract_conditions(*filters, &block) #:nodoc:
603
603
  filters.flatten!
604
- conditions = filters.last.is_a?(Hash) ? filters.pop : {}
604
+ conditions = filters.extract_options!
605
605
  filters << block if block_given?
606
606
  return filters, conditions
607
607
  end
@@ -655,8 +655,10 @@ module ActionController #:nodoc:
655
655
  def proxy_before_and_after_filter(filter) #:nodoc:
656
656
  return filter unless filter_responds_to_before_and_after(filter)
657
657
  Proc.new do |controller, action|
658
- if filter.before(controller) == false
659
- controller.send :halt_filter_chain, filter, :returned_false
658
+ filter.before(controller)
659
+
660
+ if controller.send!(:performed?)
661
+ controller.send!(:halt_filter_chain, filter, :rendered_or_redirected)
660
662
  else
661
663
  begin
662
664
  action.call
@@ -673,7 +675,6 @@ module ActionController #:nodoc:
673
675
  base.class_eval do
674
676
  alias_method_chain :perform_action, :filters
675
677
  alias_method_chain :process, :filters
676
- alias_method_chain :process_cleanup, :filters
677
678
  end
678
679
  end
679
680
 
@@ -709,6 +710,7 @@ module ActionController #:nodoc:
709
710
  while chain[index]
710
711
  filter, index = skip_excluded_filters(chain, index)
711
712
  break unless filter # end of call chain reached
713
+
712
714
  case filter.type
713
715
  when :before
714
716
  filter.run(self) # invoke before filter
@@ -716,25 +718,31 @@ module ActionController #:nodoc:
716
718
  break if @before_filter_chain_aborted
717
719
  when :around
718
720
  yielded = false
721
+
719
722
  filter.call(self) do
720
723
  yielded = true
721
724
  # all remaining before and around filters will be run in this call
722
725
  index = call_filters(chain, index.next, nesting.next)
723
726
  end
727
+
724
728
  halt_filter_chain(filter, :did_not_yield) unless yielded
729
+
725
730
  break
726
731
  else
727
732
  break # no before or around filters left
728
733
  end
729
734
  end
735
+
730
736
  index
731
737
  end
732
738
 
733
739
  def run_after_filters(chain, index)
734
740
  seen_after_filter = false
741
+
735
742
  while chain[index]
736
743
  filter, index = skip_excluded_filters(chain, index)
737
744
  break unless filter # end of call chain reached
745
+
738
746
  case filter.type
739
747
  when :after
740
748
  seen_after_filter = true
@@ -743,23 +751,16 @@ module ActionController #:nodoc:
743
751
  # implementation error or someone has mucked with the filter chain
744
752
  raise ActionControllerError, "filter #{filter.inspect} was in the wrong place!" if seen_after_filter
745
753
  end
754
+
746
755
  index = index.next
747
756
  end
757
+
748
758
  index.next
749
759
  end
750
760
 
751
761
  def halt_filter_chain(filter, reason)
752
762
  @before_filter_chain_aborted = true
753
763
  logger.info "Filter chain halted as [#{filter.inspect}] #{reason}." if logger
754
- false
755
- end
756
-
757
- def process_cleanup_with_filters
758
- if @before_filter_chain_aborted
759
- close_session
760
- else
761
- process_cleanup_without_filters
762
- end
763
764
  end
764
765
  end
765
766
  end
@@ -1,8 +1,8 @@
1
1
  module ActionController #:nodoc:
2
2
  # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed
3
- # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create action
4
- # that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can then expose
5
- # the flash to its template. Actually, that exposure is automatically done. Example:
3
+ # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
4
+ # action that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can
5
+ # then expose the flash to its template. Actually, that exposure is automatically done. Example:
6
6
  #
7
7
  # class WeblogController < ActionController::Base
8
8
  # def create
@@ -16,18 +16,17 @@ module ActionController #:nodoc:
16
16
  # end
17
17
  # end
18
18
  #
19
- # display.rhtml
19
+ # display.erb
20
20
  # <% if flash[:notice] %><div class="notice"><%= flash[:notice] %></div><% end %>
21
21
  #
22
- # This example just places a string in the flash, but you can put any object in there. And of course, you can put as many
23
- # as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
22
+ # This example just places a string in the flash, but you can put any object in there. And of course, you can put as
23
+ # many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
24
24
  #
25
25
  # See docs on the FlashHash class for more details about the flash.
26
26
  module Flash
27
27
  def self.included(base)
28
- base.send :include, InstanceMethods
29
-
30
28
  base.class_eval do
29
+ include InstanceMethods
31
30
  alias_method_chain :assign_shortcuts, :flash
32
31
  alias_method_chain :process_cleanup, :flash
33
32
  alias_method_chain :reset_session, :flash
@@ -63,7 +62,7 @@ module ActionController #:nodoc:
63
62
  end
64
63
 
65
64
  def update(h) #:nodoc:
66
- h.keys.each{ |k| discard(k) }
65
+ h.keys.each { |k| keep(k) }
67
66
  super
68
67
  end
69
68
 
@@ -85,7 +84,7 @@ module ActionController #:nodoc:
85
84
  #
86
85
  # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
87
86
  def now
88
- FlashNow.new self
87
+ FlashNow.new(self)
89
88
  end
90
89
 
91
90
  # Keeps either the entire current flash or a specific flash entry available for the next action:
@@ -96,10 +95,10 @@ module ActionController #:nodoc:
96
95
  use(k, false)
97
96
  end
98
97
 
99
- # Marks the entire flash or a single flash entry to be discarded by the end of the current action
98
+ # Marks the entire flash or a single flash entry to be discarded by the end of the current action:
100
99
  #
101
- # flash.keep # keep entire flash available for the next action
102
- # flash.discard(:warning) # discard the "warning" entry (it'll still be available for the current action)
100
+ # flash.discard # discard the entire flash at the end of the current action
101
+ # flash.discard(:warning) # discard only the "warning" entry at the end of the current action
103
102
  def discard(k = nil)
104
103
  use(k)
105
104
  end
@@ -117,7 +116,8 @@ module ActionController #:nodoc:
117
116
  end
118
117
  end
119
118
 
120
- (@used.keys - keys).each{|k| @used.delete k } # clean up after keys that could have been left over by calling reject! or shift on the flash
119
+ # clean up after keys that could have been left over by calling reject! or shift on the flash
120
+ (@used.keys - keys).each{ |k| @used.delete(k) }
121
121
  end
122
122
 
123
123
  private
@@ -130,29 +130,19 @@ module ActionController #:nodoc:
130
130
  unless k.nil?
131
131
  @used[k] = v
132
132
  else
133
- keys.each{|key| use key, v }
133
+ keys.each{ |key| use(key, v) }
134
134
  end
135
135
  end
136
136
  end
137
137
 
138
138
  module InstanceMethods #:nodoc:
139
- def assign_shortcuts_with_flash(request, response) #:nodoc:
140
- assign_shortcuts_without_flash(request, response)
141
- flash(:refresh)
142
- end
143
-
144
- def process_cleanup_with_flash
145
- flash.sweep if @_session
146
- process_cleanup_without_flash
147
- end
148
-
149
- def reset_session_with_flash
150
- reset_session_without_flash
151
- remove_instance_variable(:@_flash)
152
- flash(:refresh)
153
- end
139
+ protected
140
+ def reset_session_with_flash
141
+ reset_session_without_flash
142
+ remove_instance_variable(:@_flash)
143
+ flash(:refresh)
144
+ end
154
145
 
155
- protected
156
146
  # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
157
147
  # <tt>flash["notice"] = "hello"</tt> to put a new one.
158
148
  # Note that if sessions are disabled only flash.now will work.
@@ -172,10 +162,15 @@ module ActionController #:nodoc:
172
162
  @_flash
173
163
  end
174
164
 
175
- # deprecated. use <tt>flash.keep</tt> instead
176
- def keep_flash #:doc:
177
- ActiveSupport::Deprecation.warn 'keep_flash is deprecated; use flash.keep instead.', caller
178
- flash.keep
165
+ private
166
+ def assign_shortcuts_with_flash(request, response) #:nodoc:
167
+ assign_shortcuts_without_flash(request, response)
168
+ flash(:refresh)
169
+ end
170
+
171
+ def process_cleanup_with_flash
172
+ flash.sweep if @_session
173
+ process_cleanup_without_flash
179
174
  end
180
175
  end
181
176
  end