actionpack 2.3.18 → 3.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (513) hide show
  1. data/CHANGELOG +15 -64
  2. data/README +39 -48
  3. data/lib/abstract_controller.rb +22 -0
  4. data/lib/abstract_controller/base.rb +191 -0
  5. data/lib/abstract_controller/callbacks.rb +113 -0
  6. data/lib/abstract_controller/collector.rb +30 -0
  7. data/lib/abstract_controller/compatibility.rb +18 -0
  8. data/lib/abstract_controller/helpers.rb +163 -0
  9. data/lib/abstract_controller/layouts.rb +413 -0
  10. data/lib/abstract_controller/localized_cache.rb +49 -0
  11. data/lib/abstract_controller/logger.rb +13 -0
  12. data/lib/abstract_controller/rendering.rb +238 -0
  13. data/lib/{action_controller → abstract_controller}/translation.rb +1 -1
  14. data/lib/action_controller.rb +68 -102
  15. data/lib/action_controller/base.rb +77 -1409
  16. data/lib/action_controller/caching.rb +58 -45
  17. data/lib/action_controller/caching/actions.rb +100 -114
  18. data/lib/action_controller/caching/fragments.rb +17 -19
  19. data/lib/action_controller/caching/pages.rb +12 -6
  20. data/lib/action_controller/caching/sweeping.rb +42 -0
  21. data/lib/action_controller/deprecated.rb +5 -0
  22. data/lib/action_controller/deprecated/dispatcher.rb +28 -0
  23. data/lib/action_controller/deprecated/integration_test.rb +2 -0
  24. data/lib/action_controller/deprecated/performance_test.rb +1 -0
  25. data/lib/action_controller/metal.rb +125 -0
  26. data/lib/action_controller/metal/compatibility.rb +141 -0
  27. data/lib/action_controller/metal/conditional_get.rb +86 -0
  28. data/lib/action_controller/metal/configuration.rb +28 -0
  29. data/lib/action_controller/metal/cookies.rb +17 -0
  30. data/lib/action_controller/metal/exceptions.rb +46 -0
  31. data/lib/action_controller/metal/flash.rb +28 -0
  32. data/lib/action_controller/metal/head.rb +33 -0
  33. data/lib/action_controller/metal/helpers.rb +116 -0
  34. data/lib/action_controller/metal/hide_actions.rb +50 -0
  35. data/lib/action_controller/{http_authentication.rb → metal/http_authentication.rb} +18 -15
  36. data/lib/action_controller/metal/instrumentation.rb +99 -0
  37. data/lib/action_controller/metal/mime_responds.rb +300 -0
  38. data/lib/action_controller/metal/rack_delegation.rb +35 -0
  39. data/lib/action_controller/metal/redirecting.rb +90 -0
  40. data/lib/action_controller/metal/renderers.rb +95 -0
  41. data/lib/action_controller/metal/rendering.rb +69 -0
  42. data/lib/action_controller/metal/request_forgery_protection.rb +115 -0
  43. data/lib/action_controller/metal/rescue.rb +13 -0
  44. data/lib/action_controller/metal/responder.rb +220 -0
  45. data/lib/action_controller/{session_management.rb → metal/session_management.rb} +5 -14
  46. data/lib/action_controller/{streaming.rb → metal/streaming.rb} +13 -12
  47. data/lib/action_controller/metal/testing.rb +42 -0
  48. data/lib/action_controller/metal/url_for.rb +157 -0
  49. data/lib/action_controller/{verification.rb → metal/verification.rb} +41 -41
  50. data/lib/action_controller/middleware.rb +38 -0
  51. data/lib/action_controller/polymorphic_routes.rb +20 -26
  52. data/lib/action_controller/railtie.rb +30 -0
  53. data/lib/action_controller/railties/subscriber.rb +63 -0
  54. data/lib/action_controller/record_identifier.rb +3 -16
  55. data/lib/action_controller/test_case.rb +156 -18
  56. data/lib/action_controller/url_rewriter.rb +47 -200
  57. data/lib/action_controller/vendor/html-scanner.rb +16 -12
  58. data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -1
  59. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +12 -9
  60. data/lib/action_dispatch.rb +88 -0
  61. data/lib/action_dispatch/http/cache.rb +123 -0
  62. data/lib/action_dispatch/http/filter_parameters.rb +98 -0
  63. data/lib/{action_controller → action_dispatch/http}/headers.rb +8 -8
  64. data/lib/action_dispatch/http/mime_negotiation.rb +101 -0
  65. data/lib/{action_controller → action_dispatch/http}/mime_type.rb +30 -11
  66. data/lib/{action_controller → action_dispatch/http}/mime_types.rb +5 -3
  67. data/lib/action_dispatch/http/parameters.rb +49 -0
  68. data/lib/action_dispatch/http/request.rb +223 -0
  69. data/lib/action_dispatch/http/response.rb +209 -0
  70. data/lib/action_dispatch/http/upload.rb +48 -0
  71. data/lib/action_dispatch/http/url.rb +129 -0
  72. data/lib/action_dispatch/middleware/callbacks.rb +50 -0
  73. data/lib/action_dispatch/middleware/cascade.rb +29 -0
  74. data/lib/action_dispatch/middleware/cookies.rb +216 -0
  75. data/lib/{action_controller → action_dispatch/middleware}/flash.rb +51 -90
  76. data/lib/action_dispatch/middleware/head.rb +18 -0
  77. data/lib/action_dispatch/middleware/params_parser.rb +78 -0
  78. data/lib/action_dispatch/middleware/rescue.rb +26 -0
  79. data/lib/action_dispatch/middleware/session/abstract_store.rb +209 -0
  80. data/lib/{action_controller → action_dispatch/middleware}/session/cookie_store.rb +56 -60
  81. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
  82. data/lib/action_dispatch/middleware/show_exceptions.rb +173 -0
  83. data/lib/{action_controller/middleware_stack.rb → action_dispatch/middleware/stack.rb} +23 -13
  84. data/lib/action_dispatch/middleware/static.rb +44 -0
  85. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/_request_and_response.erb +10 -3
  86. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/_trace.erb +4 -4
  87. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
  88. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/layout.erb +2 -2
  89. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/missing_template.erb +0 -0
  90. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/routing_error.erb +0 -0
  91. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/template_error.erb +3 -3
  92. data/lib/{action_controller → action_dispatch/middleware}/templates/rescues/unknown_action.erb +0 -0
  93. data/lib/action_dispatch/railtie.rb +15 -0
  94. data/lib/action_dispatch/routing.rb +217 -0
  95. data/lib/action_dispatch/routing/deprecated_mapper.rb +877 -0
  96. data/lib/action_dispatch/routing/mapper.rb +649 -0
  97. data/lib/action_dispatch/routing/route.rb +55 -0
  98. data/lib/action_dispatch/routing/route_set.rb +445 -0
  99. data/lib/action_dispatch/testing/assertions.rb +21 -0
  100. data/lib/action_dispatch/testing/assertions/dom.rb +37 -0
  101. data/lib/{action_controller/assertions/model_assertions.rb → action_dispatch/testing/assertions/model.rb} +2 -4
  102. data/lib/action_dispatch/testing/assertions/response.rb +154 -0
  103. data/lib/{action_controller/assertions/routing_assertions.rb → action_dispatch/testing/assertions/routing.rb} +72 -34
  104. data/lib/{action_controller/assertions/selector_assertions.rb → action_dispatch/testing/assertions/selector.rb} +14 -11
  105. data/lib/{action_controller/assertions/tag_assertions.rb → action_dispatch/testing/assertions/tag.rb} +25 -14
  106. data/lib/{action_controller → action_dispatch/testing}/integration.rb +173 -406
  107. data/lib/action_dispatch/testing/performance_test.rb +17 -0
  108. data/lib/action_dispatch/testing/test_process.rb +42 -0
  109. data/lib/action_dispatch/testing/test_request.rb +83 -0
  110. data/lib/action_dispatch/testing/test_response.rb +136 -0
  111. data/lib/action_pack/version.rb +3 -3
  112. data/lib/action_view.rb +29 -26
  113. data/lib/action_view/base.rb +101 -148
  114. data/lib/action_view/context.rb +44 -0
  115. data/lib/action_view/helpers.rb +6 -4
  116. data/lib/action_view/helpers/{active_record_helper.rb → active_model_helper.rb} +63 -63
  117. data/lib/action_view/helpers/asset_tag_helper.rb +166 -31
  118. data/lib/action_view/helpers/cache_helper.rb +1 -1
  119. data/lib/action_view/helpers/capture_helper.rb +40 -8
  120. data/lib/action_view/helpers/csrf_helper.rb +2 -4
  121. data/lib/action_view/helpers/date_helper.rb +14 -15
  122. data/lib/action_view/helpers/form_helper.rb +121 -24
  123. data/lib/action_view/helpers/form_options_helper.rb +26 -25
  124. data/lib/action_view/helpers/form_tag_helper.rb +42 -33
  125. data/lib/action_view/helpers/javascript_helper.rb +1 -109
  126. data/lib/action_view/helpers/number_helper.rb +4 -1
  127. data/lib/action_view/helpers/prototype_helper.rb +75 -499
  128. data/lib/action_view/helpers/raw_output_helper.rb +1 -1
  129. data/lib/action_view/helpers/record_tag_helper.rb +3 -3
  130. data/lib/action_view/helpers/sanitize_helper.rb +3 -2
  131. data/lib/action_view/helpers/scriptaculous_helper.rb +89 -53
  132. data/lib/action_view/helpers/tag_helper.rb +12 -13
  133. data/lib/action_view/helpers/text_helper.rb +33 -38
  134. data/lib/action_view/helpers/translation_helper.rb +11 -35
  135. data/lib/action_view/helpers/url_helper.rb +140 -134
  136. data/lib/action_view/locale/en.yml +34 -28
  137. data/lib/action_view/paths.rb +27 -24
  138. data/lib/action_view/railtie.rb +17 -0
  139. data/lib/action_view/railties/subscriber.rb +24 -0
  140. data/lib/action_view/{partials.rb → render/partials.rb} +161 -51
  141. data/lib/action_view/render/rendering.rb +117 -0
  142. data/lib/action_view/template.rb +88 -217
  143. data/lib/action_view/template/error.rb +105 -0
  144. data/lib/action_view/template/handler.rb +41 -0
  145. data/lib/action_view/template/handlers.rb +54 -0
  146. data/lib/action_view/{template_handlers → template/handlers}/builder.rb +6 -6
  147. data/lib/action_view/template/handlers/erb.rb +58 -0
  148. data/lib/action_view/{template_handlers → template/handlers}/rjs.rb +8 -3
  149. data/lib/action_view/template/resolver.rb +164 -0
  150. data/lib/action_view/template/text.rb +40 -0
  151. data/lib/action_view/test_case.rb +18 -18
  152. metadata +165 -420
  153. data/RUNNING_UNIT_TESTS +0 -24
  154. data/Rakefile +0 -158
  155. data/install.rb +0 -30
  156. data/lib/action_controller/assertions/dom_assertions.rb +0 -55
  157. data/lib/action_controller/assertions/response_assertions.rb +0 -169
  158. data/lib/action_controller/benchmarking.rb +0 -107
  159. data/lib/action_controller/caching/sweeper.rb +0 -45
  160. data/lib/action_controller/cgi_ext.rb +0 -15
  161. data/lib/action_controller/cgi_ext/cookie.rb +0 -112
  162. data/lib/action_controller/cgi_ext/query_extension.rb +0 -22
  163. data/lib/action_controller/cgi_ext/stdinput.rb +0 -24
  164. data/lib/action_controller/cgi_process.rb +0 -77
  165. data/lib/action_controller/cookies.rb +0 -197
  166. data/lib/action_controller/dispatcher.rb +0 -133
  167. data/lib/action_controller/failsafe.rb +0 -87
  168. data/lib/action_controller/filters.rb +0 -680
  169. data/lib/action_controller/helpers.rb +0 -225
  170. data/lib/action_controller/layout.rb +0 -286
  171. data/lib/action_controller/middlewares.rb +0 -14
  172. data/lib/action_controller/mime_responds.rb +0 -193
  173. data/lib/action_controller/params_parser.rb +0 -77
  174. data/lib/action_controller/performance_test.rb +0 -15
  175. data/lib/action_controller/rack_lint_patch.rb +0 -36
  176. data/lib/action_controller/reloader.rb +0 -54
  177. data/lib/action_controller/request.rb +0 -518
  178. data/lib/action_controller/request_forgery_protection.rb +0 -116
  179. data/lib/action_controller/rescue.rb +0 -183
  180. data/lib/action_controller/resources.rb +0 -682
  181. data/lib/action_controller/response.rb +0 -237
  182. data/lib/action_controller/routing.rb +0 -388
  183. data/lib/action_controller/routing/builder.rb +0 -197
  184. data/lib/action_controller/routing/optimisations.rb +0 -130
  185. data/lib/action_controller/routing/recognition_optimisation.rb +0 -167
  186. data/lib/action_controller/routing/route.rb +0 -265
  187. data/lib/action_controller/routing/route_set.rb +0 -503
  188. data/lib/action_controller/routing/routing_ext.rb +0 -49
  189. data/lib/action_controller/routing/segments.rb +0 -343
  190. data/lib/action_controller/session/abstract_store.rb +0 -276
  191. data/lib/action_controller/session/mem_cache_store.rb +0 -60
  192. data/lib/action_controller/status_codes.rb +0 -88
  193. data/lib/action_controller/string_coercion.rb +0 -29
  194. data/lib/action_controller/templates/rescues/diagnostics.erb +0 -11
  195. data/lib/action_controller/test_process.rb +0 -580
  196. data/lib/action_controller/uploaded_file.rb +0 -44
  197. data/lib/action_view/helpers/benchmark_helper.rb +0 -54
  198. data/lib/action_view/inline_template.rb +0 -19
  199. data/lib/action_view/reloadable_template.rb +0 -117
  200. data/lib/action_view/renderable.rb +0 -109
  201. data/lib/action_view/renderable_partial.rb +0 -53
  202. data/lib/action_view/template_error.rb +0 -99
  203. data/lib/action_view/template_handler.rb +0 -34
  204. data/lib/action_view/template_handlers.rb +0 -48
  205. data/lib/action_view/template_handlers/erb.rb +0 -25
  206. data/lib/actionpack.rb +0 -2
  207. data/test/abstract_unit.rb +0 -78
  208. data/test/active_record_unit.rb +0 -104
  209. data/test/activerecord/active_record_store_test.rb +0 -221
  210. data/test/activerecord/render_partial_with_record_identification_test.rb +0 -188
  211. data/test/adv_attr_test.rb +0 -20
  212. data/test/controller/action_pack_assertions_test.rb +0 -545
  213. data/test/controller/addresses_render_test.rb +0 -37
  214. data/test/controller/assert_select_test.rb +0 -735
  215. data/test/controller/base_test.rb +0 -217
  216. data/test/controller/benchmark_test.rb +0 -32
  217. data/test/controller/caching_test.rb +0 -743
  218. data/test/controller/capture_test.rb +0 -66
  219. data/test/controller/content_type_test.rb +0 -178
  220. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  221. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  222. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  223. data/test/controller/cookie_test.rb +0 -208
  224. data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -32
  225. data/test/controller/dispatcher_test.rb +0 -144
  226. data/test/controller/dom_assertions_test.rb +0 -53
  227. data/test/controller/failsafe_test.rb +0 -60
  228. data/test/controller/fake_controllers.rb +0 -33
  229. data/test/controller/fake_models.rb +0 -19
  230. data/test/controller/filter_params_test.rb +0 -52
  231. data/test/controller/filters_test.rb +0 -885
  232. data/test/controller/flash_test.rb +0 -174
  233. data/test/controller/header_test.rb +0 -14
  234. data/test/controller/helper_test.rb +0 -224
  235. data/test/controller/html-scanner/cdata_node_test.rb +0 -15
  236. data/test/controller/html-scanner/document_test.rb +0 -148
  237. data/test/controller/html-scanner/node_test.rb +0 -89
  238. data/test/controller/html-scanner/sanitizer_test.rb +0 -300
  239. data/test/controller/html-scanner/tag_node_test.rb +0 -238
  240. data/test/controller/html-scanner/text_node_test.rb +0 -50
  241. data/test/controller/html-scanner/tokenizer_test.rb +0 -131
  242. data/test/controller/http_basic_authentication_test.rb +0 -113
  243. data/test/controller/http_digest_authentication_test.rb +0 -254
  244. data/test/controller/integration_test.rb +0 -526
  245. data/test/controller/layout_test.rb +0 -215
  246. data/test/controller/localized_templates_test.rb +0 -24
  247. data/test/controller/logging_test.rb +0 -46
  248. data/test/controller/middleware_stack_test.rb +0 -90
  249. data/test/controller/mime_responds_test.rb +0 -536
  250. data/test/controller/mime_type_test.rb +0 -93
  251. data/test/controller/output_escaping_test.rb +0 -19
  252. data/test/controller/polymorphic_routes_test.rb +0 -297
  253. data/test/controller/rack_test.rb +0 -308
  254. data/test/controller/record_identifier_test.rb +0 -139
  255. data/test/controller/redirect_test.rb +0 -285
  256. data/test/controller/reloader_test.rb +0 -125
  257. data/test/controller/render_test.rb +0 -1783
  258. data/test/controller/request/json_params_parsing_test.rb +0 -65
  259. data/test/controller/request/multipart_params_parsing_test.rb +0 -177
  260. data/test/controller/request/query_string_parsing_test.rb +0 -129
  261. data/test/controller/request/test_request_test.rb +0 -35
  262. data/test/controller/request/url_encoded_params_parsing_test.rb +0 -146
  263. data/test/controller/request/xml_params_parsing_test.rb +0 -103
  264. data/test/controller/request_forgery_protection_test.rb +0 -233
  265. data/test/controller/request_test.rb +0 -398
  266. data/test/controller/rescue_test.rb +0 -541
  267. data/test/controller/resources_test.rb +0 -1393
  268. data/test/controller/routing_test.rb +0 -2592
  269. data/test/controller/selector_test.rb +0 -628
  270. data/test/controller/send_file_test.rb +0 -171
  271. data/test/controller/session/abstract_store_test.rb +0 -64
  272. data/test/controller/session/cookie_store_test.rb +0 -354
  273. data/test/controller/session/mem_cache_store_test.rb +0 -187
  274. data/test/controller/session/test_session_test.rb +0 -58
  275. data/test/controller/test_test.rb +0 -700
  276. data/test/controller/translation_test.rb +0 -26
  277. data/test/controller/url_rewriter_test.rb +0 -395
  278. data/test/controller/verification_test.rb +0 -270
  279. data/test/controller/view_paths_test.rb +0 -141
  280. data/test/controller/webservice_test.rb +0 -273
  281. data/test/fixtures/_top_level_partial.html.erb +0 -1
  282. data/test/fixtures/_top_level_partial_only.erb +0 -1
  283. data/test/fixtures/addresses/list.erb +0 -1
  284. data/test/fixtures/alternate_helpers/foo_helper.rb +0 -3
  285. data/test/fixtures/bad_customers/_bad_customer.html.erb +0 -1
  286. data/test/fixtures/companies.yml +0 -24
  287. data/test/fixtures/company.rb +0 -10
  288. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +0 -1
  289. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +0 -1
  290. data/test/fixtures/content_type/render_default_for_rjs.rjs +0 -1
  291. data/test/fixtures/content_type/render_default_for_rxml.rxml +0 -1
  292. data/test/fixtures/customers/_customer.html.erb +0 -1
  293. data/test/fixtures/db_definitions/sqlite.sql +0 -49
  294. data/test/fixtures/developer.rb +0 -9
  295. data/test/fixtures/developers.yml +0 -21
  296. data/test/fixtures/developers/_developer.erb +0 -1
  297. data/test/fixtures/developers_projects.yml +0 -13
  298. data/test/fixtures/failsafe/500.html +0 -1
  299. data/test/fixtures/fun/games/_game.erb +0 -1
  300. data/test/fixtures/fun/games/hello_world.erb +0 -1
  301. data/test/fixtures/fun/serious/games/_game.erb +0 -1
  302. data/test/fixtures/functional_caching/_partial.erb +0 -3
  303. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +0 -3
  304. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +0 -6
  305. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +0 -5
  306. data/test/fixtures/functional_caching/fragment_cached.html.erb +0 -2
  307. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +0 -1
  308. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +0 -2
  309. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +0 -1
  310. data/test/fixtures/good_customers/_good_customer.html.erb +0 -1
  311. data/test/fixtures/helpers/abc_helper.rb +0 -5
  312. data/test/fixtures/helpers/fun/games_helper.rb +0 -3
  313. data/test/fixtures/helpers/fun/pdf_helper.rb +0 -3
  314. data/test/fixtures/layout_tests/abs_path_layout.rhtml +0 -1
  315. data/test/fixtures/layout_tests/alt/hello.rhtml +0 -1
  316. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  317. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +0 -1
  318. data/test/fixtures/layout_tests/layouts/item.rhtml +0 -1
  319. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +0 -1
  320. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +0 -1
  321. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +0 -1
  322. data/test/fixtures/layout_tests/views/hello.rhtml +0 -1
  323. data/test/fixtures/layouts/_column.html.erb +0 -2
  324. data/test/fixtures/layouts/block_with_layout.erb +0 -3
  325. data/test/fixtures/layouts/builder.builder +0 -3
  326. data/test/fixtures/layouts/default_html.html.erb +0 -1
  327. data/test/fixtures/layouts/partial_with_layout.erb +0 -3
  328. data/test/fixtures/layouts/standard.erb +0 -1
  329. data/test/fixtures/layouts/talk_from_action.erb +0 -2
  330. data/test/fixtures/layouts/xhr.html.erb +0 -2
  331. data/test/fixtures/layouts/yield.erb +0 -2
  332. data/test/fixtures/localized/hello_world.de.html +0 -1
  333. data/test/fixtures/localized/hello_world.en.html +0 -1
  334. data/test/fixtures/mascot.rb +0 -3
  335. data/test/fixtures/mascots.yml +0 -4
  336. data/test/fixtures/mascots/_mascot.html.erb +0 -1
  337. data/test/fixtures/multipart/binary_file +0 -0
  338. data/test/fixtures/multipart/boundary_problem_file +0 -10
  339. data/test/fixtures/multipart/bracketed_param +0 -5
  340. data/test/fixtures/multipart/empty +0 -10
  341. data/test/fixtures/multipart/hello.txt +0 -1
  342. data/test/fixtures/multipart/large_text_file +0 -10
  343. data/test/fixtures/multipart/mixed_files +0 -0
  344. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  345. data/test/fixtures/multipart/none +0 -9
  346. data/test/fixtures/multipart/single_parameter +0 -5
  347. data/test/fixtures/multipart/text_file +0 -10
  348. data/test/fixtures/override/test/hello_world.erb +0 -1
  349. data/test/fixtures/override2/layouts/test/sub.erb +0 -1
  350. data/test/fixtures/post_test/layouts/post.html.erb +0 -1
  351. data/test/fixtures/post_test/layouts/super_post.iphone.erb +0 -1
  352. data/test/fixtures/post_test/post/index.html.erb +0 -1
  353. data/test/fixtures/post_test/post/index.iphone.erb +0 -1
  354. data/test/fixtures/post_test/super_post/index.html.erb +0 -1
  355. data/test/fixtures/post_test/super_post/index.iphone.erb +0 -1
  356. data/test/fixtures/project.rb +0 -3
  357. data/test/fixtures/projects.yml +0 -7
  358. data/test/fixtures/projects/_project.erb +0 -1
  359. data/test/fixtures/public/404.html +0 -1
  360. data/test/fixtures/public/500.da.html +0 -1
  361. data/test/fixtures/public/500.html +0 -1
  362. data/test/fixtures/public/absolute/test.css +0 -23
  363. data/test/fixtures/public/absolute/test.js +0 -63
  364. data/test/fixtures/public/images/rails.png +0 -0
  365. data/test/fixtures/public/javascripts/application.js +0 -1
  366. data/test/fixtures/public/javascripts/bank.js +0 -1
  367. data/test/fixtures/public/javascripts/controls.js +0 -1
  368. data/test/fixtures/public/javascripts/dragdrop.js +0 -1
  369. data/test/fixtures/public/javascripts/effects.js +0 -1
  370. data/test/fixtures/public/javascripts/prototype.js +0 -1
  371. data/test/fixtures/public/javascripts/robber.js +0 -1
  372. data/test/fixtures/public/javascripts/subdir/subdir.js +0 -1
  373. data/test/fixtures/public/javascripts/version.1.0.js +0 -1
  374. data/test/fixtures/public/stylesheets/bank.css +0 -1
  375. data/test/fixtures/public/stylesheets/robber.css +0 -1
  376. data/test/fixtures/public/stylesheets/subdir/subdir.css +0 -1
  377. data/test/fixtures/public/stylesheets/version.1.0.css +0 -1
  378. data/test/fixtures/quiz/questions/_question.html.erb +0 -1
  379. data/test/fixtures/replies.yml +0 -15
  380. data/test/fixtures/replies/_reply.erb +0 -1
  381. data/test/fixtures/reply.rb +0 -7
  382. data/test/fixtures/respond_to/all_types_with_layout.html.erb +0 -1
  383. data/test/fixtures/respond_to/all_types_with_layout.js.rjs +0 -1
  384. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +0 -1
  385. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +0 -1
  386. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +0 -1
  387. data/test/fixtures/respond_to/layouts/missing.html.erb +0 -1
  388. data/test/fixtures/respond_to/layouts/standard.html.erb +0 -1
  389. data/test/fixtures/respond_to/layouts/standard.iphone.erb +0 -1
  390. data/test/fixtures/respond_to/using_defaults.html.erb +0 -1
  391. data/test/fixtures/respond_to/using_defaults.js.rjs +0 -1
  392. data/test/fixtures/respond_to/using_defaults.xml.builder +0 -1
  393. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +0 -1
  394. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +0 -1
  395. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +0 -1
  396. data/test/fixtures/scope/test/modgreet.erb +0 -1
  397. data/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +0 -10
  398. data/test/fixtures/shared.html.erb +0 -1
  399. data/test/fixtures/symlink_parent/symlinked_layout.erb +0 -5
  400. data/test/fixtures/test/_counter.html.erb +0 -1
  401. data/test/fixtures/test/_customer.erb +0 -1
  402. data/test/fixtures/test/_customer_counter.erb +0 -1
  403. data/test/fixtures/test/_customer_counter_with_as.erb +0 -1
  404. data/test/fixtures/test/_customer_greeting.erb +0 -1
  405. data/test/fixtures/test/_customer_with_var.erb +0 -1
  406. data/test/fixtures/test/_form.erb +0 -1
  407. data/test/fixtures/test/_from_helper.erb +0 -1
  408. data/test/fixtures/test/_hash_greeting.erb +0 -1
  409. data/test/fixtures/test/_hash_object.erb +0 -2
  410. data/test/fixtures/test/_hello.builder +0 -1
  411. data/test/fixtures/test/_labelling_form.erb +0 -1
  412. data/test/fixtures/test/_layout_for_block_with_args.html.erb +0 -3
  413. data/test/fixtures/test/_layout_for_partial.html.erb +0 -3
  414. data/test/fixtures/test/_local_inspector.html.erb +0 -1
  415. data/test/fixtures/test/_one.html.erb +0 -1
  416. data/test/fixtures/test/_partial.erb +0 -1
  417. data/test/fixtures/test/_partial.html.erb +0 -1
  418. data/test/fixtures/test/_partial.js.erb +0 -1
  419. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +0 -1
  420. data/test/fixtures/test/_partial_only.erb +0 -1
  421. data/test/fixtures/test/_partial_with_only_html_version.html.erb +0 -1
  422. data/test/fixtures/test/_person.erb +0 -2
  423. data/test/fixtures/test/_raise.html.erb +0 -1
  424. data/test/fixtures/test/_two.html.erb +0 -1
  425. data/test/fixtures/test/_utf8_partial.html.erb +0 -1
  426. data/test/fixtures/test/_utf8_partial_magic.html.erb +0 -2
  427. data/test/fixtures/test/action_talk_to_layout.erb +0 -2
  428. data/test/fixtures/test/array_translation.erb +0 -1
  429. data/test/fixtures/test/calling_partial_with_layout.html.erb +0 -1
  430. data/test/fixtures/test/capturing.erb +0 -4
  431. data/test/fixtures/test/content_for.erb +0 -2
  432. data/test/fixtures/test/content_for_concatenated.erb +0 -3
  433. data/test/fixtures/test/content_for_with_parameter.erb +0 -2
  434. data/test/fixtures/test/delete_with_js.rjs +0 -2
  435. data/test/fixtures/test/dont_pick_me +0 -1
  436. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +0 -1
  437. data/test/fixtures/test/enum_rjs_test.rjs +0 -6
  438. data/test/fixtures/test/formatted_html_erb.html.erb +0 -1
  439. data/test/fixtures/test/formatted_xml_erb.builder +0 -1
  440. data/test/fixtures/test/formatted_xml_erb.html.erb +0 -1
  441. data/test/fixtures/test/formatted_xml_erb.xml.erb +0 -1
  442. data/test/fixtures/test/greeting.erb +0 -1
  443. data/test/fixtures/test/greeting.js.rjs +0 -1
  444. data/test/fixtures/test/hello.builder +0 -4
  445. data/test/fixtures/test/hello_world.da.html.erb +0 -1
  446. data/test/fixtures/test/hello_world.erb +0 -1
  447. data/test/fixtures/test/hello_world.erb~ +0 -1
  448. data/test/fixtures/test/hello_world.pt-BR.html.erb +0 -1
  449. data/test/fixtures/test/hello_world_container.builder +0 -3
  450. data/test/fixtures/test/hello_world_from_rxml.builder +0 -4
  451. data/test/fixtures/test/hello_world_with_layout_false.erb +0 -1
  452. data/test/fixtures/test/hello_xml_world.builder +0 -11
  453. data/test/fixtures/test/hyphen-ated.erb +0 -1
  454. data/test/fixtures/test/implicit_content_type.atom.builder +0 -2
  455. data/test/fixtures/test/list.erb +0 -1
  456. data/test/fixtures/test/malformed/malformed.en.html.erb~ +0 -1
  457. data/test/fixtures/test/malformed/malformed.erb~ +0 -1
  458. data/test/fixtures/test/malformed/malformed.html.erb~ +0 -1
  459. data/test/fixtures/test/nested_layout.erb +0 -3
  460. data/test/fixtures/test/non_erb_block_content_for.builder +0 -4
  461. data/test/fixtures/test/potential_conflicts.erb +0 -4
  462. data/test/fixtures/test/render_explicit_html_template.js.rjs +0 -1
  463. data/test/fixtures/test/render_file_from_template.html.erb +0 -1
  464. data/test/fixtures/test/render_file_with_ivar.erb +0 -1
  465. data/test/fixtures/test/render_file_with_locals.erb +0 -1
  466. data/test/fixtures/test/render_implicit_html_template.js.rjs +0 -1
  467. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +0 -1
  468. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +0 -1
  469. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +0 -1
  470. data/test/fixtures/test/render_to_string_test.erb +0 -1
  471. data/test/fixtures/test/scoped_array_translation.erb +0 -1
  472. data/test/fixtures/test/sub_template_raise.html.erb +0 -1
  473. data/test/fixtures/test/template.erb +0 -1
  474. data/test/fixtures/test/translation.erb +0 -1
  475. data/test/fixtures/test/update_element_with_capture.erb +0 -9
  476. data/test/fixtures/test/using_layout_around_block.html.erb +0 -1
  477. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +0 -1
  478. data/test/fixtures/test/utf8.html.erb +0 -4
  479. data/test/fixtures/test/utf8_magic.html.erb +0 -5
  480. data/test/fixtures/test/utf8_magic_with_bare_partial.html.erb +0 -5
  481. data/test/fixtures/topic.rb +0 -3
  482. data/test/fixtures/topics.yml +0 -22
  483. data/test/fixtures/topics/_topic.html.erb +0 -1
  484. data/test/template/active_record_helper_i18n_test.rb +0 -51
  485. data/test/template/active_record_helper_test.rb +0 -302
  486. data/test/template/asset_tag_helper_test.rb +0 -770
  487. data/test/template/atom_feed_helper_test.rb +0 -315
  488. data/test/template/benchmark_helper_test.rb +0 -86
  489. data/test/template/compiled_templates_test.rb +0 -204
  490. data/test/template/date_helper_i18n_test.rb +0 -121
  491. data/test/template/date_helper_test.rb +0 -2603
  492. data/test/template/erb_util_test.rb +0 -36
  493. data/test/template/form_helper_test.rb +0 -1447
  494. data/test/template/form_options_helper_i18n_test.rb +0 -27
  495. data/test/template/form_options_helper_test.rb +0 -811
  496. data/test/template/form_tag_helper_test.rb +0 -356
  497. data/test/template/javascript_helper_test.rb +0 -106
  498. data/test/template/number_helper_i18n_test.rb +0 -69
  499. data/test/template/number_helper_test.rb +0 -132
  500. data/test/template/prototype_helper_test.rb +0 -639
  501. data/test/template/raw_output_helper_test.rb +0 -21
  502. data/test/template/record_tag_helper_test.rb +0 -58
  503. data/test/template/render_test.rb +0 -329
  504. data/test/template/sanitize_helper_test.rb +0 -57
  505. data/test/template/scriptaculous_helper_test.rb +0 -90
  506. data/test/template/tag_helper_test.rb +0 -98
  507. data/test/template/template_test.rb +0 -32
  508. data/test/template/test_test.rb +0 -54
  509. data/test/template/text_helper_test.rb +0 -601
  510. data/test/template/translation_helper_test.rb +0 -95
  511. data/test/template/url_helper_test.rb +0 -641
  512. data/test/testing_sandbox.rb +0 -15
  513. data/test/view/test_case_test.rb +0 -176
@@ -1,197 +0,0 @@
1
- module ActionController
2
- module Routing
3
- class RouteBuilder #:nodoc:
4
- attr_reader :separators, :optional_separators
5
- attr_reader :separator_regexp, :nonseparator_regexp, :interval_regexp
6
-
7
- def initialize
8
- @separators = Routing::SEPARATORS
9
- @optional_separators = %w( / )
10
-
11
- @separator_regexp = /[#{Regexp.escape(separators.join)}]/
12
- @nonseparator_regexp = /\A([^#{Regexp.escape(separators.join)}]+)/
13
- @interval_regexp = /(.*?)(#{separator_regexp}|$)/
14
- end
15
-
16
- # Accepts a "route path" (a string defining a route), and returns the array
17
- # of segments that corresponds to it. Note that the segment array is only
18
- # partially initialized--the defaults and requirements, for instance, need
19
- # to be set separately, via the +assign_route_options+ method, and the
20
- # <tt>optional?</tt> method for each segment will not be reliable until after
21
- # +assign_route_options+ is called, as well.
22
- def segments_for_route_path(path)
23
- rest, segments = path, []
24
-
25
- until rest.empty?
26
- segment, rest = segment_for(rest)
27
- segments << segment
28
- end
29
- segments
30
- end
31
-
32
- # A factory method that returns a new segment instance appropriate for the
33
- # format of the given string.
34
- def segment_for(string)
35
- segment =
36
- case string
37
- when /\A\.(:format)?\//
38
- OptionalFormatSegment.new
39
- when /\A:(\w+)/
40
- key = $1.to_sym
41
- key == :controller ? ControllerSegment.new(key) : DynamicSegment.new(key)
42
- when /\A\*(\w+)/
43
- PathSegment.new($1.to_sym, :optional => true)
44
- when /\A\?(.*?)\?/
45
- StaticSegment.new($1, :optional => true)
46
- when nonseparator_regexp
47
- StaticSegment.new($1)
48
- when separator_regexp
49
- DividerSegment.new($&, :optional => optional_separators.include?($&))
50
- end
51
- [segment, $~.post_match]
52
- end
53
-
54
- # Split the given hash of options into requirement and default hashes. The
55
- # segments are passed alongside in order to distinguish between default values
56
- # and requirements.
57
- def divide_route_options(segments, options)
58
- options = options.except(:path_prefix, :name_prefix)
59
-
60
- if options[:namespace]
61
- options[:controller] = "#{options.delete(:namespace).sub(/\/$/, '')}/#{options[:controller]}"
62
- end
63
-
64
- requirements = (options.delete(:requirements) || {}).dup
65
- defaults = (options.delete(:defaults) || {}).dup
66
- conditions = (options.delete(:conditions) || {}).dup
67
-
68
- validate_route_conditions(conditions)
69
-
70
- path_keys = segments.collect { |segment| segment.key if segment.respond_to?(:key) }.compact
71
- options.each do |key, value|
72
- hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements
73
- hash[key] = value
74
- end
75
-
76
- [defaults, requirements, conditions]
77
- end
78
-
79
- # Takes a hash of defaults and a hash of requirements, and assigns them to
80
- # the segments. Any unused requirements (which do not correspond to a segment)
81
- # are returned as a hash.
82
- def assign_route_options(segments, defaults, requirements)
83
- route_requirements = {} # Requirements that do not belong to a segment
84
-
85
- segment_named = Proc.new do |key|
86
- segments.detect { |segment| segment.key == key if segment.respond_to?(:key) }
87
- end
88
-
89
- requirements.each do |key, requirement|
90
- segment = segment_named[key]
91
- if segment
92
- raise TypeError, "#{key}: requirements on a path segment must be regular expressions" unless requirement.is_a?(Regexp)
93
- if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
94
- raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
95
- end
96
- if requirement.multiline?
97
- raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
98
- end
99
- segment.regexp = requirement
100
- else
101
- route_requirements[key] = requirement
102
- end
103
- end
104
-
105
- defaults.each do |key, default|
106
- segment = segment_named[key]
107
- raise ArgumentError, "#{key}: No matching segment exists; cannot assign default" unless segment
108
- segment.is_optional = true
109
- segment.default = default.to_param if default
110
- end
111
-
112
- assign_default_route_options(segments)
113
- ensure_required_segments(segments)
114
- route_requirements
115
- end
116
-
117
- # Assign default options, such as 'index' as a default for <tt>:action</tt>. This
118
- # method must be run *after* user supplied requirements and defaults have
119
- # been applied to the segments.
120
- def assign_default_route_options(segments)
121
- segments.each do |segment|
122
- next unless segment.is_a? DynamicSegment
123
- case segment.key
124
- when :action
125
- if segment.regexp.nil? || segment.regexp.match('index').to_s == 'index'
126
- segment.default ||= 'index'
127
- segment.is_optional = true
128
- end
129
- when :id
130
- if segment.default.nil? && segment.regexp.nil? || segment.regexp =~ ''
131
- segment.is_optional = true
132
- end
133
- end
134
- end
135
- end
136
-
137
- # Makes sure that there are no optional segments that precede a required
138
- # segment. If any are found that precede a required segment, they are
139
- # made required.
140
- def ensure_required_segments(segments)
141
- allow_optional = true
142
- segments.reverse_each do |segment|
143
- allow_optional &&= segment.optional?
144
- if !allow_optional && segment.optional?
145
- unless segment.optionality_implied?
146
- warn "Route segment \"#{segment.to_s}\" cannot be optional because it precedes a required segment. This segment will be required."
147
- end
148
- segment.is_optional = false
149
- elsif allow_optional && segment.respond_to?(:default) && segment.default
150
- # if a segment has a default, then it is optional
151
- segment.is_optional = true
152
- end
153
- end
154
- end
155
-
156
- # Construct and return a route with the given path and options.
157
- def build(path, options)
158
- # Wrap the path with slashes
159
- path = "/#{path}" unless path[0] == ?/
160
- path = "#{path}/" unless path[-1] == ?/
161
-
162
- prefix = options[:path_prefix].to_s.gsub(/^\//,'')
163
- path = "/#{prefix}#{path}" unless prefix.blank?
164
-
165
- segments = segments_for_route_path(path)
166
- defaults, requirements, conditions = divide_route_options(segments, options)
167
- requirements = assign_route_options(segments, defaults, requirements)
168
-
169
- # TODO: Segments should be frozen on initialize
170
- segments.each { |segment| segment.freeze }
171
-
172
- route = Route.new(segments, requirements, conditions)
173
-
174
- if !route.significant_keys.include?(:controller)
175
- raise ArgumentError, "Illegal route: the :controller must be specified!"
176
- end
177
-
178
- route.freeze
179
- end
180
-
181
- private
182
- def validate_route_conditions(conditions)
183
- if method = conditions[:method]
184
- [method].flatten.each do |m|
185
- if m == :head
186
- raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
187
- end
188
-
189
- unless HTTP_METHODS.include?(m.to_sym)
190
- raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
191
- end
192
- end
193
- end
194
- end
195
- end
196
- end
197
- end
@@ -1,130 +0,0 @@
1
- module ActionController
2
- module Routing
3
- # Much of the slow performance from routes comes from the
4
- # complexity of expiry, <tt>:requirements</tt> matching, defaults providing
5
- # and figuring out which url pattern to use. With named routes
6
- # we can avoid the expense of finding the right route. So if
7
- # they've provided the right number of arguments, and have no
8
- # <tt>:requirements</tt>, we can just build up a string and return it.
9
- #
10
- # To support building optimisations for other common cases, the
11
- # generation code is separated into several classes
12
- module Optimisation
13
- def generate_optimisation_block(route, kind)
14
- return "" unless route.optimise?
15
- OPTIMISERS.inject("") do |memo, klazz|
16
- memo << klazz.new(route, kind).source_code
17
- memo
18
- end
19
- end
20
-
21
- class Optimiser
22
- attr_reader :route, :kind
23
- GLOBAL_GUARD_CONDITIONS = [
24
- "(!defined?(default_url_options) || default_url_options.blank?)",
25
- "(!defined?(controller.default_url_options) || controller.default_url_options.blank?)",
26
- "defined?(request)",
27
- "request"
28
- ]
29
-
30
- def initialize(route, kind)
31
- @route = route
32
- @kind = kind
33
- end
34
-
35
- def guard_conditions
36
- ["false"]
37
- end
38
-
39
- def generation_code
40
- 'nil'
41
- end
42
-
43
- def source_code
44
- if applicable?
45
- guard_condition = (GLOBAL_GUARD_CONDITIONS + guard_conditions).join(" && ")
46
- "return #{generation_code} if #{guard_condition}\n"
47
- else
48
- "\n"
49
- end
50
- end
51
-
52
- # Temporarily disabled <tt>:url</tt> optimisation pending proper solution to
53
- # Issues around request.host etc.
54
- def applicable?
55
- true
56
- end
57
- end
58
-
59
- # Given a route
60
- #
61
- # map.person '/people/:id'
62
- #
63
- # If the user calls <tt>person_url(@person)</tt>, we can simply
64
- # return a string like "/people/#{@person.to_param}"
65
- # rather than triggering the expensive logic in +url_for+.
66
- class PositionalArguments < Optimiser
67
- def guard_conditions
68
- number_of_arguments = route.required_segment_keys.size
69
- # if they're using foo_url(:id=>2) it's one
70
- # argument, but we don't want to generate /foos/id2
71
- if number_of_arguments == 1
72
- ["args.size == 1", "!args.first.is_a?(Hash)"]
73
- else
74
- ["args.size == #{number_of_arguments}"]
75
- end
76
- end
77
-
78
- def generation_code
79
- elements = []
80
- idx = 0
81
-
82
- if kind == :url
83
- elements << '#{request.protocol}'
84
- elements << '#{request.host_with_port}'
85
- end
86
-
87
- elements << '#{ActionController::Base.relative_url_root if ActionController::Base.relative_url_root}'
88
-
89
- # The last entry in <tt>route.segments</tt> appears to *always* be a
90
- # 'divider segment' for '/' but we have assertions to ensure that
91
- # we don't include the trailing slashes, so skip them.
92
- (route.segments.size == 1 ? route.segments : route.segments[0..-2]).each do |segment|
93
- if segment.is_a?(DynamicSegment)
94
- elements << segment.interpolation_chunk("args[#{idx}].to_param")
95
- idx += 1
96
- else
97
- elements << segment.interpolation_chunk
98
- end
99
- end
100
- %("#{elements * ''}")
101
- end
102
- end
103
-
104
- # This case is mostly the same as the positional arguments case
105
- # above, but it supports additional query parameters as the last
106
- # argument
107
- class PositionalArgumentsWithAdditionalParams < PositionalArguments
108
- def guard_conditions
109
- ["args.size == #{route.segment_keys.size + 1}"] +
110
- UrlRewriter::RESERVED_OPTIONS.collect{ |key| "!args.last.has_key?(:#{key})" }
111
- end
112
-
113
- # This case uses almost the same code as positional arguments,
114
- # but add a question mark and args.last.to_query on the end,
115
- # unless the last arg is empty
116
- def generation_code
117
- super.insert(-2, '#{\'?\' + args.last.to_query unless args.last.empty?}')
118
- end
119
-
120
- # To avoid generating "http://localhost/?host=foo.example.com" we
121
- # can't use this optimisation on routes without any segments
122
- def applicable?
123
- super && route.segment_keys.size > 0
124
- end
125
- end
126
-
127
- OPTIMISERS = [PositionalArguments, PositionalArgumentsWithAdditionalParams]
128
- end
129
- end
130
- end
@@ -1,167 +0,0 @@
1
- module ActionController
2
- module Routing
3
- # BEFORE: 0.191446860631307 ms/url
4
- # AFTER: 0.029847304022858 ms/url
5
- # Speed up: 6.4 times
6
- #
7
- # Route recognition is slow due to one-by-one iterating over
8
- # a whole routeset (each map.resources generates at least 14 routes)
9
- # and matching weird regexps on each step.
10
- #
11
- # We optimize this by skipping all URI segments that 100% sure can't
12
- # be matched, moving deeper in a tree of routes (where node == segment)
13
- # until first possible match is accured. In such case, we start walking
14
- # a flat list of routes, matching them with accurate matcher.
15
- # So, first step: search a segment tree for the first relevant index.
16
- # Second step: iterate routes starting with that index.
17
- #
18
- # How tree is walked? We can do a recursive tests, but it's smarter:
19
- # We just create a tree of if-s and elsif-s matching segments.
20
- #
21
- # We have segments of 3 flavors:
22
- # 1) nil (no segment, route finished)
23
- # 2) const-dot-dynamic (like "/posts.:xml", "/preview.:size.jpg")
24
- # 3) const (like "/posts", "/comments")
25
- # 4) dynamic ("/:id", "file.:size.:extension")
26
- #
27
- # We split incoming string into segments and iterate over them.
28
- # When segment is nil, we drop immediately, on a current node index.
29
- # When segment is equal to some const, we step into branch.
30
- # If none constants matched, we step into 'dynamic' branch (it's a last).
31
- # If we can't match anything, we drop to last index on a level.
32
- #
33
- # Note: we maintain the original routes order, so we finish building
34
- # steps on a first dynamic segment.
35
- #
36
- #
37
- # Example. Given the routes:
38
- # 0 /posts/
39
- # 1 /posts/:id
40
- # 2 /posts/:id/comments
41
- # 3 /posts/blah
42
- # 4 /users/
43
- # 5 /users/:id
44
- # 6 /users/:id/profile
45
- #
46
- # request_uri = /users/123
47
- #
48
- # There will be only 4 iterations:
49
- # 1) segm test for /posts prefix, skip all /posts/* routes
50
- # 2) segm test for /users/
51
- # 3) segm test for /users/:id
52
- # (jump to list index = 5)
53
- # 4) full test for /users/:id => here we are!
54
- class RouteSet
55
- def recognize_path(path, environment={})
56
- result = recognize_optimized(path, environment) and return result
57
-
58
- # Route was not recognized. Try to find out why (maybe wrong verb).
59
- allows = HTTP_METHODS.select { |verb| routes.find { |r| r.recognize(path, environment.merge(:method => verb)) } }
60
-
61
- if environment[:method] && !HTTP_METHODS.include?(environment[:method])
62
- raise NotImplemented.new(*allows)
63
- elsif !allows.empty?
64
- raise MethodNotAllowed.new(*allows)
65
- else
66
- raise RoutingError, "No route matches #{path.inspect} with #{environment.inspect}"
67
- end
68
- end
69
-
70
- def segment_tree(routes)
71
- tree = [0]
72
-
73
- i = -1
74
- routes.each do |route|
75
- i += 1
76
- # not fast, but runs only once
77
- segments = to_plain_segments(route.segments.inject("") { |str,s| str << s.to_s })
78
-
79
- node = tree
80
- segments.each do |seg|
81
- seg = :dynamic if seg && seg[0] == ?:
82
- node << [seg, [i]] if node.empty? || node[node.size - 1][0] != seg
83
- node = node[node.size - 1][1]
84
- end
85
- end
86
- tree
87
- end
88
-
89
- def generate_code(list, padding=' ', level = 0)
90
- # a digit
91
- return padding + "#{list[0]}\n" if list.size == 1 && !(Array === list[0])
92
-
93
- body = padding + "(seg = segments[#{level}]; \n"
94
-
95
- i = 0
96
- was_nil = false
97
- list.each do |item|
98
- if Array === item
99
- i += 1
100
- start = (i == 1)
101
- tag, sub = item
102
- if tag == :dynamic
103
- body += padding + "#{start ? 'if' : 'elsif'} true\n"
104
- body += generate_code(sub, padding + " ", level + 1)
105
- break
106
- elsif tag == nil && !was_nil
107
- was_nil = true
108
- body += padding + "#{start ? 'if' : 'elsif'} seg.nil?\n"
109
- body += generate_code(sub, padding + " ", level + 1)
110
- else
111
- body += padding + "#{start ? 'if' : 'elsif'} seg == '#{tag}'\n"
112
- body += generate_code(sub, padding + " ", level + 1)
113
- end
114
- end
115
- end
116
- body += padding + "else\n"
117
- body += padding + " #{list[0]}\n"
118
- body += padding + "end)\n"
119
- body
120
- end
121
-
122
- # this must be really fast
123
- def to_plain_segments(str)
124
- str = str.dup
125
- str.sub!(/^\/+/,'')
126
- str.sub!(/\/+$/,'')
127
- segments = str.split(/\.[^\/]+\/+|\/+|\.[^\/]+\Z/) # cut off ".format" also
128
- segments << nil
129
- segments
130
- end
131
-
132
- private
133
- def write_recognize_optimized!
134
- tree = segment_tree(routes)
135
- body = generate_code(tree)
136
-
137
- remove_recognize_optimized!
138
-
139
- instance_eval %{
140
- def recognize_optimized(path, env)
141
- segments = to_plain_segments(path)
142
- index = #{body}
143
- return nil unless index
144
- while index < routes.size
145
- result = routes[index].recognize(path, env) and return result
146
- index += 1
147
- end
148
- nil
149
- end
150
- }, '(recognize_optimized)', 1
151
- end
152
-
153
- def clear_recognize_optimized!
154
- remove_recognize_optimized!
155
- write_recognize_optimized!
156
- end
157
-
158
- def remove_recognize_optimized!
159
- if respond_to?(:recognize_optimized)
160
- class << self
161
- remove_method :recognize_optimized
162
- end
163
- end
164
- end
165
- end
166
- end
167
- end