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,212 @@
1
+ require 'set'
2
+
3
+ module Mime
4
+ SET = []
5
+ EXTENSION_LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
6
+ LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
7
+
8
+ # Encapsulates the notion of a mime type. Can be used at render time, for example, with:
9
+ #
10
+ # class PostsController < ActionController::Base
11
+ # def show
12
+ # @post = Post.find(params[:id])
13
+ #
14
+ # respond_to do |format|
15
+ # format.html
16
+ # format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] }
17
+ # format.xml { render :xml => @people.to_xml }
18
+ # end
19
+ # end
20
+ # end
21
+ class Type
22
+ @@html_types = Set.new [:html, :all]
23
+ cattr_reader :html_types
24
+
25
+ # These are the content types which browsers can generate without using ajax, flash, etc
26
+ # i.e. following a link, getting an image or posting a form. CSRF protection
27
+ # only needs to protect against these types.
28
+ @@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text]
29
+ cattr_reader :browser_generated_types
30
+
31
+
32
+ @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
33
+ def self.unverifiable_types
34
+ ActiveSupport::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller)
35
+ @@unverifiable_types
36
+ end
37
+
38
+ # A simple helper class used in parsing the accept header
39
+ class AcceptItem #:nodoc:
40
+ attr_accessor :order, :name, :q
41
+
42
+ def initialize(order, name, q=nil)
43
+ @order = order
44
+ @name = name.strip
45
+ q ||= 0.0 if @name == Mime::ALL # default wilcard match to end of list
46
+ @q = ((q || 1.0).to_f * 100).to_i
47
+ end
48
+
49
+ def to_s
50
+ @name
51
+ end
52
+
53
+ def <=>(item)
54
+ result = item.q <=> q
55
+ result = order <=> item.order if result == 0
56
+ result
57
+ end
58
+
59
+ def ==(item)
60
+ name == (item.respond_to?(:name) ? item.name : item)
61
+ end
62
+ end
63
+
64
+ class << self
65
+ def lookup(string)
66
+ LOOKUP[string]
67
+ end
68
+
69
+ def lookup_by_extension(extension)
70
+ EXTENSION_LOOKUP[extension]
71
+ end
72
+
73
+ # Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for
74
+ # rendering different HTML versions depending on the user agent, like an iPhone.
75
+ def register_alias(string, symbol, extension_synonyms = [])
76
+ register(string, symbol, [], extension_synonyms, true)
77
+ end
78
+
79
+ def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
80
+ Mime.instance_eval { const_set symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms) }
81
+
82
+ SET << Mime.const_get(symbol.to_s.upcase)
83
+
84
+ ([string] + mime_type_synonyms).each { |string| LOOKUP[string] = SET.last } unless skip_lookup
85
+ ([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last }
86
+ end
87
+
88
+ def parse(accept_header)
89
+ if accept_header !~ /,/
90
+ [Mime::Type.lookup(accept_header)]
91
+ else
92
+ # keep track of creation order to keep the subsequent sort stable
93
+ list = []
94
+ accept_header.split(/,/).each_with_index do |header, index|
95
+ params, q = header.split(/;\s*q=/)
96
+ if params
97
+ params.strip!
98
+ list << AcceptItem.new(index, params, q) unless params.empty?
99
+ end
100
+ end
101
+ list.sort!
102
+
103
+ # Take care of the broken text/xml entry by renaming or deleting it
104
+ text_xml = list.index("text/xml")
105
+ app_xml = list.index(Mime::XML.to_s)
106
+
107
+ if text_xml && app_xml
108
+ # set the q value to the max of the two
109
+ list[app_xml].q = [list[text_xml].q, list[app_xml].q].max
110
+
111
+ # make sure app_xml is ahead of text_xml in the list
112
+ if app_xml > text_xml
113
+ list[app_xml], list[text_xml] = list[text_xml], list[app_xml]
114
+ app_xml, text_xml = text_xml, app_xml
115
+ end
116
+
117
+ # delete text_xml from the list
118
+ list.delete_at(text_xml)
119
+
120
+ elsif text_xml
121
+ list[text_xml].name = Mime::XML.to_s
122
+ end
123
+
124
+ # Look for more specific XML-based types and sort them ahead of app/xml
125
+
126
+ if app_xml
127
+ idx = app_xml
128
+ app_xml_type = list[app_xml]
129
+
130
+ while(idx < list.length)
131
+ type = list[idx]
132
+ break if type.q < app_xml_type.q
133
+ if type.name =~ /\+xml$/
134
+ list[app_xml], list[idx] = list[idx], list[app_xml]
135
+ app_xml = idx
136
+ end
137
+ idx += 1
138
+ end
139
+ end
140
+
141
+ list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
142
+ list
143
+ end
144
+ end
145
+ end
146
+
147
+ def initialize(string, symbol = nil, synonyms = [])
148
+ @symbol, @synonyms = symbol, synonyms
149
+ @string = string
150
+ end
151
+
152
+ def to_s
153
+ @string
154
+ end
155
+
156
+ def to_str
157
+ to_s
158
+ end
159
+
160
+ def to_sym
161
+ @symbol || @string.to_sym
162
+ end
163
+
164
+ def ===(list)
165
+ if list.is_a?(Array)
166
+ (@synonyms + [ self ]).any? { |synonym| list.include?(synonym) }
167
+ else
168
+ super
169
+ end
170
+ end
171
+
172
+ def ==(mime_type)
173
+ return false if mime_type.blank?
174
+ (@synonyms + [ self ]).any? do |synonym|
175
+ synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
176
+ end
177
+ end
178
+
179
+ def =~(mime_type)
180
+ return false if mime_type.blank?
181
+ regexp = Regexp.new(Regexp.quote(mime_type.to_s))
182
+ (@synonyms + [ self ]).any? do |synonym|
183
+ synonym.to_s =~ regexp
184
+ end
185
+ end
186
+
187
+ # Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
188
+ # ActionController::RequestForgeryProtection.
189
+ def verify_request?
190
+ browser_generated?
191
+ end
192
+
193
+ def html?
194
+ @@html_types.include?(to_sym) || @string =~ /html/
195
+ end
196
+
197
+ def browser_generated?
198
+ @@browser_generated_types.include?(to_sym)
199
+ end
200
+
201
+ private
202
+ def method_missing(method, *args)
203
+ if method.to_s =~ /(\w+)\?$/
204
+ $1.downcase.to_sym == to_sym
205
+ else
206
+ super
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ require 'action_controller/mime_types'
@@ -0,0 +1,21 @@
1
+ # Build list of Mime types for HTTP responses
2
+ # http://www.iana.org/assignments/media-types/
3
+
4
+ Mime::Type.register "*/*", :all
5
+ Mime::Type.register "text/plain", :text, [], %w(txt)
6
+ Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
7
+ Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
8
+ Mime::Type.register "text/css", :css
9
+ Mime::Type.register "text/calendar", :ics
10
+ Mime::Type.register "text/csv", :csv
11
+ Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
12
+ Mime::Type.register "application/rss+xml", :rss
13
+ Mime::Type.register "application/atom+xml", :atom
14
+ Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
15
+
16
+ Mime::Type.register "multipart/form-data", :multipart_form
17
+ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
18
+
19
+ # http://www.ietf.org/rfc/rfc4627.txt
20
+ # http://www.json.org/JSONRequest.html
21
+ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
@@ -0,0 +1,77 @@
1
+ module ActionController
2
+ class ParamsParser
3
+ ActionController::Base.param_parsers[Mime::XML] = :xml_simple
4
+ ActionController::Base.param_parsers[Mime::JSON] = :json
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ if params = parse_formatted_parameters(env)
12
+ env["action_controller.request.request_parameters"] = params
13
+ end
14
+
15
+ @app.call(env)
16
+ end
17
+
18
+ private
19
+ def parse_formatted_parameters(env)
20
+ request = Request.new(env)
21
+
22
+ return false if request.content_length.zero?
23
+
24
+ mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_type
25
+ strategy = ActionController::Base.param_parsers[mime_type]
26
+
27
+ return false unless strategy
28
+
29
+ case strategy
30
+ when Proc
31
+ strategy.call(request.raw_post)
32
+ when :xml_simple, :xml_node
33
+ body = request.raw_post
34
+ body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
35
+ when :yaml
36
+ YAML.load(request.raw_post)
37
+ when :json
38
+ body = request.raw_post
39
+ if body.blank?
40
+ {}
41
+ else
42
+ data = ActiveSupport::JSON.decode(body)
43
+ data = {:_json => data} unless data.is_a?(Hash)
44
+ data.with_indifferent_access
45
+ end
46
+ else
47
+ false
48
+ end
49
+ rescue Exception => e # YAML, XML or Ruby code block errors
50
+ logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
51
+
52
+ raise
53
+ { "body" => request.raw_post,
54
+ "content_type" => request.content_type,
55
+ "content_length" => request.content_length,
56
+ "exception" => "#{e.message} (#{e.class})",
57
+ "backtrace" => e.backtrace }
58
+ end
59
+
60
+ def content_type_from_legacy_post_data_format_header(env)
61
+ if x_post_format = env['HTTP_X_POST_DATA_FORMAT']
62
+ case x_post_format.to_s.downcase
63
+ when 'yaml'
64
+ return Mime::YAML
65
+ when 'xml'
66
+ return Mime::XML
67
+ end
68
+ end
69
+
70
+ nil
71
+ end
72
+
73
+ def logger
74
+ defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support/testing/performance'
2
+ require 'active_support/testing/default'
3
+
4
+ module ActionController
5
+ # An integration test that runs a code profiler on your test methods.
6
+ # Profiling output for combinations of each test method, measurement, and
7
+ # output format are written to your tmp/performance directory.
8
+ #
9
+ # By default, process_time is measured and both flat and graph_html output
10
+ # formats are written, so you'll have two output files per test method.
11
+ class PerformanceTest < ActionController::IntegrationTest
12
+ include ActiveSupport::Testing::Performance
13
+ include ActiveSupport::Testing::Default
14
+ end
15
+ end
@@ -0,0 +1,189 @@
1
+ module ActionController
2
+ # Polymorphic URL helpers are methods for smart resolution to a named route call when
3
+ # given an Active Record model instance. They are to be used in combination with
4
+ # ActionController::Resources.
5
+ #
6
+ # These methods are useful when you want to generate correct URL or path to a RESTful
7
+ # resource without having to know the exact type of the record in question.
8
+ #
9
+ # Nested resources and/or namespaces are also supported, as illustrated in the example:
10
+ #
11
+ # polymorphic_url([:admin, @article, @comment])
12
+ #
13
+ # results in:
14
+ #
15
+ # admin_article_comment_url(@article, @comment)
16
+ #
17
+ # == Usage within the framework
18
+ #
19
+ # Polymorphic URL helpers are used in a number of places throughout the Rails framework:
20
+ #
21
+ # * <tt>url_for</tt>, so you can use it with a record as the argument, e.g.
22
+ # <tt>url_for(@article)</tt>;
23
+ # * ActionView::Helpers::FormHelper uses <tt>polymorphic_path</tt>, so you can write
24
+ # <tt>form_for(@article)</tt> without having to specify <tt>:url</tt> parameter for the form
25
+ # action;
26
+ # * <tt>redirect_to</tt> (which, in fact, uses <tt>url_for</tt>) so you can write
27
+ # <tt>redirect_to(post)</tt> in your controllers;
28
+ # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs
29
+ # for feed entries.
30
+ #
31
+ # == Prefixed polymorphic helpers
32
+ #
33
+ # In addition to <tt>polymorphic_url</tt> and <tt>polymorphic_path</tt> methods, a
34
+ # number of prefixed helpers are available as a shorthand to <tt>:action => "..."</tt>
35
+ # in options. Those are:
36
+ #
37
+ # * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt>
38
+ # * <tt>new_polymorphic_url</tt>, <tt>new_polymorphic_path</tt>
39
+ #
40
+ # Example usage:
41
+ #
42
+ # edit_polymorphic_path(@post) # => "/posts/1/edit"
43
+ # polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf"
44
+ module PolymorphicRoutes
45
+ # Constructs a call to a named RESTful route for the given record and returns the
46
+ # resulting URL string. For example:
47
+ #
48
+ # # calls post_url(post)
49
+ # polymorphic_url(post) # => "http://example.com/posts/1"
50
+ # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
51
+ # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
52
+ # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
53
+ #
54
+ # ==== Options
55
+ #
56
+ # * <tt>:action</tt> - Specifies the action prefix for the named route:
57
+ # <tt>:new</tt> or <tt>:edit</tt>. Default is no prefix.
58
+ # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
59
+ # Default is <tt>:url</tt>.
60
+ #
61
+ # ==== Examples
62
+ #
63
+ # # an Article record
64
+ # polymorphic_url(record) # same as article_url(record)
65
+ #
66
+ # # a Comment record
67
+ # polymorphic_url(record) # same as comment_url(record)
68
+ #
69
+ # # it recognizes new records and maps to the collection
70
+ # record = Comment.new
71
+ # polymorphic_url(record) # same as comments_url()
72
+ #
73
+ def polymorphic_url(record_or_hash_or_array, options = {})
74
+ if record_or_hash_or_array.kind_of?(Array)
75
+ record_or_hash_or_array = record_or_hash_or_array.compact
76
+ record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
77
+ end
78
+
79
+ record = extract_record(record_or_hash_or_array)
80
+
81
+ args = case record_or_hash_or_array
82
+ when Hash; [ record_or_hash_or_array ]
83
+ when Array; record_or_hash_or_array.dup
84
+ else [ record_or_hash_or_array ]
85
+ end
86
+
87
+ inflection =
88
+ case
89
+ when options[:action].to_s == "new"
90
+ args.pop
91
+ :singular
92
+ when record.respond_to?(:new_record?) && record.new_record?
93
+ args.pop
94
+ :plural
95
+ else
96
+ :singular
97
+ end
98
+
99
+ args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
100
+ named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
101
+
102
+ url_options = options.except(:action, :routing_type)
103
+ unless url_options.empty?
104
+ args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
105
+ end
106
+
107
+ __send__(named_route, *args)
108
+ end
109
+
110
+ # Returns the path component of a URL for the given record. It uses
111
+ # <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
112
+ def polymorphic_path(record_or_hash_or_array, options = {})
113
+ options[:routing_type] = :path
114
+ polymorphic_url(record_or_hash_or_array, options)
115
+ end
116
+
117
+ %w(edit new).each do |action|
118
+ module_eval <<-EOT, __FILE__, __LINE__
119
+ def #{action}_polymorphic_url(record_or_hash, options = {}) # def edit_polymorphic_url(record_or_hash, options = {})
120
+ polymorphic_url( # polymorphic_url(
121
+ record_or_hash, # record_or_hash,
122
+ options.merge(:action => "#{action}")) # options.merge(:action => "edit"))
123
+ end # end
124
+ #
125
+ def #{action}_polymorphic_path(record_or_hash, options = {}) # def edit_polymorphic_path(record_or_hash, options = {})
126
+ polymorphic_url( # polymorphic_url(
127
+ record_or_hash, # record_or_hash,
128
+ options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path))
129
+ end # end
130
+ EOT
131
+ end
132
+
133
+ def formatted_polymorphic_url(record_or_hash, options = {})
134
+ ActiveSupport::Deprecation.warn("formatted_polymorphic_url has been deprecated. Please pass :format to the polymorphic_url method instead", caller)
135
+ options[:format] = record_or_hash.pop if Array === record_or_hash
136
+ polymorphic_url(record_or_hash, options)
137
+ end
138
+
139
+ def formatted_polymorphic_path(record_or_hash, options = {})
140
+ ActiveSupport::Deprecation.warn("formatted_polymorphic_path has been deprecated. Please pass :format to the polymorphic_path method instead", caller)
141
+ options[:format] = record_or_hash.pop if record_or_hash === Array
142
+ polymorphic_url(record_or_hash, options.merge(:routing_type => :path))
143
+ end
144
+
145
+ private
146
+ def action_prefix(options)
147
+ options[:action] ? "#{options[:action]}_" : ''
148
+ end
149
+
150
+ def routing_type(options)
151
+ options[:routing_type] || :url
152
+ end
153
+
154
+ def build_named_route_call(records, inflection, options = {})
155
+ unless records.is_a?(Array)
156
+ record = extract_record(records)
157
+ route = ''
158
+ else
159
+ record = records.pop
160
+ route = records.inject("") do |string, parent|
161
+ if parent.is_a?(Symbol) || parent.is_a?(String)
162
+ string << "#{parent}_"
163
+ else
164
+ string << RecordIdentifier.__send__("plural_class_name", parent).singularize
165
+ string << "_"
166
+ end
167
+ end
168
+ end
169
+
170
+ if record.is_a?(Symbol) || record.is_a?(String)
171
+ route << "#{record}_"
172
+ else
173
+ route << RecordIdentifier.__send__("plural_class_name", record)
174
+ route = route.singularize if inflection == :singular
175
+ route << "_"
176
+ end
177
+
178
+ action_prefix(options) + route + routing_type(options).to_s
179
+ end
180
+
181
+ def extract_record(record_or_hash_or_array)
182
+ case record_or_hash_or_array
183
+ when Array; record_or_hash_or_array.last
184
+ when Hash; record_or_hash_or_array[:id]
185
+ else record_or_hash_or_array
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,36 @@
1
+ # Rack 1.0 does not allow string subclass body. This does not play well with our ActionView::SafeBuffer.
2
+ # The next release of Rack will be allowing string subclass body - http://github.com/rack/rack/commit/de668df02802a0335376a81ba709270e43ba9d55
3
+ # TODO : Remove this monkey patch after the next release of Rack
4
+
5
+ module RackLintPatch
6
+ module AllowStringSubclass
7
+ def self.included(base)
8
+ base.send :alias_method, :each, :each_with_hack
9
+ end
10
+
11
+ def each_with_hack
12
+ @closed = false
13
+
14
+ @body.each { |part|
15
+ assert("Body yielded non-string value #{part.inspect}") {
16
+ part.kind_of?(String)
17
+ }
18
+ yield part
19
+ }
20
+
21
+ if @body.respond_to?(:to_path)
22
+ assert("The file identified by body.to_path does not exist") {
23
+ ::File.exist? @body.to_path
24
+ }
25
+ end
26
+ end
27
+ end
28
+
29
+ begin
30
+ app = proc {|env| [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, [Class.new(String).new("Hello World!")]] }
31
+ response = Rack::MockRequest.new(Rack::Lint.new(app)).get('/')
32
+ rescue Rack::Lint::LintError => e
33
+ raise(e) unless e.message =~ /Body yielded non-string value/
34
+ Rack::Lint.send :include, AllowStringSubclass
35
+ end
36
+ end
@@ -0,0 +1,104 @@
1
+ module ActionController
2
+ # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
3
+ # Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate
4
+ # the view actions to a higher logical level. Example:
5
+ #
6
+ # # routes
7
+ # map.resources :posts
8
+ #
9
+ # # view
10
+ # <% div_for(post) do %> <div id="post_45" class="post">
11
+ # <%= post.body %> What a wonderful world!
12
+ # <% end %> </div>
13
+ #
14
+ # # controller
15
+ # def destroy
16
+ # post = Post.find(params[:id])
17
+ # post.destroy
18
+ #
19
+ # respond_to do |format|
20
+ # format.html { redirect_to(post) } # Calls polymorphic_url(post) which in turn calls post_url(post)
21
+ # format.js do
22
+ # # Calls: new Effect.fade('post_45');
23
+ # render(:update) { |page| page[post].visual_effect(:fade) }
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ # As the example above shows, you can stop caring to a large extent what the actual id of the post is. You just know
29
+ # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming
30
+ # convention and allows you to write less code if you follow it.
31
+ module RecordIdentifier
32
+ extend self
33
+
34
+ JOIN = '_'.freeze
35
+ NEW = 'new'.freeze
36
+
37
+ # Returns plural/singular for a record or class. Example:
38
+ #
39
+ # partial_path(post) # => "posts/post"
40
+ # partial_path(Person) # => "people/person"
41
+ # partial_path(Person, "admin/games") # => "admin/people/person"
42
+ def partial_path(record_or_class, controller_path = nil)
43
+ name = model_name_from_record_or_class(record_or_class)
44
+
45
+ if controller_path && controller_path.include?("/")
46
+ "#{File.dirname(controller_path)}/#{name.partial_path}"
47
+ else
48
+ name.partial_path
49
+ end
50
+ end
51
+
52
+ # The DOM class convention is to use the singular form of an object or class. Examples:
53
+ #
54
+ # dom_class(post) # => "post"
55
+ # dom_class(Person) # => "person"
56
+ #
57
+ # If you need to address multiple instances of the same class in the same view, you can prefix the dom_class:
58
+ #
59
+ # dom_class(post, :edit) # => "edit_post"
60
+ # dom_class(Person, :edit) # => "edit_person"
61
+ def dom_class(record_or_class, prefix = nil)
62
+ singular = singular_class_name(record_or_class)
63
+ prefix ? "#{prefix}#{JOIN}#{singular}" : singular
64
+ end
65
+
66
+ # The DOM id convention is to use the singular form of an object or class with the id following an underscore.
67
+ # If no id is found, prefix with "new_" instead. Examples:
68
+ #
69
+ # dom_id(Post.find(45)) # => "post_45"
70
+ # dom_id(Post.new) # => "new_post"
71
+ #
72
+ # If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
73
+ #
74
+ # dom_id(Post.find(45), :edit) # => "edit_post_45"
75
+ def dom_id(record, prefix = nil)
76
+ if record_id = record.id
77
+ "#{dom_class(record, prefix)}#{JOIN}#{record_id}"
78
+ else
79
+ dom_class(record, prefix || NEW)
80
+ end
81
+ end
82
+
83
+ # Returns the plural class name of a record or class. Examples:
84
+ #
85
+ # plural_class_name(post) # => "posts"
86
+ # plural_class_name(Highrise::Person) # => "highrise_people"
87
+ def plural_class_name(record_or_class)
88
+ model_name_from_record_or_class(record_or_class).plural
89
+ end
90
+
91
+ # Returns the singular class name of a record or class. Examples:
92
+ #
93
+ # singular_class_name(post) # => "post"
94
+ # singular_class_name(Highrise::Person) # => "highrise_person"
95
+ def singular_class_name(record_or_class)
96
+ model_name_from_record_or_class(record_or_class).singular
97
+ end
98
+
99
+ private
100
+ def model_name_from_record_or_class(record_or_class)
101
+ (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
102
+ end
103
+ end
104
+ end