actionpack 1.13.6 → 2.0.0

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 (317) hide show
  1. data/CHANGELOG +1400 -20
  2. data/MIT-LICENSE +1 -1
  3. data/README +5 -5
  4. data/RUNNING_UNIT_TESTS +4 -5
  5. data/Rakefile +5 -6
  6. data/install.rb +2 -2
  7. data/lib/action_controller.rb +11 -15
  8. data/lib/action_controller/assertions.rb +12 -25
  9. data/lib/action_controller/assertions/dom_assertions.rb +18 -4
  10. data/lib/action_controller/assertions/model_assertions.rb +8 -1
  11. data/lib/action_controller/assertions/response_assertions.rb +35 -12
  12. data/lib/action_controller/assertions/routing_assertions.rb +56 -12
  13. data/lib/action_controller/assertions/selector_assertions.rb +105 -38
  14. data/lib/action_controller/assertions/tag_assertions.rb +28 -15
  15. data/lib/action_controller/base.rb +318 -250
  16. data/lib/action_controller/benchmarking.rb +33 -29
  17. data/lib/action_controller/caching.rb +130 -64
  18. data/lib/action_controller/cgi_ext.rb +16 -0
  19. data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
  20. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  21. data/lib/action_controller/cgi_ext/session.rb +73 -0
  22. data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
  23. data/lib/action_controller/cgi_process.rb +34 -57
  24. data/lib/action_controller/components.rb +19 -36
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/dispatcher.rb +195 -0
  27. data/lib/action_controller/filters.rb +35 -34
  28. data/lib/action_controller/flash.rb +30 -35
  29. data/lib/action_controller/helpers.rb +121 -47
  30. data/lib/action_controller/http_authentication.rb +126 -0
  31. data/lib/action_controller/integration.rb +105 -101
  32. data/lib/action_controller/layout.rb +59 -47
  33. data/lib/action_controller/mime_responds.rb +57 -68
  34. data/lib/action_controller/mime_type.rb +43 -80
  35. data/lib/action_controller/mime_types.rb +20 -0
  36. data/lib/action_controller/polymorphic_routes.rb +88 -0
  37. data/lib/action_controller/record_identifier.rb +91 -0
  38. data/lib/action_controller/request.rb +553 -88
  39. data/lib/action_controller/request_forgery_protection.rb +126 -0
  40. data/lib/action_controller/request_profiler.rb +138 -0
  41. data/lib/action_controller/rescue.rb +185 -69
  42. data/lib/action_controller/resources.rb +211 -172
  43. data/lib/action_controller/response.rb +49 -8
  44. data/lib/action_controller/routing.rb +359 -236
  45. data/lib/action_controller/routing_optimisation.rb +119 -0
  46. data/lib/action_controller/session/active_record_store.rb +3 -2
  47. data/lib/action_controller/session/cookie_store.rb +161 -0
  48. data/lib/action_controller/session/mem_cache_store.rb +9 -16
  49. data/lib/action_controller/session_management.rb +17 -8
  50. data/lib/action_controller/streaming.rb +6 -3
  51. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  52. data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
  53. data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
  54. data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
  55. data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
  56. data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
  57. data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
  58. data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
  59. data/lib/action_controller/test_case.rb +53 -0
  60. data/lib/action_controller/test_process.rb +59 -46
  61. data/lib/action_controller/url_rewriter.rb +48 -24
  62. data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
  65. data/lib/action_controller/verification.rb +27 -21
  66. data/lib/action_pack.rb +1 -1
  67. data/lib/action_pack/version.rb +4 -4
  68. data/lib/action_view.rb +2 -3
  69. data/lib/action_view/base.rb +218 -63
  70. data/lib/action_view/compiled_templates.rb +1 -2
  71. data/lib/action_view/helpers/active_record_helper.rb +35 -17
  72. data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
  73. data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
  74. data/lib/action_view/helpers/benchmark_helper.rb +12 -5
  75. data/lib/action_view/helpers/cache_helper.rb +29 -0
  76. data/lib/action_view/helpers/capture_helper.rb +97 -63
  77. data/lib/action_view/helpers/date_helper.rb +295 -35
  78. data/lib/action_view/helpers/debug_helper.rb +6 -2
  79. data/lib/action_view/helpers/form_helper.rb +354 -111
  80. data/lib/action_view/helpers/form_options_helper.rb +171 -109
  81. data/lib/action_view/helpers/form_tag_helper.rb +332 -76
  82. data/lib/action_view/helpers/javascript_helper.rb +35 -11
  83. data/lib/action_view/helpers/javascripts/controls.js +484 -354
  84. data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
  85. data/lib/action_view/helpers/javascripts/effects.js +396 -364
  86. data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
  87. data/lib/action_view/helpers/number_helper.rb +84 -60
  88. data/lib/action_view/helpers/prototype_helper.rb +419 -43
  89. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  90. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  91. data/lib/action_view/helpers/sanitize_helper.rb +223 -0
  92. data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
  93. data/lib/action_view/helpers/tag_helper.rb +69 -39
  94. data/lib/action_view/helpers/text_helper.rb +221 -148
  95. data/lib/action_view/helpers/url_helper.rb +283 -165
  96. data/lib/action_view/partials.rb +134 -62
  97. data/lib/action_view/template_error.rb +4 -12
  98. data/lib/actionpack.rb +1 -0
  99. data/test/abstract_unit.rb +21 -1
  100. data/test/action_view_test.rb +26 -0
  101. data/test/active_record_unit.rb +12 -20
  102. data/test/activerecord/active_record_store_test.rb +2 -2
  103. data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
  104. data/test/controller/action_pack_assertions_test.rb +21 -152
  105. data/test/controller/addresses_render_test.rb +2 -7
  106. data/test/controller/assert_select_test.rb +120 -14
  107. data/test/controller/base_test.rb +11 -13
  108. data/test/controller/caching_test.rb +125 -5
  109. data/test/controller/capture_test.rb +23 -16
  110. data/test/controller/cgi_test.rb +66 -391
  111. data/test/controller/components_test.rb +31 -42
  112. data/test/controller/content_type_test.rb +1 -1
  113. data/test/controller/cookie_test.rb +42 -14
  114. data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
  115. data/test/controller/dispatcher_test.rb +123 -0
  116. data/test/controller/fake_models.rb +5 -0
  117. data/test/controller/filters_test.rb +44 -7
  118. data/test/controller/flash_test.rb +46 -2
  119. data/test/controller/fragment_store_setting_test.rb +10 -8
  120. data/test/controller/helper_test.rb +19 -2
  121. data/test/controller/html-scanner/document_test.rb +124 -0
  122. data/test/controller/html-scanner/node_test.rb +69 -0
  123. data/test/controller/html-scanner/sanitizer_test.rb +250 -0
  124. data/test/controller/html-scanner/tag_node_test.rb +239 -0
  125. data/test/controller/html-scanner/text_node_test.rb +51 -0
  126. data/test/controller/html-scanner/tokenizer_test.rb +125 -0
  127. data/test/controller/http_authentication_test.rb +54 -0
  128. data/test/controller/integration_test.rb +12 -26
  129. data/test/controller/layout_test.rb +64 -12
  130. data/test/controller/mime_responds_test.rb +193 -38
  131. data/test/controller/mime_type_test.rb +30 -8
  132. data/test/controller/new_render_test.rb +104 -22
  133. data/test/controller/polymorphic_routes_test.rb +98 -0
  134. data/test/controller/record_identifier_test.rb +103 -0
  135. data/test/controller/redirect_test.rb +120 -18
  136. data/test/controller/render_test.rb +195 -45
  137. data/test/controller/request_forgery_protection_test.rb +217 -0
  138. data/test/controller/request_test.rb +545 -27
  139. data/test/controller/rescue_test.rb +501 -0
  140. data/test/controller/resources_test.rb +258 -132
  141. data/test/controller/routing_test.rb +502 -106
  142. data/test/controller/selector_test.rb +5 -5
  143. data/test/controller/send_file_test.rb +17 -7
  144. data/test/controller/session/cookie_store_test.rb +246 -0
  145. data/test/controller/session/mem_cache_store_test.rb +182 -0
  146. data/test/controller/session_fixation_test.rb +8 -11
  147. data/test/controller/session_management_test.rb +7 -7
  148. data/test/controller/test_test.rb +150 -38
  149. data/test/controller/url_rewriter_test.rb +87 -12
  150. data/test/controller/verification_test.rb +11 -0
  151. data/test/controller/view_paths_test.rb +137 -0
  152. data/test/controller/webservice_test.rb +11 -75
  153. data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
  154. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  155. data/test/fixtures/developer.rb +2 -0
  156. data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
  157. data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
  158. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  159. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  160. data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
  161. data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
  162. data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
  163. data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
  164. data/test/fixtures/multipart/binary_file +0 -0
  165. data/test/fixtures/multipart/bracketed_param +5 -0
  166. data/test/fixtures/override/test/hello_world.erb +1 -0
  167. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  168. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  169. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  170. data/test/fixtures/post_test/post/index.html.erb +1 -0
  171. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  172. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  173. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  174. data/test/fixtures/public/404.html +1 -0
  175. data/test/fixtures/public/500.html +1 -0
  176. data/test/fixtures/public/javascripts/application.js +0 -1
  177. data/test/fixtures/public/javascripts/bank.js +1 -0
  178. data/test/fixtures/public/javascripts/robber.js +1 -0
  179. data/test/fixtures/public/stylesheets/bank.css +1 -0
  180. data/test/fixtures/public/stylesheets/robber.css +1 -0
  181. data/test/fixtures/replies.yml +2 -0
  182. data/test/fixtures/reply.rb +2 -1
  183. data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
  184. data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
  185. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  186. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  187. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  188. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  189. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  190. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  191. data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
  192. data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
  193. data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
  194. data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
  195. data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
  196. data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
  197. data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
  198. data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
  199. data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
  200. data/test/fixtures/test/_hash_greeting.erb +1 -0
  201. data/test/fixtures/test/_hash_object.erb +2 -0
  202. data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
  203. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  204. data/test/fixtures/test/_partial.erb +1 -0
  205. data/test/fixtures/test/_partial.html.erb +1 -0
  206. data/test/fixtures/test/_partial.js.erb +1 -0
  207. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  208. data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
  209. data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
  210. data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
  211. data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
  212. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  213. data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
  214. data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
  215. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  216. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  217. data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  218. data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
  219. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  220. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  221. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  222. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  223. data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
  224. data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
  225. data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
  226. data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
  227. data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
  228. data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
  229. data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
  230. data/test/fixtures/test/list.erb +1 -0
  231. data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
  232. data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
  233. data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  234. data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
  235. data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
  236. data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
  237. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  238. data/test/fixtures/topic.rb +1 -1
  239. data/test/template/active_record_helper_test.rb +67 -20
  240. data/test/template/asset_tag_helper_test.rb +222 -54
  241. data/test/template/atom_feed_helper_test.rb +101 -0
  242. data/test/template/benchmark_helper_test.rb +2 -2
  243. data/test/template/compiled_templates_test.rb +76 -32
  244. data/test/template/date_helper_test.rb +125 -9
  245. data/test/template/form_helper_test.rb +326 -33
  246. data/test/template/form_options_helper_test.rb +822 -15
  247. data/test/template/form_tag_helper_test.rb +96 -30
  248. data/test/template/javascript_helper_test.rb +61 -13
  249. data/test/template/number_helper_test.rb +12 -11
  250. data/test/template/prototype_helper_test.rb +185 -24
  251. data/test/template/sanitize_helper_test.rb +49 -0
  252. data/test/template/scriptaculous_helper_test.rb +9 -3
  253. data/test/template/tag_helper_test.rb +13 -2
  254. data/test/template/text_helper_test.rb +38 -52
  255. data/test/template/url_helper_test.rb +216 -46
  256. metadata +144 -116
  257. data/examples/.htaccess +0 -24
  258. data/examples/address_book/index.rhtml +0 -33
  259. data/examples/address_book/layout.rhtml +0 -8
  260. data/examples/address_book_controller.cgi +0 -9
  261. data/examples/address_book_controller.fcgi +0 -6
  262. data/examples/address_book_controller.rb +0 -52
  263. data/examples/address_book_controller.rbx +0 -4
  264. data/examples/benchmark.rb +0 -52
  265. data/examples/benchmark_with_ar.fcgi +0 -89
  266. data/examples/blog_controller.cgi +0 -53
  267. data/examples/debate/index.rhtml +0 -14
  268. data/examples/debate/new_topic.rhtml +0 -22
  269. data/examples/debate/topic.rhtml +0 -32
  270. data/examples/debate_controller.cgi +0 -57
  271. data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
  272. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
  273. data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
  274. data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
  275. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
  276. data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
  277. data/lib/action_controller/deprecated_dependencies.rb +0 -65
  278. data/lib/action_controller/deprecated_redirects.rb +0 -17
  279. data/lib/action_controller/deprecated_request_methods.rb +0 -34
  280. data/lib/action_controller/macros/auto_complete.rb +0 -53
  281. data/lib/action_controller/macros/in_place_editing.rb +0 -33
  282. data/lib/action_controller/pagination.rb +0 -408
  283. data/lib/action_controller/scaffolding.rb +0 -189
  284. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
  285. data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
  286. data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
  287. data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
  288. data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
  289. data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
  290. data/lib/action_controller/vendor/xml_node.rb +0 -97
  291. data/lib/action_view/helpers/deprecated_helper.rb +0 -37
  292. data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
  293. data/lib/action_view/helpers/pagination_helper.rb +0 -86
  294. data/test/activerecord/active_record_assertions_test.rb +0 -92
  295. data/test/activerecord/pagination_test.rb +0 -165
  296. data/test/controller/deprecated_instance_variables_test.rb +0 -48
  297. data/test/controller/raw_post_test.rb +0 -68
  298. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
  299. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
  300. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
  301. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
  302. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
  303. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
  304. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
  305. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
  306. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
  307. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
  308. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
  309. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
  310. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
  311. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
  312. data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
  313. data/test/fixtures/test/_hash_object.rhtml +0 -1
  314. data/test/fixtures/test/list.rhtml +0 -1
  315. data/test/template/deprecated_helper_test.rb +0 -36
  316. data/test/template/deprecated_instance_variables_test.rb +0 -43
  317. data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -1,79 +1,160 @@
1
- require File.dirname(__FILE__) + '/javascript_helper'
1
+ require 'action_view/helpers/javascript_helper'
2
2
 
3
3
  module ActionView
4
4
  module Helpers #:nodoc:
5
- # Provides a set of methods for making easy links and getting urls that
6
- # depend on the controller and action. This means that you can use the
7
- # same format for links in the views that you do in the controller.
5
+ # Provides a set of methods for making links and getting URLs that
6
+ # depend on the routing subsystem (see ActionController::Routing).
7
+ # This allows you to use the same format for links in views
8
+ # and controllers.
8
9
  module UrlHelper
9
10
  include JavaScriptHelper
10
-
11
- # Returns the URL for the set of +options+ provided. This takes the
12
- # same options as url_for in action controller. For a list, see the
13
- # documentation for ActionController::Base#url_for. Note that it'll
14
- # set :only_path => true so you'll get the relative /controller/action
15
- # instead of the fully qualified http://example.com/controller/action.
16
- #
17
- # When called from a view, url_for returns an HTML escaped url. If you
11
+
12
+ # Returns the URL for the set of +options+ provided. This takes the
13
+ # same options as url_for in ActionController (see the
14
+ # documentation for ActionController::Base#url_for). Note that by default
15
+ # <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative /controller/action
16
+ # instead of the fully qualified URL like http://example.com/controller/action.
17
+ #
18
+ # When called from a view, url_for returns an HTML escaped url. If you
18
19
  # need an unescaped url, pass :escape => false in the +options+.
19
- def url_for(options = {}, *parameters_for_method_reference)
20
- if options.kind_of? Hash
21
- options = { :only_path => true }.update(options.symbolize_keys)
22
- escape = options.key?(:escape) ? options.delete(:escape) : true
23
- else
20
+ #
21
+ # ==== Options
22
+ # * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path.
23
+ # * <tt>:only_path</tt> -- if true, returns the relative URL (omitting the protocol, host name, and port) (<tt>true</tt> by default unless <tt>:host</tt> is specified)
24
+ # * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this
25
+ # is currently not recommended since it breaks caching.
26
+ # * <tt>:host</tt> -- overrides the default (current) host if provided
27
+ # * <tt>:protocol</tt> -- overrides the default (current) protocol if provided
28
+ # * <tt>:user</tt> -- Inline HTTP authentication (only plucked out if :password is also present)
29
+ # * <tt>:password</tt> -- Inline HTTP authentication (only plucked out if :user is also present)
30
+ # * <tt>:escape</tt> -- Determines whether the returned URL will be HTML escaped or not (<tt>true</tt> by default)
31
+ #
32
+ # ==== Relying on named routes
33
+ #
34
+ # If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter,
35
+ # you'll trigger the named route for that record. The lookup will happen on the name of the class. So passing
36
+ # a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as
37
+ # admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route).
38
+ #
39
+ # ==== Examples
40
+ # <%= url_for(:action => 'index') %>
41
+ # # => /blog/
42
+ #
43
+ # <%= url_for(:action => 'find', :controller => 'books') %>
44
+ # # => /books/find
45
+ #
46
+ # <%= url_for(:action => 'login', :controller => 'members', :only_path => false, :protocol => 'https') %>
47
+ # # => https://www.railsapplication.com/members/login/
48
+ #
49
+ # <%= url_for(:action => 'play', :anchor => 'player') %>
50
+ # # => /messages/play/#player
51
+ #
52
+ # <%= url_for(:action => 'checkout', :anchor => 'tax&ship') %>
53
+ # # => /testing/jump/#tax&amp;ship
54
+ #
55
+ # <%= url_for(:action => 'checkout', :anchor => 'tax&ship', :escape => false) %>
56
+ # # => /testing/jump/#tax&ship
57
+ #
58
+ # <%= url_for(Workshop.new) %>
59
+ # # relies on Workshop answering a new_record? call (and in this case returning true)
60
+ # # => /workshops
61
+ #
62
+ # <%= url_for(@workshop) %>
63
+ # # calls @workshop.to_s
64
+ # # => /workshops/5
65
+ def url_for(options = {})
66
+ case options
67
+ when Hash
68
+ show_path = options[:host].nil? ? true : false
69
+ options = { :only_path => show_path }.update(options.symbolize_keys)
70
+ escape = options.key?(:escape) ? options.delete(:escape) : true
71
+ url = @controller.send(:url_for, options)
72
+ when String
24
73
  escape = true
74
+ url = options
75
+ when NilClass
76
+ url = @controller.send(:url_for, nil)
77
+ else
78
+ escape = false
79
+ url = polymorphic_path(options)
25
80
  end
26
81
 
27
- url = @controller.send(:url_for, options, *parameters_for_method_reference)
28
- escape ? html_escape(url) : url
82
+ escape ? escape_once(url) : url
29
83
  end
30
84
 
31
- # Creates a link tag of the given +name+ using a URL created by the set
32
- # of +options+. See the valid options in the documentation for
33
- # ActionController::Base#url_for. It's also possible to pass a string instead
34
- # of an options hash to get a link tag that uses the value of the string as the
35
- # href for the link. If nil is passed as a name, the link itself will become
36
- # the name.
85
+ # Creates a link tag of the given +name+ using a URL created by the set
86
+ # of +options+. See the valid options in the documentation for
87
+ # url_for. It's also possible to pass a string instead
88
+ # of an options hash to get a link tag that uses the value of the string as the
89
+ # href for the link, or use +:back+ to link to the referrer - a JavaScript back
90
+ # link will be used in place of a referrer if none exists. If nil is passed as
91
+ # a name, the link itself will become the name.
37
92
  #
38
- # The +html_options+ will accept a hash of html attributes for the link tag.
39
- # It also accepts 3 modifiers that specialize the link behavior.
40
- #
41
- # * <tt>:confirm => 'question?'</tt>: This will add a JavaScript confirm
42
- # prompt with the question specified. If the user accepts, the link is
93
+ # ==== Options
94
+ # * <tt>:confirm => 'question?'</tt> -- This will add a JavaScript confirm
95
+ # prompt with the question specified. If the user accepts, the link is
43
96
  # processed normally, otherwise no action is taken.
44
- # * <tt>:popup => true || array of window options</tt>: This will force the
45
- # link to open in a popup window. By passing true, a default browser window
46
- # will be opened with the URL. You can also specify an array of options
97
+ # * <tt>:popup => true || array of window options</tt> -- This will force the
98
+ # link to open in a popup window. By passing true, a default browser window
99
+ # will be opened with the URL. You can also specify an array of options
47
100
  # that are passed-thru to JavaScripts window.open method.
48
- # * <tt>:method => symbol of HTTP verb</tt>: This modifier will dynamically
49
- # create an HTML form and immediately submit the form for processing using
101
+ # * <tt>:method => symbol of HTTP verb</tt> -- This modifier will dynamically
102
+ # create an HTML form and immediately submit the form for processing using
50
103
  # the HTTP verb specified. Useful for having links perform a POST operation
51
104
  # in dangerous actions like deleting a record (which search bots can follow
52
105
  # while spidering your site). Supported verbs are :post, :delete and :put.
53
- # Note that if the user has JavaScript disabled, the request will fall back
54
- # to using GET. If you are relying on the POST behavior, your should check
55
- # for it in your controllers action by using the request objects methods
106
+ # Note that if the user has JavaScript disabled, the request will fall back
107
+ # to using GET. If you are relying on the POST behavior, you should check
108
+ # for it in your controller's action by using the request object's methods
56
109
  # for post?, delete? or put?.
110
+ # * The +html_options+ will accept a hash of html attributes for the link tag.
111
+ #
112
+ # Note that if the user has JavaScript disabled, the request will fall back
113
+ # to using GET. If :href=>'#' is used and the user has JavaScript disabled
114
+ # clicking the link will have no effect. If you are relying on the POST
115
+ # behavior, your should check for it in your controller's action by using the
116
+ # request object's methods for post?, delete? or put?.
57
117
  #
58
118
  # You can mix and match the +html_options+ with the exception of
59
119
  # :popup and :method which will raise an ActionView::ActionViewError
60
120
  # exception.
61
121
  #
122
+ # ==== Examples
62
123
  # link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?"
124
+ # # => <a href="http://www.rubyonrails.org/" onclick="return confirm('Are you sure?');">Visit Other Site</a>
125
+ #
63
126
  # link_to "Help", { :action => "help" }, :popup => true
127
+ # # => <a href="/testing/help/" onclick="window.open(this.href);return false;">Help</a>
128
+ #
64
129
  # link_to "View Image", { :action => "view" }, :popup => ['new_window_name', 'height=300,width=600']
130
+ # # => <a href="/testing/view/" onclick="window.open(this.href,'new_window_name','height=300,width=600');return false;">View Image</a>
131
+ #
65
132
  # link_to "Delete Image", { :action => "delete", :id => @image.id }, :confirm => "Are you sure?", :method => :delete
66
- def link_to(name, options = {}, html_options = nil, *parameters_for_method_reference)
133
+ # # => <a href="/testing/delete/9/" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
134
+ # f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;
135
+ # var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method');
136
+ # m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a>
137
+ def link_to(name, options = {}, html_options = nil)
138
+ url = case options
139
+ when String
140
+ options
141
+ when :back
142
+ @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
143
+ else
144
+ self.url_for(options)
145
+ end
146
+
67
147
  if html_options
68
148
  html_options = html_options.stringify_keys
69
- convert_options_to_javascript!(html_options)
149
+ href = html_options['href']
150
+ convert_options_to_javascript!(html_options, url)
70
151
  tag_options = tag_options(html_options)
71
152
  else
72
153
  tag_options = nil
73
154
  end
74
-
75
- url = options.is_a?(String) ? options : self.url_for(options, *parameters_for_method_reference)
76
- "<a href=\"#{url}\"#{tag_options}>#{name || url}</a>"
155
+
156
+ href_attr = "href=\"#{url}\"" unless href
157
+ "<a #{href_attr}#{tag_options}>#{name || url}</a>"
77
158
  end
78
159
 
79
160
  # Generates a form containing a single button that submits to the URL created
@@ -88,32 +169,36 @@ module ActionView
88
169
  # the form submission and input element behavior using +html_options+.
89
170
  # This method accepts the <tt>:method</tt> and <tt>:confirm</tt> modifiers
90
171
  # described in the link_to documentation. If no <tt>:method</tt> modifier
91
- # is given, it will default to performing a POST operation. You can also
172
+ # is given, it will default to performing a POST operation. You can also
92
173
  # disable the button by passing <tt>:disabled => true</tt> in +html_options+.
93
- #
94
- # button_to "New", :action => "new"
95
- #
96
- # Generates the following HTML:
97
- #
98
- # <form method="post" action="/controller/new" class="button-to">
99
- # <div><input value="New" type="submit" /></div>
100
- # </form>
101
- #
102
174
  # If you are using RESTful routes, you can pass the <tt>:method</tt>
103
175
  # to change the HTTP verb used to submit the form.
104
176
  #
105
- # button_to "Delete Image", { :action => "delete", :id => @image.id },
106
- # :confirm => "Are you sure?", :method => :delete
177
+ # ==== Options
178
+ # The +options+ hash accepts the same options at url_for.
107
179
  #
108
- # Which generates the following HTML:
180
+ # There are a few special +html_options+:
181
+ # * <tt>:method</tt> -- specifies the anchor name to be appended to the path.
182
+ # * <tt>:disabled</tt> -- specifies the anchor name to be appended to the path.
183
+ # * <tt>:confirm</tt> -- This will add a JavaScript confirm
184
+ # prompt with the question specified. If the user accepts, the link is
185
+ # processed normally, otherwise no action is taken.
186
+ #
187
+ # ==== Examples
188
+ # <%= button_to "New", :action => "new" %>
189
+ # # => "<form method="post" action="/controller/new" class="button-to">
190
+ # # <div><input value="New" type="submit" /></div>
191
+ # # </form>"
109
192
  #
110
- # <form method="post" action="/images/delete/1" class="button-to">
111
- # <div>
112
- # <input type="hidden" name="_method" value="delete" />
113
- # <input onclick="return confirm('Are you sure?');"
114
- # value="Delete" type="submit" />
115
- # </div>
116
- # </form>
193
+ # button_to "Delete Image", { :action => "delete", :id => @image.id },
194
+ # :confirm => "Are you sure?", :method => :delete
195
+ # # => "<form method="post" action="/images/delete/1" class="button-to">
196
+ # # <div>
197
+ # # <input type="hidden" name="_method" value="delete" />
198
+ # # <input onclick="return confirm('Are you sure?');"
199
+ # # value="Delete" type="submit" />
200
+ # # </div>
201
+ # # </form>"
117
202
  def button_to(name, options = {}, html_options = {})
118
203
  html_options = html_options.stringify_keys
119
204
  convert_boolean_attributes!(html_options, %w( disabled ))
@@ -124,7 +209,12 @@ module ActionView
124
209
  end
125
210
 
126
211
  form_method = method.to_s == 'get' ? 'get' : 'post'
127
-
212
+
213
+ request_token_tag = ''
214
+ if form_method == 'post' && protect_against_forgery?
215
+ request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
216
+ end
217
+
128
218
  if confirm = html_options.delete("confirm")
129
219
  html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
130
220
  end
@@ -133,112 +223,118 @@ module ActionView
133
223
  name ||= url
134
224
 
135
225
  html_options.merge!("type" => "submit", "value" => name)
136
-
137
- "<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
138
- method_tag + tag("input", html_options) + "</div></form>"
139
- end
140
-
141
226
 
142
- # DEPRECATED. It is reccommended to use the AssetTagHelper::image_tag within
143
- # a link_to method to generate a linked image.
144
- #
145
- # link_to(image_tag("rss", :size => "30x45", :border => 0), "http://www.example.com")
146
- def link_image_to(src, options = {}, html_options = {}, *parameters_for_method_reference)
147
- image_options = { "src" => src.include?("/") ? src : "/images/#{src}" }
148
- image_options["src"] += ".png" unless image_options["src"].include?(".")
149
-
150
- html_options = html_options.stringify_keys
151
- if html_options["alt"]
152
- image_options["alt"] = html_options["alt"]
153
- html_options.delete "alt"
154
- else
155
- image_options["alt"] = src.split("/").last.split(".").first.capitalize
156
- end
157
-
158
- if html_options["size"]
159
- image_options["width"], image_options["height"] = html_options["size"].split("x")
160
- html_options.delete "size"
161
- end
162
-
163
- if html_options["border"]
164
- image_options["border"] = html_options["border"]
165
- html_options.delete "border"
166
- end
167
-
168
- if html_options["align"]
169
- image_options["align"] = html_options["align"]
170
- html_options.delete "align"
171
- end
172
-
173
- link_to(tag("img", image_options), options, html_options, *parameters_for_method_reference)
227
+ "<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
228
+ method_tag + tag("input", html_options) + request_token_tag + "</div></form>"
174
229
  end
175
230
 
176
- alias_method :link_to_image, :link_image_to
177
- deprecate :link_to_image => "use link_to(image_tag(...), url)",
178
- :link_image_to => "use link_to(image_tag(...), url)"
179
231
 
180
232
  # Creates a link tag of the given +name+ using a URL created by the set of
181
- # +options+ unless the current request uri is the same as the links, in
233
+ # +options+ unless the current request URI is the same as the links, in
182
234
  # which case only the name is returned (or the given block is yielded, if
183
- # one exists). Refer to the documentation for link_to_unless for block usage.
235
+ # one exists). You can give link_to_unless_current a block which will
236
+ # specialize the default behavior (e.g., show a "Start Here" link rather
237
+ # than the link's text).
238
+ #
239
+ # ==== Examples
240
+ # Let's say you have a navigation menu...
184
241
  #
185
242
  # <ul id="navbar">
186
243
  # <li><%= link_to_unless_current("Home", { :action => "index" }) %></li>
187
244
  # <li><%= link_to_unless_current("About Us", { :action => "about" }) %></li>
188
245
  # </ul>
189
246
  #
190
- # This will render the following HTML when on the about us page:
247
+ # If in the "about" action, it will render...
191
248
  #
192
249
  # <ul id="navbar">
193
250
  # <li><a href="/controller/index">Home</a></li>
194
251
  # <li>About Us</li>
195
252
  # </ul>
196
- def link_to_unless_current(name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
197
- link_to_unless current_page?(options), name, options, html_options, *parameters_for_method_reference, &block
253
+ #
254
+ # ...but if in the "home" action, it will render:
255
+ #
256
+ # <ul id="navbar">
257
+ # <li><a href="/controller/index">Home</a></li>
258
+ # <li><a href="/controller/about">About Us</a></li>
259
+ # </ul>
260
+ #
261
+ # The implicit block given to link_to_unless_current is evaluated if the current
262
+ # action is the action given. So, if we had a comments page and wanted to render a
263
+ # "Go Back" link instead of a link to the comments page, we could do something like this...
264
+ #
265
+ # <%=
266
+ # link_to_unless_current("Comment", { :controller => 'comments', :action => 'new}) do
267
+ # link_to("Go back", { :controller => 'posts', :action => 'index' })
268
+ # end
269
+ # %>
270
+ def link_to_unless_current(name, options = {}, html_options = {}, &block)
271
+ link_to_unless current_page?(options), name, options, html_options, &block
198
272
  end
199
273
 
200
274
  # Creates a link tag of the given +name+ using a URL created by the set of
201
- # +options+ unless +condition+ is true, in which case only the name is
202
- # returned. To specialize the default behavior, you can pass a block that
203
- # accepts the name or the full argument list for link_to_unless (see the example).
275
+ # +options+ unless +condition+ is true, in which case only the name is
276
+ # returned. To specialize the default behavior (i.e., show a login link rather
277
+ # than just the plaintext link text), you can pass a block that
278
+ # accepts the name or the full argument list for link_to_unless.
204
279
  #
280
+ # ==== Examples
205
281
  # <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) %>
282
+ # # If the user is logged in...
283
+ # # => <a href="/controller/reply/">Reply</a>
206
284
  #
207
- # This example uses a block to modify the link if the condition isn't met.
208
- #
209
- # <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
210
- # link_to(name, { :controller => "accounts", :action => "signup" })
211
- # end %>
212
- def link_to_unless(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
285
+ # <%=
286
+ # link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
287
+ # link_to(name, { :controller => "accounts", :action => "signup" })
288
+ # end
289
+ # %>
290
+ # # If the user is logged in...
291
+ # # => <a href="/controller/reply/">Reply</a>
292
+ # # If not...
293
+ # # => <a href="/accounts/signup">Reply</a>
294
+ def link_to_unless(condition, name, options = {}, html_options = {}, &block)
213
295
  if condition
214
296
  if block_given?
215
- block.arity <= 1 ? yield(name) : yield(name, options, html_options, *parameters_for_method_reference)
297
+ block.arity <= 1 ? yield(name) : yield(name, options, html_options)
216
298
  else
217
299
  name
218
300
  end
219
301
  else
220
- link_to(name, options, html_options, *parameters_for_method_reference)
221
- end
302
+ link_to(name, options, html_options)
303
+ end
222
304
  end
223
-
305
+
224
306
  # Creates a link tag of the given +name+ using a URL created by the set of
225
- # +options+ if +condition+ is true, in which case only the name is
307
+ # +options+ if +condition+ is true, in which case only the name is
226
308
  # returned. To specialize the default behavior, you can pass a block that
227
309
  # accepts the name or the full argument list for link_to_unless (see the examples
228
310
  # in link_to_unless).
229
- def link_to_if(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
230
- link_to_unless !condition, name, options, html_options, *parameters_for_method_reference, &block
311
+ #
312
+ # ==== Examples
313
+ # <%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) %>
314
+ # # If the user isn't logged in...
315
+ # # => <a href="/sessions/new/">Login</a>
316
+ #
317
+ # <%=
318
+ # link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) do
319
+ # link_to(@current_user.login, { :controller => "accounts", :action => "show", :id => @current_user })
320
+ # end
321
+ # %>
322
+ # # If the user isn't logged in...
323
+ # # => <a href="/sessions/new/">Login</a>
324
+ # # If they are logged in...
325
+ # # => <a href="/accounts/show/3">my_username</a>
326
+ def link_to_if(condition, name, options = {}, html_options = {}, &block)
327
+ link_to_unless !condition, name, options, html_options, &block
231
328
  end
232
329
 
233
330
  # Creates a mailto link tag to the specified +email_address+, which is
234
331
  # also used as the name of the link unless +name+ is specified. Additional
235
- # html attributes for the link can be passed in +html_options+.
332
+ # HTML attributes for the link can be passed in +html_options+.
236
333
  #
237
- # mail_to has several methods for hindering email harvestors and customizing
334
+ # mail_to has several methods for hindering email harvesters and customizing
238
335
  # the email itself by passing special keys to +html_options+.
239
336
  #
240
- # Special HTML Options:
241
- #
337
+ # ==== Options
242
338
  # * <tt>:encode</tt> - This key will accept the strings "javascript" or "hex".
243
339
  # Passing "javascript" will dynamically create and encode the mailto: link then
244
340
  # eval it into the DOM of the page. This method will not show the link on
@@ -257,23 +353,25 @@ module ActionView
257
353
  # * <tt>:cc</tt> - Carbon Copy addition recipients on the email.
258
354
  # * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
259
355
  #
260
- # Examples:
261
- # mail_to "me@domain.com" # => <a href="mailto:me@domain.com">me@domain.com</a>
262
- # mail_to "me@domain.com", "My email", :encode => "javascript" # =>
263
- # <script type="text/javascript">eval(unescape('%64%6f%63...%6d%65%6e'))</script>
356
+ # ==== Examples
357
+ # mail_to "me@domain.com"
358
+ # # => <a href="mailto:me@domain.com">me@domain.com</a>
359
+ #
360
+ # mail_to "me@domain.com", "My email", :encode => "javascript"
361
+ # # => <script type="text/javascript">eval(unescape('%64%6f%63...%6d%65%6e'))</script>
264
362
  #
265
- # mail_to "me@domain.com", "My email", :encode => "hex" # =>
266
- # <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>
363
+ # mail_to "me@domain.com", "My email", :encode => "hex"
364
+ # # => <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>
267
365
  #
268
- # mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email" # =>
269
- # <a href="mailto:me@domain.com" class="email">me_at_domain_dot_com</a>
366
+ # mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
367
+ # # => <a href="mailto:me@domain.com" class="email">me_at_domain_dot_com</a>
270
368
  #
271
- # mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
272
- # :subject => "This is an example email" # =>
273
- # <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
369
+ # mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
370
+ # :subject => "This is an example email"
371
+ # # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
274
372
  def mail_to(email_address, name = nil, html_options = {})
275
373
  html_options = html_options.stringify_keys
276
- encode = html_options.delete("encode")
374
+ encode = html_options.delete("encode").to_s
277
375
  cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body")
278
376
 
279
377
  string = ''
@@ -295,8 +393,16 @@ module ActionView
295
393
  for i in 0...tmp.length
296
394
  string << sprintf("%%%x",tmp[i])
297
395
  end
298
- "<script type=\"text/javascript\">eval(unescape('#{string}'))</script>"
396
+ "<script type=\"#{Mime::JS}\">eval(unescape('#{string}'))</script>"
299
397
  elsif encode == "hex"
398
+ email_address_encoded = ''
399
+ email_address_obfuscated.each_byte do |c|
400
+ email_address_encoded << sprintf("&#%d;", c)
401
+ end
402
+
403
+ protocol = 'mailto:'
404
+ protocol.each_byte { |c| string << sprintf("&#%d;", c) }
405
+
300
406
  for i in 0...email_address.length
301
407
  if email_address[i,1] =~ /\w/
302
408
  string << sprintf("%%%x",email_address[i])
@@ -304,13 +410,28 @@ module ActionView
304
410
  string << email_address[i,1]
305
411
  end
306
412
  end
307
- content_tag "a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:#{string}#{extras}" })
413
+ content_tag "a", name || email_address_encoded, html_options.merge({ "href" => "#{string}#{extras}" })
308
414
  else
309
415
  content_tag "a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:#{email_address}#{extras}" })
310
416
  end
311
417
  end
312
418
 
313
- # True if the current request uri was generated by the given +options+.
419
+ # True if the current request URI was generated by the given +options+.
420
+ #
421
+ # ==== Examples
422
+ # Let's say we're in the <tt>/shop/checkout</tt> action.
423
+ #
424
+ # current_page?(:action => 'process')
425
+ # # => false
426
+ #
427
+ # current_page?(:controller => 'shop', :action => 'checkout')
428
+ # # => true
429
+ #
430
+ # current_page?(:action => 'checkout')
431
+ # # => true
432
+ #
433
+ # current_page?(:controller => 'library', :action => 'checkout')
434
+ # # => false
314
435
  def current_page?(options)
315
436
  url_string = CGI.escapeHTML(url_for(options))
316
437
  request = @controller.request
@@ -322,22 +443,14 @@ module ActionView
322
443
  end
323
444
 
324
445
  private
325
- def convert_options_to_javascript!(html_options)
446
+ def convert_options_to_javascript!(html_options, url = '')
326
447
  confirm, popup = html_options.delete("confirm"), html_options.delete("popup")
327
448
 
328
- # post is deprecated, but if its specified and method is not, assume that method = :post
329
- method, post = html_options.delete("method"), html_options.delete("post")
330
- if !method && post
331
- ActiveSupport::Deprecation.warn(
332
- "Passing :post as a link modifier is deprecated. " +
333
- "Use :method => \"post\" instead. :post will be removed in Rails 2.0."
334
- )
335
- method = :post
336
- end
337
-
449
+ method, href = html_options.delete("method"), html_options['href']
450
+
338
451
  html_options["onclick"] = case
339
452
  when popup && method
340
- raise ActionView::ActionViewError, "You can't use :popup and :post in the same link"
453
+ raise ActionView::ActionViewError, "You can't use :popup and :method in the same link"
341
454
  when confirm && popup
342
455
  "if (#{confirm_javascript_function(confirm)}) { #{popup_javascript_function(popup)} };return false;"
343
456
  when confirm && method
@@ -345,32 +458,37 @@ module ActionView
345
458
  when confirm
346
459
  "return #{confirm_javascript_function(confirm)};"
347
460
  when method
348
- "#{method_javascript_function(method)}return false;"
461
+ "#{method_javascript_function(method, url, href)}return false;"
349
462
  when popup
350
463
  popup_javascript_function(popup) + 'return false;'
351
464
  else
352
465
  html_options["onclick"]
353
466
  end
354
467
  end
355
-
468
+
356
469
  def confirm_javascript_function(confirm)
357
470
  "confirm('#{escape_javascript(confirm)}')"
358
471
  end
359
-
472
+
360
473
  def popup_javascript_function(popup)
361
474
  popup.is_a?(Array) ? "window.open(this.href,'#{popup.first}','#{popup.last}');" : "window.open(this.href);"
362
475
  end
363
-
364
- def method_javascript_function(method)
365
- submit_function =
476
+
477
+ def method_javascript_function(method, url = '', href = nil)
478
+ action = (href && url.size > 0) ? "'#{url}'" : 'this.href'
479
+ submit_function =
366
480
  "var f = document.createElement('form'); f.style.display = 'none'; " +
367
- "this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;"
368
-
481
+ "this.parentNode.appendChild(f); f.method = 'POST'; f.action = #{action};"
482
+
369
483
  unless method == :post
370
484
  submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "
371
485
  submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);"
372
486
  end
373
-
487
+
488
+ if protect_against_forgery?
489
+ submit_function << "var s = document.createElement('input'); s.setAttribute('type', 'hidden'); "
490
+ submit_function << "s.setAttribute('name', '#{request_forgery_protection_token}'); s.setAttribute('value', '#{escape_javascript form_authenticity_token}'); f.appendChild(s);"
491
+ end
374
492
  submit_function << "f.submit();"
375
493
  end
376
494