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,503 @@
1
+ module ActionController
2
+ module Routing
3
+ class RouteSet #:nodoc:
4
+ # Mapper instances are used to build routes. The object passed to the draw
5
+ # block in config/routes.rb is a Mapper instance.
6
+ #
7
+ # Mapper instances have relatively few instance methods, in order to avoid
8
+ # clashes with named routes.
9
+ class Mapper #:doc:
10
+ include ActionController::Resources
11
+
12
+ def initialize(set) #:nodoc:
13
+ @set = set
14
+ end
15
+
16
+ # Create an unnamed route with the provided +path+ and +options+. See
17
+ # ActionController::Routing for an introduction to routes.
18
+ def connect(path, options = {})
19
+ @set.add_route(path, options)
20
+ end
21
+
22
+ # Creates a named route called "root" for matching the root level request.
23
+ def root(options = {})
24
+ if options.is_a?(Symbol)
25
+ if source_route = @set.named_routes.routes[options]
26
+ options = source_route.defaults.merge({ :conditions => source_route.conditions })
27
+ end
28
+ end
29
+ named_route("root", '', options)
30
+ end
31
+
32
+ def named_route(name, path, options = {}) #:nodoc:
33
+ @set.add_named_route(name, path, options)
34
+ end
35
+
36
+ # Enables the use of resources in a module by setting the name_prefix, path_prefix, and namespace for the model.
37
+ # Example:
38
+ #
39
+ # map.namespace(:admin) do |admin|
40
+ # admin.resources :products,
41
+ # :has_many => [ :tags, :images, :variants ]
42
+ # end
43
+ #
44
+ # This will create +admin_products_url+ pointing to "admin/products", which will look for an Admin::ProductsController.
45
+ # It'll also create +admin_product_tags_url+ pointing to "admin/products/#{product_id}/tags", which will look for
46
+ # Admin::TagsController.
47
+ def namespace(name, options = {}, &block)
48
+ if options[:namespace]
49
+ with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block)
50
+ else
51
+ with_options({:path_prefix => name, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block)
52
+ end
53
+ end
54
+
55
+ def method_missing(route_name, *args, &proc) #:nodoc:
56
+ super unless args.length >= 1 && proc.nil?
57
+ @set.add_named_route(route_name, *args)
58
+ end
59
+ end
60
+
61
+ # A NamedRouteCollection instance is a collection of named routes, and also
62
+ # maintains an anonymous module that can be used to install helpers for the
63
+ # named routes.
64
+ class NamedRouteCollection #:nodoc:
65
+ include Enumerable
66
+ include ActionController::Routing::Optimisation
67
+ attr_reader :routes, :helpers
68
+
69
+ def initialize
70
+ clear!
71
+ end
72
+
73
+ def clear!
74
+ @routes = {}
75
+ @helpers = []
76
+
77
+ @module ||= Module.new
78
+ @module.instance_methods.each do |selector|
79
+ @module.class_eval { remove_method selector }
80
+ end
81
+ end
82
+
83
+ def add(name, route)
84
+ routes[name.to_sym] = route
85
+ define_named_route_methods(name, route)
86
+ end
87
+
88
+ def get(name)
89
+ routes[name.to_sym]
90
+ end
91
+
92
+ alias []= add
93
+ alias [] get
94
+ alias clear clear!
95
+
96
+ def each
97
+ routes.each { |name, route| yield name, route }
98
+ self
99
+ end
100
+
101
+ def names
102
+ routes.keys
103
+ end
104
+
105
+ def length
106
+ routes.length
107
+ end
108
+
109
+ def reset!
110
+ old_routes = routes.dup
111
+ clear!
112
+ old_routes.each do |name, route|
113
+ add(name, route)
114
+ end
115
+ end
116
+
117
+ def install(destinations = [ActionController::Base, ActionView::Base], regenerate = false)
118
+ reset! if regenerate
119
+ Array(destinations).each do |dest|
120
+ dest.__send__(:include, @module)
121
+ end
122
+ end
123
+
124
+ private
125
+ def url_helper_name(name, kind = :url)
126
+ :"#{name}_#{kind}"
127
+ end
128
+
129
+ def hash_access_name(name, kind = :url)
130
+ :"hash_for_#{name}_#{kind}"
131
+ end
132
+
133
+ def define_named_route_methods(name, route)
134
+ {:url => {:only_path => false}, :path => {:only_path => true}}.each do |kind, opts|
135
+ hash = route.defaults.merge(:use_route => name).merge(opts)
136
+ define_hash_access route, name, kind, hash
137
+ define_url_helper route, name, kind, hash
138
+ end
139
+ end
140
+
141
+ def named_helper_module_eval(code, *args)
142
+ @module.module_eval(code, *args)
143
+ end
144
+
145
+ def define_hash_access(route, name, kind, options)
146
+ selector = hash_access_name(name, kind)
147
+ named_helper_module_eval <<-end_eval # We use module_eval to avoid leaks
148
+ def #{selector}(options = nil) # def hash_for_users_url(options = nil)
149
+ options ? #{options.inspect}.merge(options) : #{options.inspect} # options ? {:only_path=>false}.merge(options) : {:only_path=>false}
150
+ end # end
151
+ protected :#{selector} # protected :hash_for_users_url
152
+ end_eval
153
+ helpers << selector
154
+ end
155
+
156
+ def define_url_helper(route, name, kind, options)
157
+ selector = url_helper_name(name, kind)
158
+ # The segment keys used for positional paramters
159
+
160
+ hash_access_method = hash_access_name(name, kind)
161
+
162
+ # allow ordered parameters to be associated with corresponding
163
+ # dynamic segments, so you can do
164
+ #
165
+ # foo_url(bar, baz, bang)
166
+ #
167
+ # instead of
168
+ #
169
+ # foo_url(:bar => bar, :baz => baz, :bang => bang)
170
+ #
171
+ # Also allow options hash, so you can do
172
+ #
173
+ # foo_url(bar, baz, bang, :sort_by => 'baz')
174
+ #
175
+ named_helper_module_eval <<-end_eval # We use module_eval to avoid leaks
176
+ def #{selector}(*args) # def users_url(*args)
177
+ args.compact! #
178
+ #
179
+ #{generate_optimisation_block(route, kind)} # #{generate_optimisation_block(route, kind)}
180
+ #
181
+ opts = if args.empty? || Hash === args.first # opts = if args.empty? || Hash === args.first
182
+ args.first || {} # args.first || {}
183
+ else # else
184
+ options = args.extract_options! # options = args.extract_options!
185
+ args = args.zip(#{route.segment_keys.inspect}).inject({}) do |h, (v, k)| # args = args.zip([]).inject({}) do |h, (v, k)|
186
+ h[k] = v # h[k] = v
187
+ h # h
188
+ end # end
189
+ options.merge(args) # options.merge(args)
190
+ end # end
191
+ #
192
+ url_for(#{hash_access_method}(opts)) # url_for(hash_for_users_url(opts))
193
+ #
194
+ end # end
195
+ #Add an alias to support the now deprecated formatted_* URL. # #Add an alias to support the now deprecated formatted_* URL.
196
+ def formatted_#{selector}(*args) # def formatted_users_url(*args)
197
+ ActiveSupport::Deprecation.warn( # ActiveSupport::Deprecation.warn(
198
+ "formatted_#{selector}() has been deprecated. " + # "formatted_users_url() has been deprecated. " +
199
+ "Please pass format to the standard " + # "Please pass format to the standard " +
200
+ "#{selector} method instead.", caller) # "users_url method instead.", caller)
201
+ #{selector}(*args) # users_url(*args)
202
+ end # end
203
+ protected :#{selector} # protected :users_url
204
+ end_eval
205
+ helpers << selector
206
+ end
207
+ end
208
+
209
+ attr_accessor :routes, :named_routes, :configuration_files
210
+
211
+ def initialize
212
+ self.configuration_files = []
213
+
214
+ self.routes = []
215
+ self.named_routes = NamedRouteCollection.new
216
+
217
+ clear_recognize_optimized!
218
+ end
219
+
220
+ # Subclasses and plugins may override this method to specify a different
221
+ # RouteBuilder instance, so that other route DSL's can be created.
222
+ def builder
223
+ @builder ||= RouteBuilder.new
224
+ end
225
+
226
+ def draw
227
+ yield Mapper.new(self)
228
+ install_helpers
229
+ end
230
+
231
+ def clear!
232
+ routes.clear
233
+ named_routes.clear
234
+ @combined_regexp = nil
235
+ @routes_by_controller = nil
236
+ # This will force routing/recognition_optimization.rb
237
+ # to refresh optimisations.
238
+ clear_recognize_optimized!
239
+ end
240
+
241
+ def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
242
+ Array(destinations).each { |d| d.module_eval { include Helpers } }
243
+ named_routes.install(destinations, regenerate_code)
244
+ end
245
+
246
+ def empty?
247
+ routes.empty?
248
+ end
249
+
250
+ def add_configuration_file(path)
251
+ self.configuration_files << path
252
+ end
253
+
254
+ # Deprecated accessor
255
+ def configuration_file=(path)
256
+ add_configuration_file(path)
257
+ end
258
+
259
+ # Deprecated accessor
260
+ def configuration_file
261
+ configuration_files
262
+ end
263
+
264
+ def load!
265
+ Routing.use_controllers!(nil) # Clear the controller cache so we may discover new ones
266
+ clear!
267
+ load_routes!
268
+ end
269
+
270
+ # reload! will always force a reload whereas load checks the timestamp first
271
+ alias reload! load!
272
+
273
+ def reload
274
+ if configuration_files.any? && @routes_last_modified
275
+ if routes_changed_at == @routes_last_modified
276
+ return # routes didn't change, don't reload
277
+ else
278
+ @routes_last_modified = routes_changed_at
279
+ end
280
+ end
281
+
282
+ load!
283
+ end
284
+
285
+ def load_routes!
286
+ if configuration_files.any?
287
+ configuration_files.each { |config| load(config) }
288
+ @routes_last_modified = routes_changed_at
289
+ else
290
+ add_route ":controller/:action/:id"
291
+ end
292
+ end
293
+
294
+ def routes_changed_at
295
+ routes_changed_at = nil
296
+
297
+ configuration_files.each do |config|
298
+ config_changed_at = File.stat(config).mtime
299
+
300
+ if routes_changed_at.nil? || config_changed_at > routes_changed_at
301
+ routes_changed_at = config_changed_at
302
+ end
303
+ end
304
+
305
+ routes_changed_at
306
+ end
307
+
308
+ def add_route(path, options = {})
309
+ options.each { |k, v| options[k] = v.to_s if [:controller, :action].include?(k) && v.is_a?(Symbol) }
310
+ route = builder.build(path, options)
311
+ routes << route
312
+ route
313
+ end
314
+
315
+ def add_named_route(name, path, options = {})
316
+ # TODO - is options EVER used?
317
+ name = options[:name_prefix] + name.to_s if options[:name_prefix]
318
+ named_routes[name.to_sym] = add_route(path, options)
319
+ end
320
+
321
+ def options_as_params(options)
322
+ # If an explicit :controller was given, always make :action explicit
323
+ # too, so that action expiry works as expected for things like
324
+ #
325
+ # generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
326
+ #
327
+ # (the above is from the unit tests). In the above case, because the
328
+ # controller was explicitly given, but no action, the action is implied to
329
+ # be "index", not the recalled action of "show".
330
+ #
331
+ # great fun, eh?
332
+
333
+ options_as_params = options.clone
334
+ options_as_params[:action] ||= 'index' if options[:controller]
335
+ options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action]
336
+ options_as_params
337
+ end
338
+
339
+ def build_expiry(options, recall)
340
+ recall.inject({}) do |expiry, (key, recalled_value)|
341
+ expiry[key] = (options.key?(key) && options[key].to_param != recalled_value.to_param)
342
+ expiry
343
+ end
344
+ end
345
+
346
+ # Generate the path indicated by the arguments, and return an array of
347
+ # the keys that were not used to generate it.
348
+ def extra_keys(options, recall={})
349
+ generate_extras(options, recall).last
350
+ end
351
+
352
+ def generate_extras(options, recall={})
353
+ generate(options, recall, :generate_extras)
354
+ end
355
+
356
+ def generate(options, recall = {}, method=:generate)
357
+ named_route_name = options.delete(:use_route)
358
+ generate_all = options.delete(:generate_all)
359
+ if named_route_name
360
+ named_route = named_routes[named_route_name]
361
+ options = named_route.parameter_shell.merge(options)
362
+ end
363
+
364
+ options = options_as_params(options)
365
+ expire_on = build_expiry(options, recall)
366
+
367
+ if options[:controller]
368
+ options[:controller] = options[:controller].to_s
369
+ end
370
+ # if the controller has changed, make sure it changes relative to the
371
+ # current controller module, if any. In other words, if we're currently
372
+ # on admin/get, and the new controller is 'set', the new controller
373
+ # should really be admin/set.
374
+ if !named_route && expire_on[:controller] && options[:controller] && options[:controller][0] != ?/
375
+ old_parts = recall[:controller].split('/')
376
+ new_parts = options[:controller].split('/')
377
+ parts = old_parts[0..-(new_parts.length + 1)] + new_parts
378
+ options[:controller] = parts.join('/')
379
+ end
380
+
381
+ # drop the leading '/' on the controller name
382
+ options[:controller] = options[:controller][1..-1] if options[:controller] && options[:controller][0] == ?/
383
+ merged = recall.merge(options)
384
+
385
+ if named_route
386
+ path = named_route.generate(options, merged, expire_on)
387
+ if path.nil?
388
+ raise_named_route_error(options, named_route, named_route_name)
389
+ else
390
+ return path
391
+ end
392
+ else
393
+ merged[:action] ||= 'index'
394
+ options[:action] ||= 'index'
395
+
396
+ controller = merged[:controller]
397
+ action = merged[:action]
398
+
399
+ raise RoutingError, "Need controller and action!" unless controller && action
400
+
401
+ if generate_all
402
+ # Used by caching to expire all paths for a resource
403
+ return routes.collect do |route|
404
+ route.__send__(method, options, merged, expire_on)
405
+ end.compact
406
+ end
407
+
408
+ # don't use the recalled keys when determining which routes to check
409
+ future_routes, deprecated_routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]
410
+ routes = Routing.generate_best_match ? deprecated_routes : future_routes
411
+
412
+ routes.each_with_index do |route, index|
413
+ results = route.__send__(method, options, merged, expire_on)
414
+ if results && (!results.is_a?(Array) || results.first)
415
+ return results
416
+ end
417
+ end
418
+ end
419
+
420
+ raise RoutingError, "No route matches #{options.inspect}"
421
+ end
422
+
423
+ # try to give a helpful error message when named route generation fails
424
+ def raise_named_route_error(options, named_route, named_route_name)
425
+ diff = named_route.requirements.diff(options)
426
+ unless diff.empty?
427
+ raise RoutingError, "#{named_route_name}_url failed to generate from #{options.inspect}, expected: #{named_route.requirements.inspect}, diff: #{named_route.requirements.diff(options).inspect}"
428
+ else
429
+ required_segments = named_route.segments.select {|seg| (!seg.optional?) && (!seg.is_a?(DividerSegment)) }
430
+ required_keys_or_values = required_segments.map { |seg| seg.key rescue seg.value } # we want either the key or the value from the segment
431
+ raise RoutingError, "#{named_route_name}_url failed to generate from #{options.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: #{required_keys_or_values.inspect} - are they all satisfied?"
432
+ end
433
+ end
434
+
435
+ def call(env)
436
+ request = Request.new(env)
437
+ app = Routing::Routes.recognize(request)
438
+ app.call(env).to_a
439
+ end
440
+
441
+ def recognize(request)
442
+ params = recognize_path(request.path, extract_request_environment(request))
443
+ request.path_parameters = params.with_indifferent_access
444
+ "#{params[:controller].to_s.camelize}Controller".constantize
445
+ end
446
+
447
+ def recognize_path(path, environment={})
448
+ raise "Not optimized! Check that routing/recognition_optimisation overrides RouteSet#recognize_path."
449
+ end
450
+
451
+ def routes_by_controller
452
+ @routes_by_controller ||= Hash.new do |controller_hash, controller|
453
+ controller_hash[controller] = Hash.new do |action_hash, action|
454
+ action_hash[action] = Hash.new do |key_hash, keys|
455
+ key_hash[keys] = [
456
+ routes_for_controller_and_action_and_keys(controller, action, keys),
457
+ deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
458
+ ]
459
+ end
460
+ end
461
+ end
462
+ end
463
+
464
+ def routes_for(options, merged, expire_on)
465
+ raise "Need controller and action!" unless controller && action
466
+ controller = merged[:controller]
467
+ merged = options if expire_on[:controller]
468
+ action = merged[:action] || 'index'
469
+
470
+ routes_by_controller[controller][action][merged.keys][1]
471
+ end
472
+
473
+ def routes_for_controller_and_action(controller, action)
474
+ ActiveSupport::Deprecation.warn "routes_for_controller_and_action() has been deprecated. Please use routes_for()"
475
+ selected = routes.select do |route|
476
+ route.matches_controller_and_action? controller, action
477
+ end
478
+ (selected.length == routes.length) ? routes : selected
479
+ end
480
+
481
+ def routes_for_controller_and_action_and_keys(controller, action, keys)
482
+ routes.select do |route|
483
+ route.matches_controller_and_action? controller, action
484
+ end
485
+ end
486
+
487
+ def deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
488
+ selected = routes.select do |route|
489
+ route.matches_controller_and_action? controller, action
490
+ end
491
+ selected.sort_by do |route|
492
+ (keys - route.significant_keys).length
493
+ end
494
+ end
495
+
496
+ # Subclasses and plugins may override this method to extract further attributes
497
+ # from the request, for use by route conditions and such.
498
+ def extract_request_environment(request)
499
+ { :method => request.method }
500
+ end
501
+ end
502
+ end
503
+ end
@@ -0,0 +1,49 @@
1
+ class Object
2
+ def to_param
3
+ to_s
4
+ end
5
+ end
6
+
7
+ class TrueClass
8
+ def to_param
9
+ self
10
+ end
11
+ end
12
+
13
+ class FalseClass
14
+ def to_param
15
+ self
16
+ end
17
+ end
18
+
19
+ class NilClass
20
+ def to_param
21
+ self
22
+ end
23
+ end
24
+
25
+ class Regexp #:nodoc:
26
+ def number_of_captures
27
+ Regexp.new("|#{source}").match('').captures.length
28
+ end
29
+
30
+ def multiline?
31
+ options & MULTILINE == MULTILINE
32
+ end
33
+
34
+ class << self
35
+ def optionalize(pattern)
36
+ case unoptionalize(pattern)
37
+ when /\A(.|\(.*\))\Z/ then "#{pattern}?"
38
+ else "(?:#{pattern})?"
39
+ end
40
+ end
41
+
42
+ def unoptionalize(pattern)
43
+ [/\A\(\?:(.*)\)\?\Z/, /\A(.|\(.*\))\?\Z/].each do |regexp|
44
+ return $1 if regexp =~ pattern
45
+ end
46
+ return pattern
47
+ end
48
+ end
49
+ end