actionpack_csi 2.3.5.p6

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 (429) hide show
  1. data/CHANGELOG +5184 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +160 -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 +160 -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 +1423 -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 +95 -0
  27. data/lib/action_controller/dispatcher.rb +133 -0
  28. data/lib/action_controller/failsafe.rb +86 -0
  29. data/lib/action_controller/filters.rb +680 -0
  30. data/lib/action_controller/flash.rb +171 -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 +692 -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 +493 -0
  48. data/lib/action_controller/request_forgery_protection.rb +113 -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 +239 -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 +502 -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 +181 -0
  61. data/lib/action_controller/session/cookie_store.rb +221 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +51 -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 +216 -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/erb/util.rb +44 -0
  93. data/lib/action_view/helpers/active_record_helper.rb +305 -0
  94. data/lib/action_view/helpers/asset_tag_helper.rb +694 -0
  95. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  96. data/lib/action_view/helpers/benchmark_helper.rb +54 -0
  97. data/lib/action_view/helpers/cache_helper.rb +39 -0
  98. data/lib/action_view/helpers/capture_helper.rb +136 -0
  99. data/lib/action_view/helpers/date_helper.rb +988 -0
  100. data/lib/action_view/helpers/debug_helper.rb +38 -0
  101. data/lib/action_view/helpers/form_helper.rb +1074 -0
  102. data/lib/action_view/helpers/form_options_helper.rb +600 -0
  103. data/lib/action_view/helpers/form_tag_helper.rb +487 -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 +259 -0
  111. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  112. data/lib/action_view/helpers/tag_helper.rb +150 -0
  113. data/lib/action_view/helpers/text_helper.rb +587 -0
  114. data/lib/action_view/helpers/translation_helper.rb +39 -0
  115. data/lib/action_view/helpers/url_helper.rb +639 -0
  116. data/lib/action_view/helpers.rb +59 -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 +240 -0
  120. data/lib/action_view/paths.rb +69 -0
  121. data/lib/action_view/reloadable_template.rb +117 -0
  122. data/lib/action_view/renderable.rb +95 -0
  123. data/lib/action_view/renderable_partial.rb +47 -0
  124. data/lib/action_view/safe_buffer.rb +28 -0
  125. data/lib/action_view/template.rb +252 -0
  126. data/lib/action_view/template_error.rb +99 -0
  127. data/lib/action_view/template_handler.rb +34 -0
  128. data/lib/action_view/template_handlers/builder.rb +17 -0
  129. data/lib/action_view/template_handlers/erb.rb +22 -0
  130. data/lib/action_view/template_handlers/rjs.rb +13 -0
  131. data/lib/action_view/template_handlers.rb +48 -0
  132. data/lib/action_view/test_case.rb +162 -0
  133. data/lib/action_view.rb +58 -0
  134. data/lib/actionpack.rb +2 -0
  135. data/test/abstract_unit.rb +61 -0
  136. data/test/active_record_unit.rb +104 -0
  137. data/test/activerecord/active_record_store_test.rb +174 -0
  138. data/test/activerecord/render_partial_with_record_identification_test.rb +188 -0
  139. data/test/adv_attr_test.rb +20 -0
  140. data/test/controller/action_pack_assertions_test.rb +543 -0
  141. data/test/controller/addresses_render_test.rb +37 -0
  142. data/test/controller/assert_select_test.rb +734 -0
  143. data/test/controller/base_test.rb +217 -0
  144. data/test/controller/benchmark_test.rb +32 -0
  145. data/test/controller/caching_test.rb +729 -0
  146. data/test/controller/capture_test.rb +66 -0
  147. data/test/controller/content_type_test.rb +168 -0
  148. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  149. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  150. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  151. data/test/controller/cookie_test.rb +134 -0
  152. data/test/controller/deprecation/deprecated_base_methods_test.rb +32 -0
  153. data/test/controller/dispatcher_test.rb +144 -0
  154. data/test/controller/dom_assertions_test.rb +53 -0
  155. data/test/controller/failsafe_test.rb +60 -0
  156. data/test/controller/fake_controllers.rb +33 -0
  157. data/test/controller/fake_models.rb +19 -0
  158. data/test/controller/filter_params_test.rb +52 -0
  159. data/test/controller/filters_test.rb +885 -0
  160. data/test/controller/flash_test.rb +147 -0
  161. data/test/controller/header_test.rb +14 -0
  162. data/test/controller/helper_test.rb +224 -0
  163. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  164. data/test/controller/html-scanner/document_test.rb +148 -0
  165. data/test/controller/html-scanner/node_test.rb +89 -0
  166. data/test/controller/html-scanner/sanitizer_test.rb +274 -0
  167. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  168. data/test/controller/html-scanner/text_node_test.rb +50 -0
  169. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  170. data/test/controller/http_basic_authentication_test.rb +113 -0
  171. data/test/controller/http_digest_authentication_test.rb +254 -0
  172. data/test/controller/integration_test.rb +483 -0
  173. data/test/controller/layout_test.rb +215 -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/polymorphic_routes_test.rb +297 -0
  179. data/test/controller/rack_test.rb +311 -0
  180. data/test/controller/record_identifier_test.rb +139 -0
  181. data/test/controller/redirect_test.rb +285 -0
  182. data/test/controller/reloader_test.rb +124 -0
  183. data/test/controller/render_test.rb +1762 -0
  184. data/test/controller/request/json_params_parsing_test.rb +65 -0
  185. data/test/controller/request/multipart_params_parsing_test.rb +162 -0
  186. data/test/controller/request/query_string_parsing_test.rb +120 -0
  187. data/test/controller/request/test_request_test.rb +35 -0
  188. data/test/controller/request/url_encoded_params_parsing_test.rb +146 -0
  189. data/test/controller/request/xml_params_parsing_test.rb +103 -0
  190. data/test/controller/request_forgery_protection_test.rb +265 -0
  191. data/test/controller/request_test.rb +395 -0
  192. data/test/controller/rescue_test.rb +536 -0
  193. data/test/controller/resources_test.rb +1393 -0
  194. data/test/controller/routing_test.rb +2591 -0
  195. data/test/controller/selector_test.rb +628 -0
  196. data/test/controller/send_file_test.rb +171 -0
  197. data/test/controller/session/cookie_store_test.rb +216 -0
  198. data/test/controller/session/mem_cache_store_test.rb +127 -0
  199. data/test/controller/session/test_session_test.rb +58 -0
  200. data/test/controller/test_test.rb +700 -0
  201. data/test/controller/translation_test.rb +26 -0
  202. data/test/controller/url_rewriter_test.rb +385 -0
  203. data/test/controller/verification_test.rb +270 -0
  204. data/test/controller/view_paths_test.rb +141 -0
  205. data/test/controller/webservice_test.rb +273 -0
  206. data/test/fixtures/_top_level_partial.html.erb +1 -0
  207. data/test/fixtures/_top_level_partial_only.erb +1 -0
  208. data/test/fixtures/addresses/list.erb +1 -0
  209. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  210. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  211. data/test/fixtures/companies.yml +24 -0
  212. data/test/fixtures/company.rb +10 -0
  213. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  214. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  215. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  216. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  217. data/test/fixtures/customers/_customer.html.erb +1 -0
  218. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  219. data/test/fixtures/developer.rb +9 -0
  220. data/test/fixtures/developers/_developer.erb +1 -0
  221. data/test/fixtures/developers.yml +21 -0
  222. data/test/fixtures/developers_projects.yml +13 -0
  223. data/test/fixtures/failsafe/500.html +1 -0
  224. data/test/fixtures/fun/games/_game.erb +1 -0
  225. data/test/fixtures/fun/games/hello_world.erb +1 -0
  226. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  227. data/test/fixtures/functional_caching/_partial.erb +3 -0
  228. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  229. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  230. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  231. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  232. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  233. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  234. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  235. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  236. data/test/fixtures/helpers/abc_helper.rb +5 -0
  237. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  238. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  239. data/test/fixtures/layout_tests/abs_path_layout.rhtml +1 -0
  240. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  241. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  242. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  243. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  244. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  245. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  246. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  247. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  248. data/test/fixtures/layouts/_column.html.erb +2 -0
  249. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  250. data/test/fixtures/layouts/builder.builder +3 -0
  251. data/test/fixtures/layouts/default_html.html.erb +1 -0
  252. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  253. data/test/fixtures/layouts/standard.erb +1 -0
  254. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  255. data/test/fixtures/layouts/xhr.html.erb +2 -0
  256. data/test/fixtures/layouts/yield.erb +2 -0
  257. data/test/fixtures/mascot.rb +3 -0
  258. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  259. data/test/fixtures/mascots.yml +4 -0
  260. data/test/fixtures/multipart/binary_file +0 -0
  261. data/test/fixtures/multipart/boundary_problem_file +10 -0
  262. data/test/fixtures/multipart/bracketed_param +5 -0
  263. data/test/fixtures/multipart/empty +10 -0
  264. data/test/fixtures/multipart/hello.txt +1 -0
  265. data/test/fixtures/multipart/large_text_file +10 -0
  266. data/test/fixtures/multipart/mixed_files +0 -0
  267. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  268. data/test/fixtures/multipart/none +9 -0
  269. data/test/fixtures/multipart/single_parameter +5 -0
  270. data/test/fixtures/multipart/text_file +10 -0
  271. data/test/fixtures/override/test/hello_world.erb +1 -0
  272. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  273. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  274. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  275. data/test/fixtures/post_test/post/index.html.erb +1 -0
  276. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  277. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  278. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  279. data/test/fixtures/project.rb +3 -0
  280. data/test/fixtures/projects/_project.erb +1 -0
  281. data/test/fixtures/projects.yml +7 -0
  282. data/test/fixtures/public/404.html +1 -0
  283. data/test/fixtures/public/500.da.html +1 -0
  284. data/test/fixtures/public/500.html +1 -0
  285. data/test/fixtures/public/absolute/test.css +23 -0
  286. data/test/fixtures/public/absolute/test.js +63 -0
  287. data/test/fixtures/public/images/rails.png +0 -0
  288. data/test/fixtures/public/javascripts/application.js +1 -0
  289. data/test/fixtures/public/javascripts/bank.js +1 -0
  290. data/test/fixtures/public/javascripts/controls.js +1 -0
  291. data/test/fixtures/public/javascripts/dragdrop.js +1 -0
  292. data/test/fixtures/public/javascripts/effects.js +1 -0
  293. data/test/fixtures/public/javascripts/prototype.js +1 -0
  294. data/test/fixtures/public/javascripts/robber.js +1 -0
  295. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  296. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  297. data/test/fixtures/public/stylesheets/bank.css +1 -0
  298. data/test/fixtures/public/stylesheets/robber.css +1 -0
  299. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  300. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  301. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  302. data/test/fixtures/replies/_reply.erb +1 -0
  303. data/test/fixtures/replies.yml +15 -0
  304. data/test/fixtures/reply.rb +7 -0
  305. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  306. data/test/fixtures/respond_to/all_types_with_layout.js.rjs +1 -0
  307. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  308. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  309. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  310. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  311. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  312. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  313. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  314. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  315. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  316. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  317. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  318. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  319. data/test/fixtures/scope/test/modgreet.erb +1 -0
  320. data/test/fixtures/shared.html.erb +1 -0
  321. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  322. data/test/fixtures/test/_counter.html.erb +1 -0
  323. data/test/fixtures/test/_customer.erb +1 -0
  324. data/test/fixtures/test/_customer_counter.erb +1 -0
  325. data/test/fixtures/test/_customer_greeting.erb +1 -0
  326. data/test/fixtures/test/_customer_with_var.erb +1 -0
  327. data/test/fixtures/test/_form.erb +1 -0
  328. data/test/fixtures/test/_from_helper.erb +1 -0
  329. data/test/fixtures/test/_hash_greeting.erb +1 -0
  330. data/test/fixtures/test/_hash_object.erb +2 -0
  331. data/test/fixtures/test/_hello.builder +1 -0
  332. data/test/fixtures/test/_labelling_form.erb +1 -0
  333. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  334. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  335. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  336. data/test/fixtures/test/_one.html.erb +1 -0
  337. data/test/fixtures/test/_partial.erb +1 -0
  338. data/test/fixtures/test/_partial.html.erb +1 -0
  339. data/test/fixtures/test/_partial.js.erb +1 -0
  340. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  341. data/test/fixtures/test/_partial_only.erb +1 -0
  342. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  343. data/test/fixtures/test/_person.erb +2 -0
  344. data/test/fixtures/test/_raise.html.erb +1 -0
  345. data/test/fixtures/test/_two.html.erb +1 -0
  346. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  347. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  348. data/test/fixtures/test/capturing.erb +4 -0
  349. data/test/fixtures/test/content_for.erb +2 -0
  350. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  351. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  352. data/test/fixtures/test/delete_with_js.rjs +2 -0
  353. data/test/fixtures/test/dont_pick_me +1 -0
  354. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  355. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  356. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  357. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  358. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  359. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  360. data/test/fixtures/test/greeting.erb +1 -0
  361. data/test/fixtures/test/greeting.js.rjs +1 -0
  362. data/test/fixtures/test/hello.builder +4 -0
  363. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  364. data/test/fixtures/test/hello_world.erb +1 -0
  365. data/test/fixtures/test/hello_world.erb~ +1 -0
  366. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  367. data/test/fixtures/test/hello_world_container.builder +3 -0
  368. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  369. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  370. data/test/fixtures/test/hello_xml_world.builder +11 -0
  371. data/test/fixtures/test/hyphen-ated.erb +1 -0
  372. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  373. data/test/fixtures/test/list.erb +1 -0
  374. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  375. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  376. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  377. data/test/fixtures/test/nested_layout.erb +3 -0
  378. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  379. data/test/fixtures/test/potential_conflicts.erb +4 -0
  380. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  381. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  382. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  383. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  384. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  385. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  386. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  387. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  388. data/test/fixtures/test/render_to_string_test.erb +1 -0
  389. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  390. data/test/fixtures/test/template.erb +1 -0
  391. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  392. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  393. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  394. data/test/fixtures/test/utf8.html.erb +2 -0
  395. data/test/fixtures/topic.rb +3 -0
  396. data/test/fixtures/topics/_topic.html.erb +1 -0
  397. data/test/fixtures/topics.yml +22 -0
  398. data/test/template/active_record_helper_i18n_test.rb +44 -0
  399. data/test/template/active_record_helper_test.rb +302 -0
  400. data/test/template/asset_tag_helper_test.rb +771 -0
  401. data/test/template/atom_feed_helper_test.rb +315 -0
  402. data/test/template/benchmark_helper_test.rb +86 -0
  403. data/test/template/compiled_templates_test.rb +204 -0
  404. data/test/template/date_helper_i18n_test.rb +121 -0
  405. data/test/template/date_helper_test.rb +2485 -0
  406. data/test/template/erb_util_test.rb +24 -0
  407. data/test/template/form_helper_test.rb +1393 -0
  408. data/test/template/form_options_helper_i18n_test.rb +27 -0
  409. data/test/template/form_options_helper_test.rb +807 -0
  410. data/test/template/form_tag_helper_test.rb +344 -0
  411. data/test/template/javascript_helper_test.rb +106 -0
  412. data/test/template/number_helper_i18n_test.rb +69 -0
  413. data/test/template/number_helper_test.rb +132 -0
  414. data/test/template/prototype_helper_test.rb +639 -0
  415. data/test/template/raw_output_helper_test.rb +21 -0
  416. data/test/template/record_tag_helper_test.rb +58 -0
  417. data/test/template/render_test.rb +290 -0
  418. data/test/template/sanitize_helper_test.rb +57 -0
  419. data/test/template/scriptaculous_helper_test.rb +90 -0
  420. data/test/template/tag_helper_test.rb +98 -0
  421. data/test/template/template_test.rb +32 -0
  422. data/test/template/test_test.rb +54 -0
  423. data/test/template/text_helper_test.rb +543 -0
  424. data/test/template/translation_helper_test.rb +32 -0
  425. data/test/template/url_helper_test.rb +622 -0
  426. data/test/testing_sandbox.rb +15 -0
  427. data/test/view/safe_buffer_test.rb +36 -0
  428. data/test/view/test_case_test.rb +176 -0
  429. metadata +531 -0
@@ -0,0 +1,502 @@
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
+ #
178
+ #{generate_optimisation_block(route, kind)} # #{generate_optimisation_block(route, kind)}
179
+ #
180
+ opts = if args.empty? || Hash === args.first # opts = if args.empty? || Hash === args.first
181
+ args.first || {} # args.first || {}
182
+ else # else
183
+ options = args.extract_options! # options = args.extract_options!
184
+ args = args.zip(#{route.segment_keys.inspect}).inject({}) do |h, (v, k)| # args = args.zip([]).inject({}) do |h, (v, k)|
185
+ h[k] = v # h[k] = v
186
+ h # h
187
+ end # end
188
+ options.merge(args) # options.merge(args)
189
+ end # end
190
+ #
191
+ url_for(#{hash_access_method}(opts)) # url_for(hash_for_users_url(opts))
192
+ #
193
+ end # end
194
+ #Add an alias to support the now deprecated formatted_* URL. # #Add an alias to support the now deprecated formatted_* URL.
195
+ def formatted_#{selector}(*args) # def formatted_users_url(*args)
196
+ ActiveSupport::Deprecation.warn( # ActiveSupport::Deprecation.warn(
197
+ "formatted_#{selector}() has been deprecated. " + # "formatted_users_url() has been deprecated. " +
198
+ "Please pass format to the standard " + # "Please pass format to the standard " +
199
+ "#{selector} method instead.", caller) # "users_url method instead.", caller)
200
+ #{selector}(*args) # users_url(*args)
201
+ end # end
202
+ protected :#{selector} # protected :users_url
203
+ end_eval
204
+ helpers << selector
205
+ end
206
+ end
207
+
208
+ attr_accessor :routes, :named_routes, :configuration_files
209
+
210
+ def initialize
211
+ self.configuration_files = []
212
+
213
+ self.routes = []
214
+ self.named_routes = NamedRouteCollection.new
215
+
216
+ clear_recognize_optimized!
217
+ end
218
+
219
+ # Subclasses and plugins may override this method to specify a different
220
+ # RouteBuilder instance, so that other route DSL's can be created.
221
+ def builder
222
+ @builder ||= RouteBuilder.new
223
+ end
224
+
225
+ def draw
226
+ yield Mapper.new(self)
227
+ install_helpers
228
+ end
229
+
230
+ def clear!
231
+ routes.clear
232
+ named_routes.clear
233
+ @combined_regexp = nil
234
+ @routes_by_controller = nil
235
+ # This will force routing/recognition_optimization.rb
236
+ # to refresh optimisations.
237
+ clear_recognize_optimized!
238
+ end
239
+
240
+ def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
241
+ Array(destinations).each { |d| d.module_eval { include Helpers } }
242
+ named_routes.install(destinations, regenerate_code)
243
+ end
244
+
245
+ def empty?
246
+ routes.empty?
247
+ end
248
+
249
+ def add_configuration_file(path)
250
+ self.configuration_files << path
251
+ end
252
+
253
+ # Deprecated accessor
254
+ def configuration_file=(path)
255
+ add_configuration_file(path)
256
+ end
257
+
258
+ # Deprecated accessor
259
+ def configuration_file
260
+ configuration_files
261
+ end
262
+
263
+ def load!
264
+ Routing.use_controllers!(nil) # Clear the controller cache so we may discover new ones
265
+ clear!
266
+ load_routes!
267
+ end
268
+
269
+ # reload! will always force a reload whereas load checks the timestamp first
270
+ alias reload! load!
271
+
272
+ def reload
273
+ if configuration_files.any? && @routes_last_modified
274
+ if routes_changed_at == @routes_last_modified
275
+ return # routes didn't change, don't reload
276
+ else
277
+ @routes_last_modified = routes_changed_at
278
+ end
279
+ end
280
+
281
+ load!
282
+ end
283
+
284
+ def load_routes!
285
+ if configuration_files.any?
286
+ configuration_files.each { |config| load(config) }
287
+ @routes_last_modified = routes_changed_at
288
+ else
289
+ add_route ":controller/:action/:id"
290
+ end
291
+ end
292
+
293
+ def routes_changed_at
294
+ routes_changed_at = nil
295
+
296
+ configuration_files.each do |config|
297
+ config_changed_at = File.stat(config).mtime
298
+
299
+ if routes_changed_at.nil? || config_changed_at > routes_changed_at
300
+ routes_changed_at = config_changed_at
301
+ end
302
+ end
303
+
304
+ routes_changed_at
305
+ end
306
+
307
+ def add_route(path, options = {})
308
+ options.each { |k, v| options[k] = v.to_s if [:controller, :action].include?(k) && v.is_a?(Symbol) }
309
+ route = builder.build(path, options)
310
+ routes << route
311
+ route
312
+ end
313
+
314
+ def add_named_route(name, path, options = {})
315
+ # TODO - is options EVER used?
316
+ name = options[:name_prefix] + name.to_s if options[:name_prefix]
317
+ named_routes[name.to_sym] = add_route(path, options)
318
+ end
319
+
320
+ def options_as_params(options)
321
+ # If an explicit :controller was given, always make :action explicit
322
+ # too, so that action expiry works as expected for things like
323
+ #
324
+ # generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
325
+ #
326
+ # (the above is from the unit tests). In the above case, because the
327
+ # controller was explicitly given, but no action, the action is implied to
328
+ # be "index", not the recalled action of "show".
329
+ #
330
+ # great fun, eh?
331
+
332
+ options_as_params = options.clone
333
+ options_as_params[:action] ||= 'index' if options[:controller]
334
+ options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action]
335
+ options_as_params
336
+ end
337
+
338
+ def build_expiry(options, recall)
339
+ recall.inject({}) do |expiry, (key, recalled_value)|
340
+ expiry[key] = (options.key?(key) && options[key].to_param != recalled_value.to_param)
341
+ expiry
342
+ end
343
+ end
344
+
345
+ # Generate the path indicated by the arguments, and return an array of
346
+ # the keys that were not used to generate it.
347
+ def extra_keys(options, recall={})
348
+ generate_extras(options, recall).last
349
+ end
350
+
351
+ def generate_extras(options, recall={})
352
+ generate(options, recall, :generate_extras)
353
+ end
354
+
355
+ def generate(options, recall = {}, method=:generate)
356
+ named_route_name = options.delete(:use_route)
357
+ generate_all = options.delete(:generate_all)
358
+ if named_route_name
359
+ named_route = named_routes[named_route_name]
360
+ options = named_route.parameter_shell.merge(options)
361
+ end
362
+
363
+ options = options_as_params(options)
364
+ expire_on = build_expiry(options, recall)
365
+
366
+ if options[:controller]
367
+ options[:controller] = options[:controller].to_s
368
+ end
369
+ # if the controller has changed, make sure it changes relative to the
370
+ # current controller module, if any. In other words, if we're currently
371
+ # on admin/get, and the new controller is 'set', the new controller
372
+ # should really be admin/set.
373
+ if !named_route && expire_on[:controller] && options[:controller] && options[:controller][0] != ?/
374
+ old_parts = recall[:controller].split('/')
375
+ new_parts = options[:controller].split('/')
376
+ parts = old_parts[0..-(new_parts.length + 1)] + new_parts
377
+ options[:controller] = parts.join('/')
378
+ end
379
+
380
+ # drop the leading '/' on the controller name
381
+ options[:controller] = options[:controller][1..-1] if options[:controller] && options[:controller][0] == ?/
382
+ merged = recall.merge(options)
383
+
384
+ if named_route
385
+ path = named_route.generate(options, merged, expire_on)
386
+ if path.nil?
387
+ raise_named_route_error(options, named_route, named_route_name)
388
+ else
389
+ return path
390
+ end
391
+ else
392
+ merged[:action] ||= 'index'
393
+ options[:action] ||= 'index'
394
+
395
+ controller = merged[:controller]
396
+ action = merged[:action]
397
+
398
+ raise RoutingError, "Need controller and action!" unless controller && action
399
+
400
+ if generate_all
401
+ # Used by caching to expire all paths for a resource
402
+ return routes.collect do |route|
403
+ route.__send__(method, options, merged, expire_on)
404
+ end.compact
405
+ end
406
+
407
+ # don't use the recalled keys when determining which routes to check
408
+ future_routes, deprecated_routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]
409
+ routes = Routing.generate_best_match ? deprecated_routes : future_routes
410
+
411
+ routes.each_with_index do |route, index|
412
+ results = route.__send__(method, options, merged, expire_on)
413
+ if results && (!results.is_a?(Array) || results.first)
414
+ return results
415
+ end
416
+ end
417
+ end
418
+
419
+ raise RoutingError, "No route matches #{options.inspect}"
420
+ end
421
+
422
+ # try to give a helpful error message when named route generation fails
423
+ def raise_named_route_error(options, named_route, named_route_name)
424
+ diff = named_route.requirements.diff(options)
425
+ unless diff.empty?
426
+ raise RoutingError, "#{named_route_name}_url failed to generate from #{options.inspect}, expected: #{named_route.requirements.inspect}, diff: #{named_route.requirements.diff(options).inspect}"
427
+ else
428
+ required_segments = named_route.segments.select {|seg| (!seg.optional?) && (!seg.is_a?(DividerSegment)) }
429
+ required_keys_or_values = required_segments.map { |seg| seg.key rescue seg.value } # we want either the key or the value from the segment
430
+ 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?"
431
+ end
432
+ end
433
+
434
+ def call(env)
435
+ request = Request.new(env)
436
+ app = Routing::Routes.recognize(request)
437
+ app.call(env).to_a
438
+ end
439
+
440
+ def recognize(request)
441
+ params = recognize_path(request.path, extract_request_environment(request))
442
+ request.path_parameters = params.with_indifferent_access
443
+ "#{params[:controller].to_s.camelize}Controller".constantize
444
+ end
445
+
446
+ def recognize_path(path, environment={})
447
+ raise "Not optimized! Check that routing/recognition_optimisation overrides RouteSet#recognize_path."
448
+ end
449
+
450
+ def routes_by_controller
451
+ @routes_by_controller ||= Hash.new do |controller_hash, controller|
452
+ controller_hash[controller] = Hash.new do |action_hash, action|
453
+ action_hash[action] = Hash.new do |key_hash, keys|
454
+ key_hash[keys] = [
455
+ routes_for_controller_and_action_and_keys(controller, action, keys),
456
+ deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
457
+ ]
458
+ end
459
+ end
460
+ end
461
+ end
462
+
463
+ def routes_for(options, merged, expire_on)
464
+ raise "Need controller and action!" unless controller && action
465
+ controller = merged[:controller]
466
+ merged = options if expire_on[:controller]
467
+ action = merged[:action] || 'index'
468
+
469
+ routes_by_controller[controller][action][merged.keys][1]
470
+ end
471
+
472
+ def routes_for_controller_and_action(controller, action)
473
+ ActiveSupport::Deprecation.warn "routes_for_controller_and_action() has been deprecated. Please use routes_for()"
474
+ selected = routes.select do |route|
475
+ route.matches_controller_and_action? controller, action
476
+ end
477
+ (selected.length == routes.length) ? routes : selected
478
+ end
479
+
480
+ def routes_for_controller_and_action_and_keys(controller, action, keys)
481
+ routes.select do |route|
482
+ route.matches_controller_and_action? controller, action
483
+ end
484
+ end
485
+
486
+ def deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
487
+ selected = routes.select do |route|
488
+ route.matches_controller_and_action? controller, action
489
+ end
490
+ selected.sort_by do |route|
491
+ (keys - route.significant_keys).length
492
+ end
493
+ end
494
+
495
+ # Subclasses and plugins may override this method to extract further attributes
496
+ # from the request, for use by route conditions and such.
497
+ def extract_request_environment(request)
498
+ { :method => request.method }
499
+ end
500
+ end
501
+ end
502
+ 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