actionpack-rack-upgrade 2.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. data/CHANGELOG +5250 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +158 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller/assertions/dom_assertions.rb +55 -0
  8. data/lib/action_controller/assertions/model_assertions.rb +21 -0
  9. data/lib/action_controller/assertions/response_assertions.rb +169 -0
  10. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  11. data/lib/action_controller/assertions/selector_assertions.rb +638 -0
  12. data/lib/action_controller/assertions/tag_assertions.rb +127 -0
  13. data/lib/action_controller/base.rb +1425 -0
  14. data/lib/action_controller/benchmarking.rb +107 -0
  15. data/lib/action_controller/caching/actions.rb +177 -0
  16. data/lib/action_controller/caching/fragments.rb +120 -0
  17. data/lib/action_controller/caching/pages.rb +152 -0
  18. data/lib/action_controller/caching/sweeper.rb +45 -0
  19. data/lib/action_controller/caching/sweeping.rb +55 -0
  20. data/lib/action_controller/caching.rb +71 -0
  21. data/lib/action_controller/cgi_ext/cookie.rb +112 -0
  22. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  23. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  24. data/lib/action_controller/cgi_ext.rb +15 -0
  25. data/lib/action_controller/cgi_process.rb +77 -0
  26. data/lib/action_controller/cookies.rb +197 -0
  27. data/lib/action_controller/dispatcher.rb +133 -0
  28. data/lib/action_controller/failsafe.rb +87 -0
  29. data/lib/action_controller/filters.rb +680 -0
  30. data/lib/action_controller/flash.rb +213 -0
  31. data/lib/action_controller/headers.rb +33 -0
  32. data/lib/action_controller/helpers.rb +225 -0
  33. data/lib/action_controller/http_authentication.rb +309 -0
  34. data/lib/action_controller/integration.rb +708 -0
  35. data/lib/action_controller/layout.rb +286 -0
  36. data/lib/action_controller/middleware_stack.rb +119 -0
  37. data/lib/action_controller/middlewares.rb +14 -0
  38. data/lib/action_controller/mime_responds.rb +193 -0
  39. data/lib/action_controller/mime_type.rb +212 -0
  40. data/lib/action_controller/mime_types.rb +21 -0
  41. data/lib/action_controller/params_parser.rb +77 -0
  42. data/lib/action_controller/performance_test.rb +15 -0
  43. data/lib/action_controller/polymorphic_routes.rb +189 -0
  44. data/lib/action_controller/rack_lint_patch.rb +36 -0
  45. data/lib/action_controller/record_identifier.rb +104 -0
  46. data/lib/action_controller/reloader.rb +54 -0
  47. data/lib/action_controller/request.rb +495 -0
  48. data/lib/action_controller/request_forgery_protection.rb +116 -0
  49. data/lib/action_controller/rescue.rb +183 -0
  50. data/lib/action_controller/resources.rb +682 -0
  51. data/lib/action_controller/response.rb +237 -0
  52. data/lib/action_controller/routing/builder.rb +197 -0
  53. data/lib/action_controller/routing/optimisations.rb +130 -0
  54. data/lib/action_controller/routing/recognition_optimisation.rb +167 -0
  55. data/lib/action_controller/routing/route.rb +265 -0
  56. data/lib/action_controller/routing/route_set.rb +503 -0
  57. data/lib/action_controller/routing/routing_ext.rb +49 -0
  58. data/lib/action_controller/routing/segments.rb +343 -0
  59. data/lib/action_controller/routing.rb +388 -0
  60. data/lib/action_controller/session/abstract_store.rb +276 -0
  61. data/lib/action_controller/session/cookie_store.rb +240 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +60 -0
  63. data/lib/action_controller/session_management.rb +54 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +181 -0
  66. data/lib/action_controller/string_coercion.rb +29 -0
  67. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  68. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  69. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  70. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  71. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  72. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  73. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  74. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  75. data/lib/action_controller/test_case.rb +209 -0
  76. data/lib/action_controller/test_process.rb +580 -0
  77. data/lib/action_controller/translation.rb +13 -0
  78. data/lib/action_controller/uploaded_file.rb +44 -0
  79. data/lib/action_controller/url_rewriter.rb +229 -0
  80. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  81. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  82. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  83. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  84. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  85. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  86. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  87. data/lib/action_controller/verification.rb +130 -0
  88. data/lib/action_controller.rb +113 -0
  89. data/lib/action_pack/version.rb +9 -0
  90. data/lib/action_pack.rb +24 -0
  91. data/lib/action_view/base.rb +362 -0
  92. data/lib/action_view/helpers/active_record_helper.rb +305 -0
  93. data/lib/action_view/helpers/asset_tag_helper.rb +695 -0
  94. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  95. data/lib/action_view/helpers/benchmark_helper.rb +54 -0
  96. data/lib/action_view/helpers/cache_helper.rb +39 -0
  97. data/lib/action_view/helpers/capture_helper.rb +136 -0
  98. data/lib/action_view/helpers/csrf_helper.rb +14 -0
  99. data/lib/action_view/helpers/date_helper.rb +989 -0
  100. data/lib/action_view/helpers/debug_helper.rb +38 -0
  101. data/lib/action_view/helpers/form_helper.rb +1118 -0
  102. data/lib/action_view/helpers/form_options_helper.rb +599 -0
  103. data/lib/action_view/helpers/form_tag_helper.rb +490 -0
  104. data/lib/action_view/helpers/javascript_helper.rb +208 -0
  105. data/lib/action_view/helpers/number_helper.rb +308 -0
  106. data/lib/action_view/helpers/prototype_helper.rb +1305 -0
  107. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  108. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  109. data/lib/action_view/helpers/record_tag_helper.rb +58 -0
  110. data/lib/action_view/helpers/sanitize_helper.rb +251 -0
  111. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  112. data/lib/action_view/helpers/tag_helper.rb +151 -0
  113. data/lib/action_view/helpers/text_helper.rb +597 -0
  114. data/lib/action_view/helpers/translation_helper.rb +67 -0
  115. data/lib/action_view/helpers/url_helper.rb +637 -0
  116. data/lib/action_view/helpers.rb +61 -0
  117. data/lib/action_view/inline_template.rb +19 -0
  118. data/lib/action_view/locale/en.yml +117 -0
  119. data/lib/action_view/partials.rb +241 -0
  120. data/lib/action_view/paths.rb +77 -0
  121. data/lib/action_view/reloadable_template.rb +117 -0
  122. data/lib/action_view/renderable.rb +109 -0
  123. data/lib/action_view/renderable_partial.rb +53 -0
  124. data/lib/action_view/template.rb +252 -0
  125. data/lib/action_view/template_error.rb +99 -0
  126. data/lib/action_view/template_handler.rb +34 -0
  127. data/lib/action_view/template_handlers/builder.rb +17 -0
  128. data/lib/action_view/template_handlers/erb.rb +25 -0
  129. data/lib/action_view/template_handlers/rjs.rb +13 -0
  130. data/lib/action_view/template_handlers.rb +48 -0
  131. data/lib/action_view/test_case.rb +162 -0
  132. data/lib/action_view.rb +58 -0
  133. data/lib/actionpack.rb +2 -0
  134. data/test/abstract_unit.rb +78 -0
  135. data/test/active_record_unit.rb +104 -0
  136. data/test/activerecord/active_record_store_test.rb +221 -0
  137. data/test/activerecord/render_partial_with_record_identification_test.rb +188 -0
  138. data/test/adv_attr_test.rb +20 -0
  139. data/test/controller/action_pack_assertions_test.rb +545 -0
  140. data/test/controller/addresses_render_test.rb +37 -0
  141. data/test/controller/assert_select_test.rb +735 -0
  142. data/test/controller/base_test.rb +217 -0
  143. data/test/controller/benchmark_test.rb +32 -0
  144. data/test/controller/caching_test.rb +743 -0
  145. data/test/controller/capture_test.rb +66 -0
  146. data/test/controller/content_type_test.rb +178 -0
  147. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  148. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  149. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  150. data/test/controller/cookie_test.rb +208 -0
  151. data/test/controller/deprecation/deprecated_base_methods_test.rb +32 -0
  152. data/test/controller/dispatcher_test.rb +144 -0
  153. data/test/controller/dom_assertions_test.rb +53 -0
  154. data/test/controller/failsafe_test.rb +60 -0
  155. data/test/controller/fake_controllers.rb +33 -0
  156. data/test/controller/fake_models.rb +19 -0
  157. data/test/controller/filter_params_test.rb +52 -0
  158. data/test/controller/filters_test.rb +885 -0
  159. data/test/controller/flash_test.rb +174 -0
  160. data/test/controller/header_test.rb +14 -0
  161. data/test/controller/helper_test.rb +224 -0
  162. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  163. data/test/controller/html-scanner/document_test.rb +148 -0
  164. data/test/controller/html-scanner/node_test.rb +89 -0
  165. data/test/controller/html-scanner/sanitizer_test.rb +281 -0
  166. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  167. data/test/controller/html-scanner/text_node_test.rb +50 -0
  168. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  169. data/test/controller/http_basic_authentication_test.rb +113 -0
  170. data/test/controller/http_digest_authentication_test.rb +254 -0
  171. data/test/controller/integration_test.rb +526 -0
  172. data/test/controller/layout_test.rb +215 -0
  173. data/test/controller/localized_templates_test.rb +24 -0
  174. data/test/controller/logging_test.rb +46 -0
  175. data/test/controller/middleware_stack_test.rb +90 -0
  176. data/test/controller/mime_responds_test.rb +536 -0
  177. data/test/controller/mime_type_test.rb +93 -0
  178. data/test/controller/output_escaping_test.rb +19 -0
  179. data/test/controller/polymorphic_routes_test.rb +297 -0
  180. data/test/controller/rack_test.rb +308 -0
  181. data/test/controller/record_identifier_test.rb +139 -0
  182. data/test/controller/redirect_test.rb +285 -0
  183. data/test/controller/reloader_test.rb +125 -0
  184. data/test/controller/render_test.rb +1783 -0
  185. data/test/controller/request/json_params_parsing_test.rb +65 -0
  186. data/test/controller/request/multipart_params_parsing_test.rb +177 -0
  187. data/test/controller/request/query_string_parsing_test.rb +120 -0
  188. data/test/controller/request/test_request_test.rb +35 -0
  189. data/test/controller/request/url_encoded_params_parsing_test.rb +146 -0
  190. data/test/controller/request/xml_params_parsing_test.rb +103 -0
  191. data/test/controller/request_forgery_protection_test.rb +233 -0
  192. data/test/controller/request_test.rb +395 -0
  193. data/test/controller/rescue_test.rb +541 -0
  194. data/test/controller/resources_test.rb +1393 -0
  195. data/test/controller/routing_test.rb +2592 -0
  196. data/test/controller/selector_test.rb +628 -0
  197. data/test/controller/send_file_test.rb +171 -0
  198. data/test/controller/session/abstract_store_test.rb +64 -0
  199. data/test/controller/session/cookie_store_test.rb +354 -0
  200. data/test/controller/session/mem_cache_store_test.rb +187 -0
  201. data/test/controller/session/test_session_test.rb +58 -0
  202. data/test/controller/test_test.rb +700 -0
  203. data/test/controller/translation_test.rb +26 -0
  204. data/test/controller/url_rewriter_test.rb +395 -0
  205. data/test/controller/verification_test.rb +270 -0
  206. data/test/controller/view_paths_test.rb +141 -0
  207. data/test/controller/webservice_test.rb +260 -0
  208. data/test/fixtures/_top_level_partial.html.erb +1 -0
  209. data/test/fixtures/_top_level_partial_only.erb +1 -0
  210. data/test/fixtures/addresses/list.erb +1 -0
  211. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  212. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  213. data/test/fixtures/companies.yml +24 -0
  214. data/test/fixtures/company.rb +10 -0
  215. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  216. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  217. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  218. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  219. data/test/fixtures/customers/_customer.html.erb +1 -0
  220. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  221. data/test/fixtures/developer.rb +9 -0
  222. data/test/fixtures/developers/_developer.erb +1 -0
  223. data/test/fixtures/developers.yml +21 -0
  224. data/test/fixtures/developers_projects.yml +13 -0
  225. data/test/fixtures/failsafe/500.html +1 -0
  226. data/test/fixtures/fun/games/_game.erb +1 -0
  227. data/test/fixtures/fun/games/hello_world.erb +1 -0
  228. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  229. data/test/fixtures/functional_caching/_partial.erb +3 -0
  230. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  231. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  232. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  233. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  234. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  235. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  236. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  237. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  238. data/test/fixtures/helpers/abc_helper.rb +5 -0
  239. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  240. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  241. data/test/fixtures/layout_tests/abs_path_layout.rhtml +1 -0
  242. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  243. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  244. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  245. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  246. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  247. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  248. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  249. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  250. data/test/fixtures/layouts/_column.html.erb +2 -0
  251. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  252. data/test/fixtures/layouts/builder.builder +3 -0
  253. data/test/fixtures/layouts/default_html.html.erb +1 -0
  254. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  255. data/test/fixtures/layouts/standard.erb +1 -0
  256. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  257. data/test/fixtures/layouts/xhr.html.erb +2 -0
  258. data/test/fixtures/layouts/yield.erb +2 -0
  259. data/test/fixtures/localized/hello_world.de.html +1 -0
  260. data/test/fixtures/localized/hello_world.en.html +1 -0
  261. data/test/fixtures/mascot.rb +3 -0
  262. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  263. data/test/fixtures/mascots.yml +4 -0
  264. data/test/fixtures/multipart/binary_file +0 -0
  265. data/test/fixtures/multipart/boundary_problem_file +10 -0
  266. data/test/fixtures/multipart/bracketed_param +5 -0
  267. data/test/fixtures/multipart/empty +10 -0
  268. data/test/fixtures/multipart/hello.txt +1 -0
  269. data/test/fixtures/multipart/large_text_file +10 -0
  270. data/test/fixtures/multipart/mixed_files +0 -0
  271. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  272. data/test/fixtures/multipart/none +9 -0
  273. data/test/fixtures/multipart/single_parameter +5 -0
  274. data/test/fixtures/multipart/text_file +10 -0
  275. data/test/fixtures/override/test/hello_world.erb +1 -0
  276. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  277. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  278. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  279. data/test/fixtures/post_test/post/index.html.erb +1 -0
  280. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  281. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  282. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  283. data/test/fixtures/project.rb +3 -0
  284. data/test/fixtures/projects/_project.erb +1 -0
  285. data/test/fixtures/projects.yml +7 -0
  286. data/test/fixtures/public/404.html +1 -0
  287. data/test/fixtures/public/500.da.html +1 -0
  288. data/test/fixtures/public/500.html +1 -0
  289. data/test/fixtures/public/absolute/test.css +23 -0
  290. data/test/fixtures/public/absolute/test.js +63 -0
  291. data/test/fixtures/public/images/rails.png +0 -0
  292. data/test/fixtures/public/javascripts/application.js +1 -0
  293. data/test/fixtures/public/javascripts/bank.js +1 -0
  294. data/test/fixtures/public/javascripts/controls.js +1 -0
  295. data/test/fixtures/public/javascripts/dragdrop.js +1 -0
  296. data/test/fixtures/public/javascripts/effects.js +1 -0
  297. data/test/fixtures/public/javascripts/prototype.js +1 -0
  298. data/test/fixtures/public/javascripts/robber.js +1 -0
  299. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  300. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  301. data/test/fixtures/public/stylesheets/bank.css +1 -0
  302. data/test/fixtures/public/stylesheets/robber.css +1 -0
  303. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  304. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  305. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  306. data/test/fixtures/replies/_reply.erb +1 -0
  307. data/test/fixtures/replies.yml +15 -0
  308. data/test/fixtures/reply.rb +7 -0
  309. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  310. data/test/fixtures/respond_to/all_types_with_layout.js.rjs +1 -0
  311. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  312. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  313. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  314. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  315. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  316. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  317. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  318. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  319. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  320. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  321. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  322. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  323. data/test/fixtures/scope/test/modgreet.erb +1 -0
  324. data/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +10 -0
  325. data/test/fixtures/shared.html.erb +1 -0
  326. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  327. data/test/fixtures/test/_counter.html.erb +1 -0
  328. data/test/fixtures/test/_customer.erb +1 -0
  329. data/test/fixtures/test/_customer_counter.erb +1 -0
  330. data/test/fixtures/test/_customer_counter_with_as.erb +1 -0
  331. data/test/fixtures/test/_customer_greeting.erb +1 -0
  332. data/test/fixtures/test/_customer_with_var.erb +1 -0
  333. data/test/fixtures/test/_form.erb +1 -0
  334. data/test/fixtures/test/_from_helper.erb +1 -0
  335. data/test/fixtures/test/_hash_greeting.erb +1 -0
  336. data/test/fixtures/test/_hash_object.erb +2 -0
  337. data/test/fixtures/test/_hello.builder +1 -0
  338. data/test/fixtures/test/_labelling_form.erb +1 -0
  339. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  340. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  341. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  342. data/test/fixtures/test/_one.html.erb +1 -0
  343. data/test/fixtures/test/_partial.erb +1 -0
  344. data/test/fixtures/test/_partial.html.erb +1 -0
  345. data/test/fixtures/test/_partial.js.erb +1 -0
  346. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  347. data/test/fixtures/test/_partial_only.erb +1 -0
  348. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  349. data/test/fixtures/test/_person.erb +2 -0
  350. data/test/fixtures/test/_raise.html.erb +1 -0
  351. data/test/fixtures/test/_two.html.erb +1 -0
  352. data/test/fixtures/test/_utf8_partial.html.erb +1 -0
  353. data/test/fixtures/test/_utf8_partial_magic.html.erb +2 -0
  354. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  355. data/test/fixtures/test/array_translation.erb +1 -0
  356. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  357. data/test/fixtures/test/capturing.erb +4 -0
  358. data/test/fixtures/test/content_for.erb +2 -0
  359. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  360. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  361. data/test/fixtures/test/delete_with_js.rjs +2 -0
  362. data/test/fixtures/test/dont_pick_me +1 -0
  363. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  364. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  365. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  366. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  367. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  368. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  369. data/test/fixtures/test/greeting.erb +1 -0
  370. data/test/fixtures/test/greeting.js.rjs +1 -0
  371. data/test/fixtures/test/hello.builder +4 -0
  372. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  373. data/test/fixtures/test/hello_world.erb +1 -0
  374. data/test/fixtures/test/hello_world.erb~ +1 -0
  375. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  376. data/test/fixtures/test/hello_world_container.builder +3 -0
  377. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  378. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  379. data/test/fixtures/test/hello_xml_world.builder +11 -0
  380. data/test/fixtures/test/hyphen-ated.erb +1 -0
  381. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  382. data/test/fixtures/test/list.erb +1 -0
  383. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  384. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  385. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  386. data/test/fixtures/test/nested_layout.erb +3 -0
  387. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  388. data/test/fixtures/test/potential_conflicts.erb +4 -0
  389. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  390. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  391. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  392. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  393. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  394. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  395. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  396. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  397. data/test/fixtures/test/render_to_string_test.erb +1 -0
  398. data/test/fixtures/test/scoped_array_translation.erb +1 -0
  399. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  400. data/test/fixtures/test/template.erb +1 -0
  401. data/test/fixtures/test/translation.erb +1 -0
  402. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  403. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  404. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  405. data/test/fixtures/test/utf8.html.erb +4 -0
  406. data/test/fixtures/test/utf8_magic.html.erb +5 -0
  407. data/test/fixtures/test/utf8_magic_with_bare_partial.html.erb +5 -0
  408. data/test/fixtures/topic.rb +3 -0
  409. data/test/fixtures/topics/_topic.html.erb +1 -0
  410. data/test/fixtures/topics.yml +22 -0
  411. data/test/template/active_record_helper_i18n_test.rb +51 -0
  412. data/test/template/active_record_helper_test.rb +302 -0
  413. data/test/template/asset_tag_helper_test.rb +770 -0
  414. data/test/template/atom_feed_helper_test.rb +315 -0
  415. data/test/template/benchmark_helper_test.rb +86 -0
  416. data/test/template/compiled_templates_test.rb +204 -0
  417. data/test/template/date_helper_i18n_test.rb +121 -0
  418. data/test/template/date_helper_test.rb +2603 -0
  419. data/test/template/erb_util_test.rb +36 -0
  420. data/test/template/form_helper_test.rb +1447 -0
  421. data/test/template/form_options_helper_i18n_test.rb +27 -0
  422. data/test/template/form_options_helper_test.rb +811 -0
  423. data/test/template/form_tag_helper_test.rb +356 -0
  424. data/test/template/javascript_helper_test.rb +106 -0
  425. data/test/template/number_helper_i18n_test.rb +69 -0
  426. data/test/template/number_helper_test.rb +132 -0
  427. data/test/template/prototype_helper_test.rb +639 -0
  428. data/test/template/raw_output_helper_test.rb +21 -0
  429. data/test/template/record_tag_helper_test.rb +58 -0
  430. data/test/template/render_test.rb +329 -0
  431. data/test/template/sanitize_helper_test.rb +57 -0
  432. data/test/template/scriptaculous_helper_test.rb +90 -0
  433. data/test/template/tag_helper_test.rb +98 -0
  434. data/test/template/template_test.rb +32 -0
  435. data/test/template/test_test.rb +54 -0
  436. data/test/template/text_helper_test.rb +597 -0
  437. data/test/template/translation_helper_test.rb +95 -0
  438. data/test/template/url_helper_test.rb +641 -0
  439. data/test/testing_sandbox.rb +15 -0
  440. data/test/view/test_case_test.rb +176 -0
  441. metadata +519 -0
@@ -0,0 +1,388 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'action_controller/routing/optimisations'
4
+ require 'action_controller/routing/routing_ext'
5
+ require 'action_controller/routing/route'
6
+ require 'action_controller/routing/segments'
7
+ require 'action_controller/routing/builder'
8
+ require 'action_controller/routing/route_set'
9
+ require 'action_controller/routing/recognition_optimisation'
10
+
11
+ module ActionController
12
+ # == Routing
13
+ #
14
+ # The routing module provides URL rewriting in native Ruby. It's a way to
15
+ # redirect incoming requests to controllers and actions. This replaces
16
+ # mod_rewrite rules. Best of all, Rails' Routing works with any web server.
17
+ # Routes are defined in <tt>config/routes.rb</tt>.
18
+ #
19
+ # Consider the following route, installed by Rails when you generate your
20
+ # application:
21
+ #
22
+ # map.connect ':controller/:action/:id'
23
+ #
24
+ # This route states that it expects requests to consist of a
25
+ # <tt>:controller</tt> followed by an <tt>:action</tt> that in turn is fed
26
+ # some <tt>:id</tt>.
27
+ #
28
+ # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end up
29
+ # with:
30
+ #
31
+ # params = { :controller => 'blog',
32
+ # :action => 'edit',
33
+ # :id => '22'
34
+ # }
35
+ #
36
+ # Think of creating routes as drawing a map for your requests. The map tells
37
+ # them where to go based on some predefined pattern:
38
+ #
39
+ # ActionController::Routing::Routes.draw do |map|
40
+ # Pattern 1 tells some request to go to one place
41
+ # Pattern 2 tell them to go to another
42
+ # ...
43
+ # end
44
+ #
45
+ # The following symbols are special:
46
+ #
47
+ # :controller maps to your controller name
48
+ # :action maps to an action with your controllers
49
+ #
50
+ # Other names simply map to a parameter as in the case of <tt>:id</tt>.
51
+ #
52
+ # == Route priority
53
+ #
54
+ # Not all routes are created equally. Routes have priority defined by the
55
+ # order of appearance of the routes in the <tt>config/routes.rb</tt> file. The priority goes
56
+ # from top to bottom. The last route in that file is at the lowest priority
57
+ # and will be applied last. If no route matches, 404 is returned.
58
+ #
59
+ # Within blocks, the empty pattern is at the highest priority.
60
+ # In practice this works out nicely:
61
+ #
62
+ # ActionController::Routing::Routes.draw do |map|
63
+ # map.with_options :controller => 'blog' do |blog|
64
+ # blog.show '', :action => 'list'
65
+ # end
66
+ # map.connect ':controller/:action/:view'
67
+ # end
68
+ #
69
+ # In this case, invoking blog controller (with an URL like '/blog/')
70
+ # without parameters will activate the 'list' action by default.
71
+ #
72
+ # == Defaults routes and default parameters
73
+ #
74
+ # Setting a default route is straightforward in Rails - you simply append a
75
+ # Hash at the end of your mapping to set any default parameters.
76
+ #
77
+ # Example:
78
+ #
79
+ # ActionController::Routing:Routes.draw do |map|
80
+ # map.connect ':controller/:action/:id', :controller => 'blog'
81
+ # end
82
+ #
83
+ # This sets up +blog+ as the default controller if no other is specified.
84
+ # This means visiting '/' would invoke the blog controller.
85
+ #
86
+ # More formally, you can include arbitrary parameters in the route, thus:
87
+ #
88
+ # map.connect ':controller/:action/:id', :action => 'show', :page => 'Dashboard'
89
+ #
90
+ # This will pass the :page parameter to all incoming requests that match this route.
91
+ #
92
+ # Note: The default routes, as provided by the Rails generator, make all actions in every
93
+ # controller accessible via GET requests. You should consider removing them or commenting
94
+ # them out if you're using named routes and resources.
95
+ #
96
+ # == Named routes
97
+ #
98
+ # Routes can be named with the syntax <tt>map.name_of_route options</tt>,
99
+ # allowing for easy reference within your source as +name_of_route_url+
100
+ # for the full URL and +name_of_route_path+ for the URI path.
101
+ #
102
+ # Example:
103
+ #
104
+ # # In routes.rb
105
+ # map.login 'login', :controller => 'accounts', :action => 'login'
106
+ #
107
+ # # With render, redirect_to, tests, etc.
108
+ # redirect_to login_url
109
+ #
110
+ # Arguments can be passed as well.
111
+ #
112
+ # redirect_to show_item_path(:id => 25)
113
+ #
114
+ # Use <tt>map.root</tt> as a shorthand to name a route for the root path "".
115
+ #
116
+ # # In routes.rb
117
+ # map.root :controller => 'blogs'
118
+ #
119
+ # # would recognize http://www.example.com/ as
120
+ # params = { :controller => 'blogs', :action => 'index' }
121
+ #
122
+ # # and provide these named routes
123
+ # root_url # => 'http://www.example.com/'
124
+ # root_path # => ''
125
+ #
126
+ # You can also specify an already-defined named route in your <tt>map.root</tt> call:
127
+ #
128
+ # # In routes.rb
129
+ # map.new_session :controller => 'sessions', :action => 'new'
130
+ # map.root :new_session
131
+ #
132
+ # Note: when using +with_options+, the route is simply named after the
133
+ # method you call on the block parameter rather than map.
134
+ #
135
+ # # In routes.rb
136
+ # map.with_options :controller => 'blog' do |blog|
137
+ # blog.show '', :action => 'list'
138
+ # blog.delete 'delete/:id', :action => 'delete',
139
+ # blog.edit 'edit/:id', :action => 'edit'
140
+ # end
141
+ #
142
+ # # provides named routes for show, delete, and edit
143
+ # link_to @article.title, show_path(:id => @article.id)
144
+ #
145
+ # == Pretty URLs
146
+ #
147
+ # Routes can generate pretty URLs. For example:
148
+ #
149
+ # map.connect 'articles/:year/:month/:day',
150
+ # :controller => 'articles',
151
+ # :action => 'find_by_date',
152
+ # :year => /\d{4}/,
153
+ # :month => /\d{1,2}/,
154
+ # :day => /\d{1,2}/
155
+ #
156
+ # Using the route above, the URL "http://localhost:3000/articles/2005/11/06"
157
+ # maps to
158
+ #
159
+ # params = {:year => '2005', :month => '11', :day => '06'}
160
+ #
161
+ # == Regular Expressions and parameters
162
+ # You can specify a regular expression to define a format for a parameter.
163
+ #
164
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
165
+ # :action => 'show', :postalcode => /\d{5}(-\d{4})?/
166
+ #
167
+ # or, more formally:
168
+ #
169
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
170
+ # :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
171
+ #
172
+ # Formats can include the 'ignorecase' and 'extended syntax' regular
173
+ # expression modifiers:
174
+ #
175
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
176
+ # :action => 'show', :postalcode => /hx\d\d\s\d[a-z]{2}/i
177
+ #
178
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
179
+ # :action => 'show',:requirements => {
180
+ # :postalcode => /# Postcode format
181
+ # \d{5} #Prefix
182
+ # (-\d{4})? #Suffix
183
+ # /x
184
+ # }
185
+ #
186
+ # Using the multiline match modifier will raise an ArgumentError.
187
+ # Encoding regular expression modifiers are silently ignored. The
188
+ # match will always use the default encoding or ASCII.
189
+ #
190
+ # == Route globbing
191
+ #
192
+ # Specifying <tt>*[string]</tt> as part of a rule like:
193
+ #
194
+ # map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
195
+ #
196
+ # will glob all remaining parts of the route that were not recognized earlier.
197
+ # The globbed values are in <tt>params[:path]</tt> as an array of path segments.
198
+ #
199
+ # == Route conditions
200
+ #
201
+ # With conditions you can define restrictions on routes. Currently the only valid condition is <tt>:method</tt>.
202
+ #
203
+ # * <tt>:method</tt> - Allows you to specify which method can access the route. Possible values are <tt>:post</tt>,
204
+ # <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>. The default value is <tt>:any</tt>,
205
+ # <tt>:any</tt> means that any method can access the route.
206
+ #
207
+ # Example:
208
+ #
209
+ # map.connect 'post/:id', :controller => 'posts', :action => 'show',
210
+ # :conditions => { :method => :get }
211
+ # map.connect 'post/:id', :controller => 'posts', :action => 'create_comment',
212
+ # :conditions => { :method => :post }
213
+ #
214
+ # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
215
+ # URL will route to the <tt>show</tt> action.
216
+ #
217
+ # == Reloading routes
218
+ #
219
+ # You can reload routes if you feel you must:
220
+ #
221
+ # ActionController::Routing::Routes.reload
222
+ #
223
+ # This will clear all named routes and reload routes.rb if the file has been modified from
224
+ # last load. To absolutely force reloading, use <tt>reload!</tt>.
225
+ #
226
+ # == Testing Routes
227
+ #
228
+ # The two main methods for testing your routes:
229
+ #
230
+ # === +assert_routing+
231
+ #
232
+ # def test_movie_route_properly_splits
233
+ # opts = {:controller => "plugin", :action => "checkout", :id => "2"}
234
+ # assert_routing "plugin/checkout/2", opts
235
+ # end
236
+ #
237
+ # +assert_routing+ lets you test whether or not the route properly resolves into options.
238
+ #
239
+ # === +assert_recognizes+
240
+ #
241
+ # def test_route_has_options
242
+ # opts = {:controller => "plugin", :action => "show", :id => "12"}
243
+ # assert_recognizes opts, "/plugins/show/12"
244
+ # end
245
+ #
246
+ # Note the subtle difference between the two: +assert_routing+ tests that
247
+ # a URL fits options while +assert_recognizes+ tests that a URL
248
+ # breaks into parameters properly.
249
+ #
250
+ # In tests you can simply pass the URL or named route to +get+ or +post+.
251
+ #
252
+ # def send_to_jail
253
+ # get '/jail'
254
+ # assert_response :success
255
+ # assert_template "jail/front"
256
+ # end
257
+ #
258
+ # def goes_to_login
259
+ # get login_url
260
+ # #...
261
+ # end
262
+ #
263
+ # == View a list of all your routes
264
+ #
265
+ # Run <tt>rake routes</tt>.
266
+ #
267
+ module Routing
268
+ SEPARATORS = %w( / . ? )
269
+
270
+ HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]
271
+
272
+ ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set
273
+
274
+ mattr_accessor :generate_best_match
275
+ self.generate_best_match = true
276
+
277
+ # The root paths which may contain controller files
278
+ mattr_accessor :controller_paths
279
+ self.controller_paths = []
280
+
281
+ # A helper module to hold URL related helpers.
282
+ module Helpers
283
+ include PolymorphicRoutes
284
+ end
285
+
286
+ class << self
287
+ # Expects an array of controller names as the first argument.
288
+ # Executes the passed block with only the named controllers named available.
289
+ # This method is used in internal Rails testing.
290
+ def with_controllers(names)
291
+ prior_controllers = @possible_controllers
292
+ use_controllers! names
293
+ yield
294
+ ensure
295
+ use_controllers! prior_controllers
296
+ end
297
+
298
+ # Returns an array of paths, cleaned of double-slashes and relative path references.
299
+ # * "\\\" and "//" become "\\" or "/".
300
+ # * "/foo/bar/../config" becomes "/foo/config".
301
+ # The returned array is sorted by length, descending.
302
+ def normalize_paths(paths)
303
+ # do the hokey-pokey of path normalization...
304
+ paths = paths.collect do |path|
305
+ path = path.
306
+ gsub("//", "/"). # replace double / chars with a single
307
+ gsub("\\\\", "\\"). # replace double \ chars with a single
308
+ gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
309
+
310
+ # eliminate .. paths where possible
311
+ re = %r{[^/\\]+[/\\]\.\.[/\\]}
312
+ path.gsub!(re, "") while path.match(re)
313
+ path
314
+ end
315
+
316
+ # start with longest path, first
317
+ paths = paths.uniq.sort_by { |path| - path.length }
318
+ end
319
+
320
+ # Returns the array of controller names currently available to ActionController::Routing.
321
+ def possible_controllers
322
+ unless @possible_controllers
323
+ @possible_controllers = []
324
+
325
+ paths = controller_paths.select { |path| File.directory?(path) && path != "." }
326
+
327
+ seen_paths = Hash.new {|h, k| h[k] = true; false}
328
+ normalize_paths(paths).each do |load_path|
329
+ Dir["#{load_path}/**/*_controller.rb"].collect do |path|
330
+ next if seen_paths[path.gsub(%r{^\.[/\\]}, "")]
331
+
332
+ controller_name = path[(load_path.length + 1)..-1]
333
+
334
+ controller_name.gsub!(/_controller\.rb\Z/, '')
335
+ @possible_controllers << controller_name
336
+ end
337
+ end
338
+
339
+ # remove duplicates
340
+ @possible_controllers.uniq!
341
+ end
342
+ @possible_controllers
343
+ end
344
+
345
+ # Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
346
+ # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
347
+ def use_controllers!(controller_names)
348
+ @possible_controllers = controller_names
349
+ end
350
+
351
+ # Returns a controller path for a new +controller+ based on a +previous+ controller path.
352
+ # Handles 4 scenarios:
353
+ #
354
+ # * stay in the previous controller:
355
+ # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
356
+ #
357
+ # * stay in the previous namespace:
358
+ # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
359
+ #
360
+ # * forced move to the root namespace:
361
+ # controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
362
+ #
363
+ # * previous namespace is root:
364
+ # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
365
+ #
366
+ def controller_relative_to(controller, previous)
367
+ if controller.nil? then previous
368
+ elsif controller[0] == ?/ then controller[1..-1]
369
+ elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
370
+ else controller
371
+ end
372
+ end
373
+ end
374
+
375
+ Routes = RouteSet.new
376
+
377
+ ActiveSupport::Inflector.module_eval do
378
+ # Ensures that routes are reloaded when Rails inflections are updated.
379
+ def inflections_with_route_reloading(&block)
380
+ (inflections_without_route_reloading(&block)).tap {
381
+ ActionController::Routing::Routes.reload! if block_given?
382
+ }
383
+ end
384
+
385
+ alias_method_chain :inflections, :route_reloading
386
+ end
387
+ end
388
+ end
@@ -0,0 +1,276 @@
1
+ require 'rack/utils'
2
+
3
+ module ActionController
4
+ module Session
5
+ class AbstractStore
6
+ ENV_SESSION_KEY = 'rack.session'.freeze
7
+ ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
8
+
9
+ HTTP_COOKIE = 'HTTP_COOKIE'.freeze
10
+ SET_COOKIE = 'Set-Cookie'.freeze
11
+
12
+ # thin wrapper around Hash that allows us to lazily
13
+ # load session id into session_options
14
+ class OptionsHash < Hash
15
+ def initialize(by, env, default_options)
16
+ @by = by
17
+ @env = env
18
+ @session_id_loaded = false
19
+ merge!(default_options)
20
+ end
21
+
22
+ def [](key)
23
+ if key == :id
24
+ load_session_id! unless super(:id) || has_session_id?
25
+ end
26
+ super(key)
27
+ end
28
+
29
+ private
30
+
31
+ def has_session_id?
32
+ @session_id_loaded
33
+ end
34
+
35
+ def load_session_id!
36
+ self[:id] = @by.send(:extract_session_id, @env)
37
+ @session_id_loaded = true
38
+ end
39
+ end
40
+
41
+ class SessionHash < Hash
42
+ def initialize(by, env)
43
+ super()
44
+ @by = by
45
+ @env = env
46
+ @loaded = false
47
+ end
48
+
49
+ def session_id
50
+ ActiveSupport::Deprecation.warn(
51
+ "ActionController::Session::AbstractStore::SessionHash#session_id " +
52
+ "has been deprecated. Please use request.session_options[:id] instead.", caller)
53
+ @env[ENV_SESSION_OPTIONS_KEY][:id]
54
+ end
55
+
56
+ def [](key)
57
+ load_for_read!
58
+ super
59
+ end
60
+
61
+ def has_key?(key)
62
+ load_for_read!
63
+ super
64
+ end
65
+
66
+ def []=(key, value)
67
+ load_for_write!
68
+ super
69
+ end
70
+
71
+ def clear
72
+ load_for_write!
73
+ super
74
+ end
75
+
76
+ def to_hash
77
+ load_for_read!
78
+ h = {}.replace(self)
79
+ h.delete_if { |k,v| v.nil? }
80
+ h
81
+ end
82
+
83
+ def update(hash)
84
+ load_for_write!
85
+ super
86
+ end
87
+
88
+ def delete(key)
89
+ load_for_write!
90
+ super
91
+ end
92
+
93
+ def data
94
+ ActiveSupport::Deprecation.warn(
95
+ "ActionController::Session::AbstractStore::SessionHash#data " +
96
+ "has been deprecated. Please use #to_hash instead.", caller)
97
+ to_hash
98
+ end
99
+
100
+ def inspect
101
+ load_for_read!
102
+ super
103
+ end
104
+
105
+ def exists?
106
+ return @exists if instance_variable_defined?(:@exists)
107
+ @exists = @by.send(:exists?, @env)
108
+ end
109
+
110
+ def loaded?
111
+ @loaded
112
+ end
113
+
114
+ def destroy
115
+ clear
116
+ @by.send(:destroy, @env) if @by
117
+ @env[ENV_SESSION_OPTIONS_KEY][:id] = nil if @env && @env[ENV_SESSION_OPTIONS_KEY]
118
+ @loaded = false
119
+ end
120
+
121
+ private
122
+
123
+ def load_for_read!
124
+ load! if !loaded? && exists?
125
+ end
126
+
127
+ def load_for_write!
128
+ load! unless loaded?
129
+ end
130
+
131
+ def load!
132
+ id, session = @by.send(:load_session, @env)
133
+ @env[ENV_SESSION_OPTIONS_KEY][:id] = id
134
+ replace(session)
135
+ @loaded = true
136
+ end
137
+
138
+ end
139
+
140
+ DEFAULT_OPTIONS = {
141
+ :key => '_session_id',
142
+ :path => '/',
143
+ :domain => nil,
144
+ :expire_after => nil,
145
+ :secure => false,
146
+ :httponly => true,
147
+ :cookie_only => true
148
+ }
149
+
150
+ def initialize(app, options = {})
151
+ # Process legacy CGI options
152
+ options = options.symbolize_keys
153
+ if options.has_key?(:session_path)
154
+ ActiveSupport::Deprecation.warn "Giving :session_path to SessionStore is deprecated, " <<
155
+ "please use :path instead", caller
156
+ options[:path] = options.delete(:session_path)
157
+ end
158
+ if options.has_key?(:session_key)
159
+ ActiveSupport::Deprecation.warn "Giving :session_key to SessionStore is deprecated, " <<
160
+ "please use :key instead", caller
161
+ options[:key] = options.delete(:session_key)
162
+ end
163
+ if options.has_key?(:session_http_only)
164
+ ActiveSupport::Deprecation.warn "Giving :session_http_only to SessionStore is deprecated, " <<
165
+ "please use :httponly instead", caller
166
+ options[:httponly] = options.delete(:session_http_only)
167
+ end
168
+
169
+ @app = app
170
+ @default_options = DEFAULT_OPTIONS.merge(options)
171
+ @key = @default_options[:key]
172
+ @cookie_only = @default_options[:cookie_only]
173
+ end
174
+
175
+ def call(env)
176
+ prepare!(env)
177
+ response = @app.call(env)
178
+
179
+ session_data = env[ENV_SESSION_KEY]
180
+ options = env[ENV_SESSION_OPTIONS_KEY]
181
+
182
+ if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]
183
+ request = ActionController::Request.new(env)
184
+
185
+ return response if (options[:secure] && !request.ssl?)
186
+
187
+ session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
188
+
189
+ sid = options[:id] || generate_sid
190
+
191
+ unless set_session(env, sid, session_data.to_hash)
192
+ return response
193
+ end
194
+
195
+ request_cookies = env["rack.request.cookie_hash"]
196
+
197
+ if (request_cookies.nil? || request_cookies[@key] != sid) || options[:expire_after]
198
+ cookie = {:value => sid}
199
+ cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
200
+ Rack::Utils.set_cookie_header!(response[1], @key, cookie.merge(options))
201
+ end
202
+ end
203
+
204
+ response
205
+ end
206
+
207
+ private
208
+
209
+ def prepare!(env)
210
+ env[ENV_SESSION_KEY] = SessionHash.new(self, env)
211
+ env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
212
+ end
213
+
214
+ def generate_sid
215
+ ActiveSupport::SecureRandom.hex(16)
216
+ end
217
+
218
+ def load_session(env)
219
+ stale_session_check! do
220
+ sid = current_session_id(env)
221
+ sid, session = get_session(env, sid)
222
+ [sid, session]
223
+ end
224
+ end
225
+
226
+ def extract_session_id(env)
227
+ stale_session_check! do
228
+ request = Rack::Request.new(env)
229
+ sid = request.cookies[@key]
230
+ sid ||= request.params[@key] unless @cookie_only
231
+ sid
232
+ end
233
+ end
234
+
235
+ def current_session_id(env)
236
+ env[ENV_SESSION_OPTIONS_KEY][:id]
237
+ end
238
+
239
+ def exists?(env)
240
+ current_session_id(env).present?
241
+ end
242
+
243
+ def get_session(env, sid)
244
+ raise '#get_session needs to be implemented.'
245
+ end
246
+
247
+ def set_session(env, sid, session_data)
248
+ raise '#set_session needs to be implemented.'
249
+ end
250
+
251
+ def destroy(env)
252
+ raise '#destroy needs to be implemented.'
253
+ end
254
+
255
+ module SessionUtils
256
+ private
257
+ def stale_session_check!
258
+ yield
259
+ rescue ArgumentError => argument_error
260
+ if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
261
+ begin
262
+ # Note that the regexp does not allow $1 to end with a ':'
263
+ $1.constantize
264
+ rescue LoadError, NameError => const_error
265
+ raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn\\'t available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: \#{const_error.message} [\#{const_error.class}])\n"
266
+ end
267
+ retry
268
+ else
269
+ raise
270
+ end
271
+ end
272
+ end
273
+ include SessionUtils
274
+ end
275
+ end
276
+ end