eactionpack 2.1.2

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 (338) hide show
  1. data/CHANGELOG +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +469 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +146 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller.rb +79 -0
  8. data/lib/action_controller/assertions.rb +69 -0
  9. data/lib/action_controller/assertions/dom_assertions.rb +39 -0
  10. data/lib/action_controller/assertions/model_assertions.rb +20 -0
  11. data/lib/action_controller/assertions/response_assertions.rb +172 -0
  12. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  13. data/lib/action_controller/assertions/selector_assertions.rb +491 -0
  14. data/lib/action_controller/assertions/tag_assertions.rb +130 -0
  15. data/lib/action_controller/base.rb +1288 -0
  16. data/lib/action_controller/benchmarking.rb +94 -0
  17. data/lib/action_controller/caching.rb +72 -0
  18. data/lib/action_controller/caching/actions.rb +144 -0
  19. data/lib/action_controller/caching/fragments.rb +138 -0
  20. data/lib/action_controller/caching/pages.rb +154 -0
  21. data/lib/action_controller/caching/sql_cache.rb +18 -0
  22. data/lib/action_controller/caching/sweeping.rb +97 -0
  23. data/lib/action_controller/cgi_ext.rb +16 -0
  24. data/lib/action_controller/cgi_ext/cookie.rb +110 -0
  25. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  26. data/lib/action_controller/cgi_ext/session.rb +73 -0
  27. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  28. data/lib/action_controller/cgi_process.rb +223 -0
  29. data/lib/action_controller/components.rb +166 -0
  30. data/lib/action_controller/cookies.rb +96 -0
  31. data/lib/action_controller/dispatcher.rb +162 -0
  32. data/lib/action_controller/filters.rb +642 -0
  33. data/lib/action_controller/flash.rb +172 -0
  34. data/lib/action_controller/headers.rb +31 -0
  35. data/lib/action_controller/helpers.rb +221 -0
  36. data/lib/action_controller/http_authentication.rb +124 -0
  37. data/lib/action_controller/integration.rb +634 -0
  38. data/lib/action_controller/layout.rb +309 -0
  39. data/lib/action_controller/mime_responds.rb +173 -0
  40. data/lib/action_controller/mime_type.rb +186 -0
  41. data/lib/action_controller/mime_types.rb +20 -0
  42. data/lib/action_controller/polymorphic_routes.rb +191 -0
  43. data/lib/action_controller/record_identifier.rb +102 -0
  44. data/lib/action_controller/request.rb +764 -0
  45. data/lib/action_controller/request_forgery_protection.rb +140 -0
  46. data/lib/action_controller/request_profiler.rb +169 -0
  47. data/lib/action_controller/rescue.rb +258 -0
  48. data/lib/action_controller/resources.rb +572 -0
  49. data/lib/action_controller/response.rb +76 -0
  50. data/lib/action_controller/routing.rb +387 -0
  51. data/lib/action_controller/routing/builder.rb +203 -0
  52. data/lib/action_controller/routing/optimisations.rb +120 -0
  53. data/lib/action_controller/routing/recognition_optimisation.rb +162 -0
  54. data/lib/action_controller/routing/route.rb +240 -0
  55. data/lib/action_controller/routing/route_set.rb +436 -0
  56. data/lib/action_controller/routing/routing_ext.rb +46 -0
  57. data/lib/action_controller/routing/segments.rb +283 -0
  58. data/lib/action_controller/session/active_record_store.rb +340 -0
  59. data/lib/action_controller/session/cookie_store.rb +166 -0
  60. data/lib/action_controller/session/drb_server.rb +32 -0
  61. data/lib/action_controller/session/drb_store.rb +35 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +98 -0
  63. data/lib/action_controller/session_management.rb +158 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +155 -0
  66. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  67. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  68. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  69. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  70. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  71. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  72. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  73. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  74. data/lib/action_controller/test_case.rb +83 -0
  75. data/lib/action_controller/test_process.rb +526 -0
  76. data/lib/action_controller/url_rewriter.rb +142 -0
  77. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  78. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  79. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  80. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  81. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  82. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  83. data/lib/action_controller/verification.rb +130 -0
  84. data/lib/action_pack.rb +24 -0
  85. data/lib/action_pack/version.rb +9 -0
  86. data/lib/action_view.rb +44 -0
  87. data/lib/action_view/base.rb +335 -0
  88. data/lib/action_view/helpers/active_record_helper.rb +276 -0
  89. data/lib/action_view/helpers/asset_tag_helper.rb +599 -0
  90. data/lib/action_view/helpers/atom_feed_helper.rb +143 -0
  91. data/lib/action_view/helpers/benchmark_helper.rb +33 -0
  92. data/lib/action_view/helpers/cache_helper.rb +40 -0
  93. data/lib/action_view/helpers/capture_helper.rb +161 -0
  94. data/lib/action_view/helpers/date_helper.rb +711 -0
  95. data/lib/action_view/helpers/debug_helper.rb +31 -0
  96. data/lib/action_view/helpers/form_helper.rb +767 -0
  97. data/lib/action_view/helpers/form_options_helper.rb +458 -0
  98. data/lib/action_view/helpers/form_tag_helper.rb +458 -0
  99. data/lib/action_view/helpers/javascript_helper.rb +148 -0
  100. data/lib/action_view/helpers/number_helper.rb +186 -0
  101. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  102. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  103. data/lib/action_view/helpers/sanitize_helper.rb +229 -0
  104. data/lib/action_view/helpers/tag_helper.rb +134 -0
  105. data/lib/action_view/helpers/text_helper.rb +507 -0
  106. data/lib/action_view/helpers/url_helper.rb +573 -0
  107. data/lib/action_view/inline_template.rb +20 -0
  108. data/lib/action_view/partial_template.rb +70 -0
  109. data/lib/action_view/partials.rb +158 -0
  110. data/lib/action_view/template.rb +125 -0
  111. data/lib/action_view/template_error.rb +110 -0
  112. data/lib/action_view/template_finder.rb +176 -0
  113. data/lib/action_view/template_handler.rb +34 -0
  114. data/lib/action_view/template_handlers/builder.rb +27 -0
  115. data/lib/action_view/template_handlers/compilable.rb +128 -0
  116. data/lib/action_view/template_handlers/erb.rb +56 -0
  117. data/lib/action_view/test_case.rb +58 -0
  118. data/lib/actionpack.rb +1 -0
  119. data/test/abstract_unit.rb +36 -0
  120. data/test/active_record_unit.rb +105 -0
  121. data/test/activerecord/active_record_store_test.rb +141 -0
  122. data/test/activerecord/render_partial_with_record_identification_test.rb +191 -0
  123. data/test/adv_attr_test.rb +20 -0
  124. data/test/controller/action_pack_assertions_test.rb +543 -0
  125. data/test/controller/addresses_render_test.rb +43 -0
  126. data/test/controller/assert_select_test.rb +331 -0
  127. data/test/controller/base_test.rb +219 -0
  128. data/test/controller/benchmark_test.rb +32 -0
  129. data/test/controller/caching_test.rb +581 -0
  130. data/test/controller/capture_test.rb +89 -0
  131. data/test/controller/cgi_test.rb +116 -0
  132. data/test/controller/components_test.rb +140 -0
  133. data/test/controller/content_type_test.rb +139 -0
  134. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  135. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  136. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  137. data/test/controller/cookie_test.rb +146 -0
  138. data/test/controller/custom_handler_test.rb +45 -0
  139. data/test/controller/deprecation/deprecated_base_methods_test.rb +37 -0
  140. data/test/controller/dispatcher_test.rb +105 -0
  141. data/test/controller/fake_controllers.rb +33 -0
  142. data/test/controller/fake_models.rb +11 -0
  143. data/test/controller/filter_params_test.rb +49 -0
  144. data/test/controller/filters_test.rb +881 -0
  145. data/test/controller/flash_test.rb +146 -0
  146. data/test/controller/header_test.rb +14 -0
  147. data/test/controller/helper_test.rb +210 -0
  148. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  149. data/test/controller/html-scanner/document_test.rb +148 -0
  150. data/test/controller/html-scanner/node_test.rb +89 -0
  151. data/test/controller/html-scanner/sanitizer_test.rb +269 -0
  152. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  153. data/test/controller/html-scanner/text_node_test.rb +50 -0
  154. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  155. data/test/controller/http_authentication_test.rb +54 -0
  156. data/test/controller/integration_test.rb +252 -0
  157. data/test/controller/integration_upload_test.rb +43 -0
  158. data/test/controller/layout_test.rb +255 -0
  159. data/test/controller/mime_responds_test.rb +514 -0
  160. data/test/controller/mime_type_test.rb +84 -0
  161. data/test/controller/new_render_test.rb +843 -0
  162. data/test/controller/polymorphic_routes_test.rb +174 -0
  163. data/test/controller/record_identifier_test.rb +139 -0
  164. data/test/controller/redirect_test.rb +289 -0
  165. data/test/controller/render_test.rb +484 -0
  166. data/test/controller/request_forgery_protection_test.rb +305 -0
  167. data/test/controller/request_test.rb +928 -0
  168. data/test/controller/rescue_test.rb +517 -0
  169. data/test/controller/resources_test.rb +873 -0
  170. data/test/controller/routing_test.rb +2464 -0
  171. data/test/controller/selector_test.rb +628 -0
  172. data/test/controller/send_file_test.rb +138 -0
  173. data/test/controller/session/cookie_store_test.rb +258 -0
  174. data/test/controller/session/mem_cache_store_test.rb +181 -0
  175. data/test/controller/session_fixation_test.rb +89 -0
  176. data/test/controller/session_management_test.rb +178 -0
  177. data/test/controller/test_test.rb +695 -0
  178. data/test/controller/url_rewriter_test.rb +310 -0
  179. data/test/controller/verification_test.rb +270 -0
  180. data/test/controller/view_paths_test.rb +140 -0
  181. data/test/controller/webservice_test.rb +229 -0
  182. data/test/fixtures/addresses/list.erb +1 -0
  183. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  184. data/test/fixtures/companies.yml +24 -0
  185. data/test/fixtures/company.rb +10 -0
  186. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  187. data/test/fixtures/content_type/render_default_for_js.js.erb +1 -0
  188. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  189. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  190. data/test/fixtures/customers/_customer.html.erb +1 -0
  191. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  192. data/test/fixtures/developer.rb +9 -0
  193. data/test/fixtures/developers.yml +21 -0
  194. data/test/fixtures/developers_projects.yml +13 -0
  195. data/test/fixtures/fun/games/hello_world.erb +1 -0
  196. data/test/fixtures/functional_caching/_partial.erb +3 -0
  197. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  198. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  199. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  200. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  201. data/test/fixtures/helpers/abc_helper.rb +5 -0
  202. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  203. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  204. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  205. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  206. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  207. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  208. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  209. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  210. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  211. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  212. data/test/fixtures/layouts/builder.builder +3 -0
  213. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  214. data/test/fixtures/layouts/standard.erb +1 -0
  215. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  216. data/test/fixtures/layouts/yield.erb +2 -0
  217. data/test/fixtures/mascot.rb +3 -0
  218. data/test/fixtures/mascots.yml +4 -0
  219. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  220. data/test/fixtures/multipart/binary_file +0 -0
  221. data/test/fixtures/multipart/boundary_problem_file +10 -0
  222. data/test/fixtures/multipart/bracketed_param +5 -0
  223. data/test/fixtures/multipart/large_text_file +10 -0
  224. data/test/fixtures/multipart/mixed_files +0 -0
  225. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  226. data/test/fixtures/multipart/single_parameter +5 -0
  227. data/test/fixtures/multipart/text_file +10 -0
  228. data/test/fixtures/override/test/hello_world.erb +1 -0
  229. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  230. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  231. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  232. data/test/fixtures/post_test/post/index.html.erb +1 -0
  233. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  234. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  235. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  236. data/test/fixtures/project.rb +3 -0
  237. data/test/fixtures/projects.yml +7 -0
  238. data/test/fixtures/public/404.html +1 -0
  239. data/test/fixtures/public/500.html +1 -0
  240. data/test/fixtures/public/images/rails.png +0 -0
  241. data/test/fixtures/public/javascripts/application.js +1 -0
  242. data/test/fixtures/public/javascripts/bank.js +1 -0
  243. data/test/fixtures/public/javascripts/robber.js +1 -0
  244. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  245. data/test/fixtures/public/stylesheets/bank.css +1 -0
  246. data/test/fixtures/public/stylesheets/robber.css +1 -0
  247. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  248. data/test/fixtures/replies.yml +15 -0
  249. data/test/fixtures/reply.rb +7 -0
  250. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  251. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  252. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  253. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  254. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  255. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  256. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  257. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  258. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  259. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  260. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  261. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  262. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  263. data/test/fixtures/scope/test/modgreet.erb +1 -0
  264. data/test/fixtures/shared.html.erb +1 -0
  265. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  266. data/test/fixtures/test/_customer.erb +1 -0
  267. data/test/fixtures/test/_customer_counter.erb +1 -0
  268. data/test/fixtures/test/_customer_greeting.erb +1 -0
  269. data/test/fixtures/test/_form.erb +1 -0
  270. data/test/fixtures/test/_hash_greeting.erb +1 -0
  271. data/test/fixtures/test/_hash_object.erb +2 -0
  272. data/test/fixtures/test/_hello.builder +1 -0
  273. data/test/fixtures/test/_labelling_form.erb +1 -0
  274. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  275. data/test/fixtures/test/_partial.erb +1 -0
  276. data/test/fixtures/test/_partial.html.erb +1 -0
  277. data/test/fixtures/test/_partial.js.erb +1 -0
  278. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  279. data/test/fixtures/test/_partial_only.erb +1 -0
  280. data/test/fixtures/test/_person.erb +2 -0
  281. data/test/fixtures/test/_raise.html.erb +1 -0
  282. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  283. data/test/fixtures/test/block_content_for.erb +2 -0
  284. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  285. data/test/fixtures/test/capturing.erb +4 -0
  286. data/test/fixtures/test/content_for.erb +2 -0
  287. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  288. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  289. data/test/fixtures/test/delete_with_js.rjs +2 -0
  290. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  291. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  292. data/test/fixtures/test/erb_content_for.erb +2 -0
  293. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  294. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  295. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  296. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  297. data/test/fixtures/test/greeting.erb +1 -0
  298. data/test/fixtures/test/greeting.js.rjs +1 -0
  299. data/test/fixtures/test/hello.builder +4 -0
  300. data/test/fixtures/test/hello_world.erb +1 -0
  301. data/test/fixtures/test/hello_world_container.builder +3 -0
  302. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  303. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  304. data/test/fixtures/test/hello_xml_world.builder +11 -0
  305. data/test/fixtures/test/list.erb +1 -0
  306. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  307. data/test/fixtures/test/potential_conflicts.erb +4 -0
  308. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  309. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  310. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  311. data/test/fixtures/test/render_to_string_test.erb +1 -0
  312. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  313. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  314. data/test/fixtures/topic.rb +3 -0
  315. data/test/fixtures/topics.yml +22 -0
  316. data/test/fixtures/topics/_topic.html.erb +1 -0
  317. data/test/template/active_record_helper_test.rb +268 -0
  318. data/test/template/asset_tag_helper_test.rb +514 -0
  319. data/test/template/atom_feed_helper_test.rb +179 -0
  320. data/test/template/benchmark_helper_test.rb +60 -0
  321. data/test/template/date_helper_test.rb +1791 -0
  322. data/test/template/deprecated_erb_variable_test.rb +9 -0
  323. data/test/template/erb_util_test.rb +24 -0
  324. data/test/template/form_helper_test.rb +885 -0
  325. data/test/template/form_options_helper_test.rb +1333 -0
  326. data/test/template/form_tag_helper_test.rb +272 -0
  327. data/test/template/javascript_helper_test.rb +73 -0
  328. data/test/template/number_helper_test.rb +97 -0
  329. data/test/template/record_tag_helper_test.rb +54 -0
  330. data/test/template/sanitize_helper_test.rb +48 -0
  331. data/test/template/tag_helper_test.rb +77 -0
  332. data/test/template/template_finder_test.rb +73 -0
  333. data/test/template/template_object_test.rb +95 -0
  334. data/test/template/test_test.rb +56 -0
  335. data/test/template/text_helper_test.rb +367 -0
  336. data/test/template/url_helper_test.rb +544 -0
  337. data/test/testing_sandbox.rb +15 -0
  338. metadata +469 -0
@@ -0,0 +1,76 @@
1
+ require 'digest/md5'
2
+
3
+ module ActionController
4
+ class AbstractResponse #:nodoc:
5
+ DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
6
+ attr_accessor :request
7
+ attr_accessor :body, :headers, :session, :cookies, :assigns, :template, :redirected_to, :redirected_to_method_params, :layout
8
+
9
+ def initialize
10
+ @body, @headers, @session, @assigns = "", DEFAULT_HEADERS.merge("cookie" => []), [], []
11
+ end
12
+
13
+ def content_type=(mime_type)
14
+ self.headers["Content-Type"] = charset ? "#{mime_type}; charset=#{charset}" : mime_type
15
+ end
16
+
17
+ def content_type
18
+ content_type = String(headers["Content-Type"] || headers["type"]).split(";")[0]
19
+ content_type.blank? ? nil : content_type
20
+ end
21
+
22
+ def charset=(encoding)
23
+ self.headers["Content-Type"] = "#{content_type || Mime::HTML}; charset=#{encoding}"
24
+ end
25
+
26
+ def charset
27
+ charset = String(headers["Content-Type"] || headers["type"]).split(";")[1]
28
+ charset.blank? ? nil : charset.strip.split("=")[1]
29
+ end
30
+
31
+ def redirect(to_url, response_status)
32
+ self.headers["Status"] = response_status
33
+ self.headers["Location"] = to_url.gsub(/[\r\n]/, '')
34
+
35
+ self.body = "<html><body>You are being <a href=\"#{CGI.escapeHTML(to_url)}\">redirected</a>.</body></html>"
36
+ end
37
+
38
+ def prepare!
39
+ handle_conditional_get!
40
+ convert_content_type!
41
+ set_content_length!
42
+ end
43
+
44
+
45
+ private
46
+ def handle_conditional_get!
47
+ if body.is_a?(String) && (headers['Status'] ? headers['Status'][0..2] == '200' : true) && !body.empty?
48
+ self.headers['ETag'] ||= %("#{Digest::MD5.hexdigest(body)}")
49
+ self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
50
+
51
+ if request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
52
+ self.headers['Status'] = '304 Not Modified'
53
+ self.body = ''
54
+ end
55
+ end
56
+ end
57
+
58
+ def convert_content_type!
59
+ if content_type = headers.delete("Content-Type")
60
+ self.headers["type"] = content_type
61
+ end
62
+ if content_type = headers.delete("Content-type")
63
+ self.headers["type"] = content_type
64
+ end
65
+ if content_type = headers.delete("content-type")
66
+ self.headers["type"] = content_type
67
+ end
68
+ end
69
+
70
+ # Don't set the Content-Length for block-based bodies as that would mean reading it all into memory. Not nice
71
+ # for, say, a 2GB streaming file.
72
+ def set_content_length!
73
+ self.headers["Content-Length"] = body.size unless body.respond_to?(:call)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,387 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'action_controller/polymorphic_routes'
4
+ require 'action_controller/routing/optimisations'
5
+ require 'action_controller/routing/routing_ext'
6
+ require 'action_controller/routing/route'
7
+ require 'action_controller/routing/segments'
8
+ require 'action_controller/routing/builder'
9
+ require 'action_controller/routing/route_set'
10
+ require 'action_controller/routing/recognition_optimisation'
11
+
12
+ module ActionController
13
+ # == Routing
14
+ #
15
+ # The routing module provides URL rewriting in native Ruby. It's a way to
16
+ # redirect incoming requests to controllers and actions. This replaces
17
+ # mod_rewrite rules. Best of all, Rails' Routing works with any web server.
18
+ # Routes are defined in <tt>config/routes.rb</tt>.
19
+ #
20
+ # Consider the following route, installed by Rails when you generate your
21
+ # application:
22
+ #
23
+ # map.connect ':controller/:action/:id'
24
+ #
25
+ # This route states that it expects requests to consist of a
26
+ # <tt>:controller</tt> followed by an <tt>:action</tt> that in turn is fed
27
+ # some <tt>:id</tt>.
28
+ #
29
+ # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end up
30
+ # with:
31
+ #
32
+ # params = { :controller => 'blog',
33
+ # :action => 'edit',
34
+ # :id => '22'
35
+ # }
36
+ #
37
+ # Think of creating routes as drawing a map for your requests. The map tells
38
+ # them where to go based on some predefined pattern:
39
+ #
40
+ # ActionController::Routing::Routes.draw do |map|
41
+ # Pattern 1 tells some request to go to one place
42
+ # Pattern 2 tell them to go to another
43
+ # ...
44
+ # end
45
+ #
46
+ # The following symbols are special:
47
+ #
48
+ # :controller maps to your controller name
49
+ # :action maps to an action with your controllers
50
+ #
51
+ # Other names simply map to a parameter as in the case of <tt>:id</tt>.
52
+ #
53
+ # == Route priority
54
+ #
55
+ # Not all routes are created equally. Routes have priority defined by the
56
+ # order of appearance of the routes in the <tt>config/routes.rb</tt> file. The priority goes
57
+ # from top to bottom. The last route in that file is at the lowest priority
58
+ # and will be applied last. If no route matches, 404 is returned.
59
+ #
60
+ # Within blocks, the empty pattern is at the highest priority.
61
+ # In practice this works out nicely:
62
+ #
63
+ # ActionController::Routing::Routes.draw do |map|
64
+ # map.with_options :controller => 'blog' do |blog|
65
+ # blog.show '', :action => 'list'
66
+ # end
67
+ # map.connect ':controller/:action/:view'
68
+ # end
69
+ #
70
+ # In this case, invoking blog controller (with an URL like '/blog/')
71
+ # without parameters will activate the 'list' action by default.
72
+ #
73
+ # == Defaults routes and default parameters
74
+ #
75
+ # Setting a default route is straightforward in Rails - you simply append a
76
+ # Hash at the end of your mapping to set any default parameters.
77
+ #
78
+ # Example:
79
+ #
80
+ # ActionController::Routing:Routes.draw do |map|
81
+ # map.connect ':controller/:action/:id', :controller => 'blog'
82
+ # end
83
+ #
84
+ # This sets up +blog+ as the default controller if no other is specified.
85
+ # This means visiting '/' would invoke the blog controller.
86
+ #
87
+ # More formally, you can define defaults in a route with the <tt>:defaults</tt> key.
88
+ #
89
+ # map.connect ':controller/:action/:id', :action => 'show', :defaults => { :page => 'Dashboard' }
90
+ #
91
+ # Note: The default routes, as provided by the Rails generator, make all actions in every
92
+ # controller accessible via GET requests. You should consider removing them or commenting
93
+ # them out if you're using named routes and resources.
94
+ #
95
+ # == Named routes
96
+ #
97
+ # Routes can be named with the syntax <tt>map.name_of_route options</tt>,
98
+ # allowing for easy reference within your source as +name_of_route_url+
99
+ # for the full URL and +name_of_route_path+ for the URI path.
100
+ #
101
+ # Example:
102
+ #
103
+ # # In routes.rb
104
+ # map.login 'login', :controller => 'accounts', :action => 'login'
105
+ #
106
+ # # With render, redirect_to, tests, etc.
107
+ # redirect_to login_url
108
+ #
109
+ # Arguments can be passed as well.
110
+ #
111
+ # redirect_to show_item_path(:id => 25)
112
+ #
113
+ # Use <tt>map.root</tt> as a shorthand to name a route for the root path "".
114
+ #
115
+ # # In routes.rb
116
+ # map.root :controller => 'blogs'
117
+ #
118
+ # # would recognize http://www.example.com/ as
119
+ # params = { :controller => 'blogs', :action => 'index' }
120
+ #
121
+ # # and provide these named routes
122
+ # root_url # => 'http://www.example.com/'
123
+ # root_path # => ''
124
+ #
125
+ # You can also specify an already-defined named route in your <tt>map.root</tt> call:
126
+ #
127
+ # # In routes.rb
128
+ # map.new_session :controller => 'sessions', :action => 'new'
129
+ # map.root :new_session
130
+ #
131
+ # Note: when using +with_options+, the route is simply named after the
132
+ # method you call on the block parameter rather than map.
133
+ #
134
+ # # In routes.rb
135
+ # map.with_options :controller => 'blog' do |blog|
136
+ # blog.show '', :action => 'list'
137
+ # blog.delete 'delete/:id', :action => 'delete',
138
+ # blog.edit 'edit/:id', :action => 'edit'
139
+ # end
140
+ #
141
+ # # provides named routes for show, delete, and edit
142
+ # link_to @article.title, show_path(:id => @article.id)
143
+ #
144
+ # == Pretty URLs
145
+ #
146
+ # Routes can generate pretty URLs. For example:
147
+ #
148
+ # map.connect 'articles/:year/:month/:day',
149
+ # :controller => 'articles',
150
+ # :action => 'find_by_date',
151
+ # :year => /\d{4}/,
152
+ # :month => /\d{1,2}/,
153
+ # :day => /\d{1,2}/
154
+ #
155
+ # Using the route above, the URL "http://localhost:3000/articles/2005/11/06"
156
+ # maps to
157
+ #
158
+ # params = {:year => '2005', :month => '11', :day => '06'}
159
+ #
160
+ # == Regular Expressions and parameters
161
+ # You can specify a regular expression to define a format for a parameter.
162
+ #
163
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
164
+ # :action => 'show', :postalcode => /\d{5}(-\d{4})?/
165
+ #
166
+ # or, more formally:
167
+ #
168
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
169
+ # :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
170
+ #
171
+ # Formats can include the 'ignorecase' and 'extended syntax' regular
172
+ # expression modifiers:
173
+ #
174
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
175
+ # :action => 'show', :postalcode => /hx\d\d\s\d[a-z]{2}/i
176
+ #
177
+ # map.geocode 'geocode/:postalcode', :controller => 'geocode',
178
+ # :action => 'show',:requirements => {
179
+ # :postalcode => /# Postcode format
180
+ # \d{5} #Prefix
181
+ # (-\d{4})? #Suffix
182
+ # /x
183
+ # }
184
+ #
185
+ # Using the multiline match modifier will raise an ArgumentError.
186
+ # Encoding regular expression modifiers are silently ignored. The
187
+ # match will always use the default encoding or ASCII.
188
+ #
189
+ # == Route globbing
190
+ #
191
+ # Specifying <tt>*[string]</tt> as part of a rule like:
192
+ #
193
+ # map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
194
+ #
195
+ # will glob all remaining parts of the route that were not recognized earlier. This idiom
196
+ # must appear at the end of the path. The globbed values are in <tt>params[:path]</tt> in
197
+ # this case.
198
+ #
199
+ # == Route conditions
200
+ #
201
+ # With conditions you can define restrictions on routes. Currently the only valid condition is <tt>:method</tt>.
202
+ #
203
+ # * <tt>:method</tt> - Allows you to specify which method can access the route. Possible values are <tt>:post</tt>,
204
+ # <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>. The default value is <tt>:any</tt>,
205
+ # <tt>:any</tt> means that any method can access the route.
206
+ #
207
+ # Example:
208
+ #
209
+ # map.connect 'post/:id', :controller => 'posts', :action => 'show',
210
+ # :conditions => { :method => :get }
211
+ # map.connect 'post/:id', :controller => 'posts', :action => 'create_comment',
212
+ # :conditions => { :method => :post }
213
+ #
214
+ # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
215
+ # URL will route to the <tt>show</tt> action.
216
+ #
217
+ # == Reloading routes
218
+ #
219
+ # You can reload routes if you feel you must:
220
+ #
221
+ # ActionController::Routing::Routes.reload
222
+ #
223
+ # This will clear all named routes and reload routes.rb if the file has been modified from
224
+ # last load. To absolutely force reloading, use <tt>reload!</tt>.
225
+ #
226
+ # == Testing Routes
227
+ #
228
+ # The two main methods for testing your routes:
229
+ #
230
+ # === +assert_routing+
231
+ #
232
+ # def test_movie_route_properly_splits
233
+ # opts = {:controller => "plugin", :action => "checkout", :id => "2"}
234
+ # assert_routing "plugin/checkout/2", opts
235
+ # end
236
+ #
237
+ # +assert_routing+ lets you test whether or not the route properly resolves into options.
238
+ #
239
+ # === +assert_recognizes+
240
+ #
241
+ # def test_route_has_options
242
+ # opts = {:controller => "plugin", :action => "show", :id => "12"}
243
+ # assert_recognizes opts, "/plugins/show/12"
244
+ # end
245
+ #
246
+ # Note the subtle difference between the two: +assert_routing+ tests that
247
+ # a URL fits options while +assert_recognizes+ tests that a URL
248
+ # breaks into parameters properly.
249
+ #
250
+ # In tests you can simply pass the URL or named route to +get+ or +post+.
251
+ #
252
+ # def send_to_jail
253
+ # get '/jail'
254
+ # assert_response :success
255
+ # assert_template "jail/front"
256
+ # end
257
+ #
258
+ # def goes_to_login
259
+ # get login_url
260
+ # #...
261
+ # end
262
+ #
263
+ # == View a list of all your routes
264
+ #
265
+ # Run <tt>rake routes</tt>.
266
+ #
267
+ module Routing
268
+ SEPARATORS = %w( / . ? )
269
+
270
+ HTTP_METHODS = [:get, :head, :post, :put, :delete]
271
+
272
+ ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set
273
+
274
+ # The root paths which may contain controller files
275
+ mattr_accessor :controller_paths
276
+ self.controller_paths = []
277
+
278
+ # A helper module to hold URL related helpers.
279
+ module Helpers
280
+ include PolymorphicRoutes
281
+ end
282
+
283
+ class << self
284
+ # Expects an array of controller names as the first argument.
285
+ # Executes the passed block with only the named controllers named available.
286
+ # This method is used in internal Rails testing.
287
+ def with_controllers(names)
288
+ prior_controllers = @possible_controllers
289
+ use_controllers! names
290
+ yield
291
+ ensure
292
+ use_controllers! prior_controllers
293
+ end
294
+
295
+ # Returns an array of paths, cleaned of double-slashes and relative path references.
296
+ # * "\\\" and "//" become "\\" or "/".
297
+ # * "/foo/bar/../config" becomes "/foo/config".
298
+ # The returned array is sorted by length, descending.
299
+ def normalize_paths(paths)
300
+ # do the hokey-pokey of path normalization...
301
+ paths = paths.collect do |path|
302
+ path = path.
303
+ gsub("//", "/"). # replace double / chars with a single
304
+ gsub("\\\\", "\\"). # replace double \ chars with a single
305
+ gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
306
+
307
+ # eliminate .. paths where possible
308
+ re = %r{[^/\\]+[/\\]\.\.[/\\]}
309
+ path.gsub!(re, "") while path.match(re)
310
+ path
311
+ end
312
+
313
+ # start with longest path, first
314
+ paths = paths.uniq.sort_by { |path| - path.length }
315
+ end
316
+
317
+ # Returns the array of controller names currently available to ActionController::Routing.
318
+ def possible_controllers
319
+ unless @possible_controllers
320
+ @possible_controllers = []
321
+
322
+ paths = controller_paths.select { |path| File.directory?(path) && path != "." }
323
+
324
+ seen_paths = Hash.new {|h, k| h[k] = true; false}
325
+ normalize_paths(paths).each do |load_path|
326
+ Dir["#{load_path}/**/*_controller.rb"].collect do |path|
327
+ next if seen_paths[path.gsub(%r{^\.[/\\]}, "")]
328
+
329
+ controller_name = path[(load_path.length + 1)..-1]
330
+
331
+ controller_name.gsub!(/_controller\.rb\Z/, '')
332
+ @possible_controllers << controller_name
333
+ end
334
+ end
335
+
336
+ # remove duplicates
337
+ @possible_controllers.uniq!
338
+ end
339
+ @possible_controllers
340
+ end
341
+
342
+ # Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
343
+ # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
344
+ def use_controllers!(controller_names)
345
+ @possible_controllers = controller_names
346
+ end
347
+
348
+ # Returns a controller path for a new +controller+ based on a +previous+ controller path.
349
+ # Handles 4 scenarios:
350
+ #
351
+ # * stay in the previous controller:
352
+ # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
353
+ #
354
+ # * stay in the previous namespace:
355
+ # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
356
+ #
357
+ # * forced move to the root namespace:
358
+ # controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
359
+ #
360
+ # * previous namespace is root:
361
+ # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
362
+ #
363
+
364
+ def controller_relative_to(controller, previous)
365
+ if controller.nil? then previous
366
+ elsif controller[0] == ?/ then controller[1..-1]
367
+ elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
368
+ else controller
369
+ end
370
+ end
371
+ end
372
+
373
+
374
+ Routes = RouteSet.new
375
+
376
+ ActiveSupport::Inflector.module_eval do
377
+ # Ensures that routes are reloaded when Rails inflections are updated.
378
+ def inflections_with_route_reloading(&block)
379
+ returning(inflections_without_route_reloading(&block)) {
380
+ ActionController::Routing::Routes.reload! if block_given?
381
+ }
382
+ end
383
+
384
+ alias_method_chain :inflections, :route_reloading
385
+ end
386
+ end
387
+ end