actionpack 3.0.20 → 3.1.0.beta1

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 (161) hide show
  1. data/CHANGELOG +88 -142
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +5 -6
  4. data/lib/abstract_controller.rb +1 -0
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +24 -19
  7. data/lib/abstract_controller/callbacks.rb +19 -19
  8. data/lib/abstract_controller/helpers.rb +11 -13
  9. data/lib/abstract_controller/layouts.rb +4 -5
  10. data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
  11. data/lib/abstract_controller/rendering.rb +34 -31
  12. data/lib/abstract_controller/url_for.rb +27 -0
  13. data/lib/abstract_controller/view_paths.rb +31 -6
  14. data/lib/action_controller.rb +5 -3
  15. data/lib/action_controller/base.rb +15 -16
  16. data/lib/action_controller/caching.rb +2 -2
  17. data/lib/action_controller/caching/actions.rb +11 -12
  18. data/lib/action_controller/caching/fragments.rb +41 -19
  19. data/lib/action_controller/caching/pages.rb +3 -9
  20. data/lib/action_controller/caching/sweeping.rb +0 -1
  21. data/lib/action_controller/deprecated.rb +1 -1
  22. data/lib/action_controller/log_subscriber.rb +1 -1
  23. data/lib/action_controller/metal.rb +78 -20
  24. data/lib/action_controller/metal/compatibility.rb +0 -9
  25. data/lib/action_controller/metal/conditional_get.rb +9 -9
  26. data/lib/action_controller/metal/data_streaming.rb +145 -0
  27. data/lib/action_controller/metal/force_ssl.rb +35 -0
  28. data/lib/action_controller/metal/head.rb +1 -1
  29. data/lib/action_controller/metal/helpers.rb +37 -44
  30. data/lib/action_controller/metal/hide_actions.rb +2 -3
  31. data/lib/action_controller/metal/http_authentication.rb +41 -38
  32. data/lib/action_controller/metal/implicit_render.rb +13 -13
  33. data/lib/action_controller/metal/instrumentation.rb +2 -2
  34. data/lib/action_controller/metal/mime_responds.rb +25 -19
  35. data/lib/action_controller/metal/params_wrapper.rb +224 -0
  36. data/lib/action_controller/metal/redirecting.rb +6 -2
  37. data/lib/action_controller/metal/renderers.rb +50 -36
  38. data/lib/action_controller/metal/rendering.rb +34 -25
  39. data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
  40. data/lib/action_controller/metal/responder.rb +47 -12
  41. data/lib/action_controller/metal/streaming.rb +244 -138
  42. data/lib/action_controller/metal/testing.rb +0 -9
  43. data/lib/action_controller/metal/url_for.rb +12 -14
  44. data/lib/action_controller/railtie.rb +19 -37
  45. data/lib/action_controller/railties/paths.rb +24 -0
  46. data/lib/action_controller/record_identifier.rb +4 -10
  47. data/lib/action_controller/test_case.rb +36 -19
  48. data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
  49. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
  50. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
  51. data/lib/action_dispatch.rb +4 -1
  52. data/lib/action_dispatch/http/cache.rb +5 -32
  53. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  54. data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
  55. data/lib/action_dispatch/http/mime_type.rb +45 -5
  56. data/lib/action_dispatch/http/rack_cache.rb +58 -0
  57. data/lib/action_dispatch/http/request.rb +27 -41
  58. data/lib/action_dispatch/http/response.rb +56 -54
  59. data/lib/action_dispatch/http/upload.rb +1 -11
  60. data/lib/action_dispatch/http/url.rb +102 -42
  61. data/lib/action_dispatch/middleware/callbacks.rb +8 -25
  62. data/lib/action_dispatch/middleware/closed_error.rb +7 -0
  63. data/lib/action_dispatch/middleware/cookies.rb +37 -15
  64. data/lib/action_dispatch/middleware/flash.rb +80 -11
  65. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  66. data/lib/action_dispatch/middleware/reloader.rb +76 -0
  67. data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
  68. data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
  69. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
  70. data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
  71. data/lib/action_dispatch/middleware/stack.rb +50 -17
  72. data/lib/action_dispatch/middleware/static.rb +41 -29
  73. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
  74. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  75. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
  76. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
  77. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
  78. data/lib/action_dispatch/railtie.rb +8 -0
  79. data/lib/action_dispatch/routing.rb +13 -1
  80. data/lib/action_dispatch/routing/mapper.rb +345 -227
  81. data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
  82. data/lib/action_dispatch/routing/redirection.rb +110 -0
  83. data/lib/action_dispatch/routing/route.rb +15 -13
  84. data/lib/action_dispatch/routing/route_set.rb +116 -90
  85. data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
  86. data/lib/action_dispatch/routing/url_for.rb +25 -1
  87. data/lib/action_dispatch/testing/assertions/response.rb +8 -10
  88. data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
  89. data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
  90. data/lib/action_dispatch/testing/integration.rb +37 -28
  91. data/lib/action_dispatch/testing/performance_test.rb +1 -3
  92. data/lib/action_dispatch/testing/test_process.rb +1 -1
  93. data/lib/action_dispatch/testing/test_request.rb +9 -3
  94. data/lib/action_dispatch/testing/test_response.rb +4 -111
  95. data/lib/action_pack.rb +1 -1
  96. data/lib/action_pack/version.rb +3 -3
  97. data/lib/action_view.rb +39 -24
  98. data/lib/action_view/base.rb +61 -86
  99. data/lib/action_view/buffers.rb +43 -0
  100. data/lib/action_view/context.rb +21 -24
  101. data/lib/action_view/flows.rb +79 -0
  102. data/lib/action_view/helpers.rb +8 -6
  103. data/lib/action_view/helpers/active_model_helper.rb +0 -23
  104. data/lib/action_view/helpers/asset_paths.rb +79 -0
  105. data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
  106. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
  107. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
  108. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
  109. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
  110. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  111. data/lib/action_view/helpers/cache_helper.rb +11 -19
  112. data/lib/action_view/helpers/capture_helper.rb +19 -8
  113. data/lib/action_view/helpers/controller_helper.rb +21 -0
  114. data/lib/action_view/helpers/csrf_helper.rb +22 -4
  115. data/lib/action_view/helpers/date_helper.rb +36 -22
  116. data/lib/action_view/helpers/form_helper.rb +199 -113
  117. data/lib/action_view/helpers/form_options_helper.rb +10 -11
  118. data/lib/action_view/helpers/form_tag_helper.rb +94 -22
  119. data/lib/action_view/helpers/javascript_helper.rb +24 -107
  120. data/lib/action_view/helpers/number_helper.rb +36 -33
  121. data/lib/action_view/helpers/output_safety_helper.rb +38 -0
  122. data/lib/action_view/helpers/record_tag_helper.rb +6 -6
  123. data/lib/action_view/helpers/rendering_helper.rb +90 -0
  124. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  125. data/lib/action_view/helpers/sprockets_helper.rb +69 -0
  126. data/lib/action_view/helpers/tag_helper.rb +34 -12
  127. data/lib/action_view/helpers/text_helper.rb +30 -145
  128. data/lib/action_view/helpers/translation_helper.rb +10 -17
  129. data/lib/action_view/helpers/url_helper.rb +70 -67
  130. data/lib/action_view/locale/en.yml +1 -1
  131. data/lib/action_view/lookup_context.rb +36 -14
  132. data/lib/action_view/{paths.rb → path_set.rb} +9 -8
  133. data/lib/action_view/railtie.rb +12 -4
  134. data/lib/action_view/renderer/abstract_renderer.rb +36 -0
  135. data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
  136. data/lib/action_view/renderer/renderer.rb +54 -0
  137. data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
  138. data/lib/action_view/renderer/template_renderer.rb +74 -0
  139. data/lib/action_view/template.rb +91 -54
  140. data/lib/action_view/template/error.rb +11 -8
  141. data/lib/action_view/template/handler.rb +9 -1
  142. data/lib/action_view/template/handlers.rb +9 -9
  143. data/lib/action_view/template/handlers/builder.rb +4 -4
  144. data/lib/action_view/template/handlers/erb.rb +21 -41
  145. data/lib/action_view/template/resolver.rb +171 -57
  146. data/lib/action_view/template/text.rb +0 -4
  147. data/lib/action_view/test_case.rb +32 -16
  148. data/lib/action_view/testing/resolvers.rb +16 -10
  149. data/lib/sprockets/railtie.rb +100 -0
  150. metadata +162 -140
  151. checksums.yaml +0 -7
  152. data/lib/action_controller/deprecated/base.rb +0 -143
  153. data/lib/action_controller/deprecated/dispatcher.rb +0 -28
  154. data/lib/action_controller/deprecated/url_writer.rb +0 -14
  155. data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
  156. data/lib/action_view/helpers/prototype_helper.rb +0 -851
  157. data/lib/action_view/helpers/raw_output_helper.rb +0 -18
  158. data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
  159. data/lib/action_view/render/layouts.rb +0 -83
  160. data/lib/action_view/render/rendering.rb +0 -67
  161. data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -2,6 +2,7 @@ require 'cgi'
2
2
  require 'erb'
3
3
  require 'action_view/helpers/form_helper'
4
4
  require 'active_support/core_ext/object/blank'
5
+ require 'active_support/core_ext/string/output_safety'
5
6
 
6
7
  module ActionView
7
8
  # = Action View Form Option Helpers
@@ -100,7 +101,6 @@ module ActionView
100
101
  #
101
102
  module FormOptionsHelper
102
103
  # ERB::Util can mask some helpers like textilize. Make sure to include them.
103
- include ERB::Util
104
104
  include TextHelper
105
105
 
106
106
  # Create a select tag and a series of contained option tags for the provided object and method.
@@ -247,7 +247,7 @@ module ActionView
247
247
  #
248
248
  # time_zone_select( "user", 'time_zone', /Australia/)
249
249
  #
250
- # time_zone_select( "user", "time_zone", ActiveSupport::Timezone.all.sort, :model => ActiveSupport::Timezone)
250
+ # time_zone_select( "user", "time_zone", ActiveSupport::TimeZone.all.sort, :model => ActiveSupport::TimeZone)
251
251
  def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
252
252
  InstanceTag.new(object, method, self, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options)
253
253
  end
@@ -297,17 +297,16 @@ module ActionView
297
297
  def options_for_select(container, selected = nil)
298
298
  return container if String === container
299
299
 
300
- container = container.to_a if Hash === container
301
300
  selected, disabled = extract_selected_and_disabled(selected).map do | r |
302
- Array.wrap(r).map { |item| item.to_s }
301
+ Array.wrap(r).map(&:to_s)
303
302
  end
304
303
 
305
304
  container.map do |element|
306
305
  html_attributes = option_html_attributes(element)
307
- text, value = option_text_and_value(element).map { |item| item.to_s }
306
+ text, value = option_text_and_value(element).map(&:to_s)
308
307
  selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
309
308
  disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
310
- %(<option value="#{html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text)}</option>)
309
+ %(<option value="#{ERB::Util.html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{ERB::Util.html_escape(text)}</option>)
311
310
  end.join("\n").html_safe
312
311
 
313
312
  end
@@ -397,7 +396,7 @@ module ActionView
397
396
  def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
398
397
  collection.map do |group|
399
398
  group_label_string = eval("group.#{group_label_method}")
400
- "<optgroup label=\"#{html_escape(group_label_string)}\">" +
399
+ "<optgroup label=\"#{ERB::Util.html_escape(group_label_string)}\">" +
401
400
  options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) +
402
401
  '</optgroup>'
403
402
  end.join.html_safe
@@ -502,7 +501,7 @@ module ActionView
502
501
  return "" unless Array === element
503
502
  html_attributes = []
504
503
  element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v|
505
- html_attributes << " #{k}=\"#{html_escape(v.to_s)}\""
504
+ html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
506
505
  end
507
506
  html_attributes.join
508
507
  end
@@ -596,13 +595,13 @@ module ActionView
596
595
  private
597
596
  def add_options(option_tags, options, value = nil)
598
597
  if options[:include_blank]
599
- option_tags = content_tag('option', options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, :value => '') + "\n" + option_tags
598
+ option_tags = "<option value=\"\">#{ERB::Util.html_escape(options[:include_blank]) if options[:include_blank].kind_of?(String)}</option>\n" + option_tags
600
599
  end
601
600
  if value.blank? && options[:prompt]
602
601
  prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('helpers.select.prompt', :default => 'Please select')
603
- option_tags = content_tag('option', prompt, :value => '') + "\n" + option_tags
602
+ option_tags = "<option value=\"\">#{ERB::Util.html_escape(prompt)}</option>\n" + option_tags
604
603
  end
605
- option_tags
604
+ option_tags.html_safe
606
605
  end
607
606
  end
608
607
 
@@ -1,6 +1,7 @@
1
1
  require 'cgi'
2
2
  require 'action_view/helpers/tag_helper'
3
3
  require 'active_support/core_ext/object/blank'
4
+ require 'active_support/core_ext/string/output_safety'
4
5
 
5
6
  module ActionView
6
7
  # = Action View Form Tag Helpers
@@ -24,6 +25,9 @@ module ActionView
24
25
  # * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
25
26
  # If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
26
27
  # is added to simulate the verb over post.
28
+ # * <tt>:authenticity_token</tt> - Authenticity token to use in the form. Use only if you need to
29
+ # pass custom authenticity token string, or to not add authenticity_token field at all
30
+ # (by passing <tt>false</tt>).
27
31
  # * A list of parameters to feed to the URL the form will be posted to.
28
32
  # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
29
33
  # submit behaviour. By default this behaviour is an ajax submit.
@@ -46,8 +50,14 @@ module ActionView
46
50
  # <%= form_tag('/posts', :remote => true) %>
47
51
  # # => <form action="/posts" method="post" data-remote="true">
48
52
  #
49
- def form_tag(url_for_options = {}, options = {}, &block)
50
- html_options = html_options_for_form(url_for_options, options)
53
+ # form_tag('http://far.away.com/form', :authenticity_token => false)
54
+ # # form without authenticity token
55
+ #
56
+ # form_tag('http://far.away.com/form', :authenticity_token => "cf50faa3fe97702ca1ae")
57
+ # # form with custom authenticity token
58
+ #
59
+ def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)
60
+ html_options = html_options_for_form(url_for_options, options, *parameters_for_url)
51
61
  if block_given?
52
62
  form_tag_in_block(html_options, &block)
53
63
  else
@@ -64,6 +74,8 @@ module ActionView
64
74
  # ==== Options
65
75
  # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
66
76
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
77
+ # * <tt>:include_blank</tt> - If set to true, an empty option will be create
78
+ # * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something
67
79
  # * Any other key creates standard HTML attributes for the tag.
68
80
  #
69
81
  # ==== Examples
@@ -89,22 +101,26 @@ module ActionView
89
101
  # # => <select class="form_input" id="access" multiple="multiple" name="access[]"><option>Read</option>
90
102
  # # <option>Write</option></select>
91
103
  #
104
+ # select_tag "people", options_from_collection_for_select(@people, "id", "name"), :include_blank => true
105
+ # # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
106
+ #
107
+ # select_tag "people", options_from_collection_for_select(@people, "id", "name"), :prompt => "Select something"
108
+ # # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
109
+ #
92
110
  # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>", :disabled => true
93
111
  # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
94
112
  # # <option>Paris</option><option>Rome</option></select>
95
113
  def select_tag(name, option_tags = nil, options = {})
96
- if Array === option_tags
97
- ActiveSupport::Deprecation.warn 'Passing an array of option_tags to select_tag implicitly joins them without marking them as HTML-safe. Pass option_tags.join.html_safe instead.', caller
114
+ html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
115
+
116
+ if options.delete(:include_blank)
117
+ option_tags = "<option value=\"\"></option>".html_safe + option_tags
98
118
  end
99
119
 
100
- html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
101
- if blank = options.delete(:include_blank)
102
- if blank.kind_of?(String)
103
- option_tags = content_tag(:option, blank, :value => '').safe_concat(option_tags)
104
- else
105
- option_tags = content_tag(:option, '', :value => '').safe_concat(option_tags)
106
- end
120
+ if prompt = options.delete(:prompt)
121
+ option_tags = "<option value=\"\">#{prompt}</option>".html_safe + option_tags
107
122
  end
123
+
108
124
  content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
109
125
  end
110
126
 
@@ -295,7 +311,7 @@ module ActionView
295
311
  end
296
312
 
297
313
  escape = options.key?("escape") ? options.delete("escape") : true
298
- content = html_escape(content) if escape
314
+ content = ERB::Util.html_escape(content) if escape
299
315
 
300
316
  content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
301
317
  end
@@ -398,12 +414,65 @@ module ActionView
398
414
  end
399
415
 
400
416
  if confirm = options.delete("confirm")
401
- add_confirm_to_attributes!(options, confirm)
417
+ options["data-confirm"] = confirm
402
418
  end
403
419
 
404
420
  tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys)
405
421
  end
406
422
 
423
+ # Creates a button element that defines a <tt>submit</tt> button,
424
+ # <tt>reset</tt>button or a generic button which can be used in
425
+ # JavaScript, for example. You can use the button tag as a regular
426
+ # submit tag but it isn't supported in legacy browsers. However,
427
+ # the button tag allows richer labels such as images and emphasis,
428
+ # so this helper will also accept a block.
429
+ #
430
+ # ==== Options
431
+ # * <tt>:confirm => 'question?'</tt> - If present, the
432
+ # unobtrusive JavaScript drivers will provide a prompt with
433
+ # the question specified. If the user accepts, the form is
434
+ # processed normally, otherwise no action is taken.
435
+ # * <tt>:disabled</tt> - If true, the user will not be able to
436
+ # use this input.
437
+ # * <tt>:disable_with</tt> - Value of this parameter will be
438
+ # used as the value for a disabled version of the submit
439
+ # button when the form is submitted. This feature is provided
440
+ # by the unobtrusive JavaScript driver.
441
+ # * Any other key creates standard HTML options for the tag.
442
+ #
443
+ # ==== Examples
444
+ # button_tag
445
+ # # => <button name="button" type="submit">Button</button>
446
+ #
447
+ # button_tag(:type => 'button') do
448
+ # content_tag(:strong, 'Ask me!')
449
+ # end
450
+ # # => <button name="button" type="button">
451
+ # <strong>Ask me!</strong>
452
+ # </button>
453
+ #
454
+ # button_tag "Checkout", :disable_with => "Please wait..."
455
+ # # => <button data-disable-with="Please wait..." name="button"
456
+ # type="submit">Checkout</button>
457
+ #
458
+ def button_tag(content_or_options = nil, options = nil, &block)
459
+ options = content_or_options if block_given? && content_or_options.is_a?(Hash)
460
+ options ||= {}
461
+ options.stringify_keys!
462
+
463
+ if disable_with = options.delete("disable_with")
464
+ options["data-disable-with"] = disable_with
465
+ end
466
+
467
+ if confirm = options.delete("confirm")
468
+ options["data-confirm"] = confirm
469
+ end
470
+
471
+ options.reverse_merge! 'name' => 'button', 'type' => 'submit'
472
+
473
+ content_tag :button, content_or_options || 'Button', options, &block
474
+ end
475
+
407
476
  # Displays an image which when clicked will submit the form.
408
477
  #
409
478
  # <tt>source</tt> is passed to AssetTagHelper#path_to_image
@@ -431,7 +500,7 @@ module ActionView
431
500
  options.stringify_keys!
432
501
 
433
502
  if confirm = options.delete("confirm")
434
- add_confirm_to_attributes!(options, confirm)
503
+ options["data-confirm"] = confirm
435
504
  end
436
505
 
437
506
  tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys)
@@ -529,14 +598,15 @@ module ActionView
529
598
  end
530
599
 
531
600
  private
532
- def html_options_for_form(url_for_options, options)
601
+ def html_options_for_form(url_for_options, options, *parameters_for_url)
533
602
  options.stringify_keys.tap do |html_options|
534
603
  html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
535
604
  # The following URL is unescaped, this is just a hash of options, and it is the
536
- # responsability of the caller to escape all the values.
537
- html_options["action"] = url_for(url_for_options)
605
+ # responsibility of the caller to escape all the values.
606
+ html_options["action"] = url_for(url_for_options, *parameters_for_url)
538
607
  html_options["accept-charset"] = "UTF-8"
539
608
  html_options["data-remote"] = true if html_options.delete("remote")
609
+ html_options["authenticity_token"] = html_options.delete("authenticity_token") if html_options.has_key?("authenticity_token")
540
610
  end
541
611
  end
542
612
 
@@ -544,6 +614,7 @@ module ActionView
544
614
  snowman_tag = tag(:input, :type => "hidden",
545
615
  :name => "utf8", :value => "&#x2713;".html_safe)
546
616
 
617
+ authenticity_token = html_options.delete("authenticity_token")
547
618
  method = html_options.delete("method").to_s
548
619
 
549
620
  method_tag = case method
@@ -552,10 +623,10 @@ module ActionView
552
623
  ''
553
624
  when /^post$/i, "", nil
554
625
  html_options["method"] = "post"
555
- token_tag
626
+ token_tag(authenticity_token)
556
627
  else
557
628
  html_options["method"] = "post"
558
- tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag
629
+ tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag(authenticity_token)
559
630
  end
560
631
 
561
632
  tags = snowman_tag << method_tag
@@ -575,11 +646,12 @@ module ActionView
575
646
  output.safe_concat("</form>")
576
647
  end
577
648
 
578
- def token_tag
579
- unless protect_against_forgery?
649
+ def token_tag(token)
650
+ if token == false || !protect_against_forgery?
580
651
  ''
581
652
  else
582
- tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
653
+ token = form_authenticity_token if token.nil?
654
+ tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => token)
583
655
  end
584
656
  end
585
657
 
@@ -1,42 +1,8 @@
1
1
  require 'action_view/helpers/tag_helper'
2
2
 
3
3
  module ActionView
4
- # = Action View JavaScript Helpers
5
4
  module Helpers
6
- # Provides functionality for working with JavaScript in your views.
7
- #
8
- # == Ajax, controls and visual effects
9
- #
10
- # * For information on using Ajax, see
11
- # ActionView::Helpers::PrototypeHelper.
12
- # * For information on using controls and visual effects, see
13
- # ActionView::Helpers::ScriptaculousHelper.
14
- #
15
- # == Including the JavaScript libraries into your pages
16
- #
17
- # Rails includes the Prototype JavaScript framework and the Scriptaculous
18
- # JavaScript controls and visual effects library. If you wish to use
19
- # these libraries and their helpers (ActionView::Helpers::PrototypeHelper
20
- # and ActionView::Helpers::ScriptaculousHelper), you must do one of the
21
- # following:
22
- #
23
- # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
24
- # section of your page (recommended): This function will return
25
- # references to the JavaScript files created by the +rails+ command in
26
- # your <tt>public/javascripts</tt> directory. Using it is recommended as
27
- # the browser can then cache the libraries instead of fetching all the
28
- # functions anew on every request.
29
- # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
30
- # will only include the Prototype core library, which means you are able
31
- # to use all basic AJAX functionality. For the Scriptaculous-based
32
- # JavaScript helpers, like visual effects, autocompletion, drag and drop
33
- # and so on, you should use the method described above.
34
- #
35
- # For documentation on +javascript_include_tag+ see
36
- # ActionView::Helpers::AssetTagHelper.
37
5
  module JavaScriptHelper
38
- include PrototypeHelper
39
-
40
6
  JS_ESCAPE_MAP = {
41
7
  '\\' => '\\\\',
42
8
  '</' => '<\/',
@@ -47,15 +13,19 @@ module ActionView
47
13
  "'" => "\\'" }
48
14
 
49
15
  # Escape carrier returns and single and double quotes for JavaScript segments.
16
+ # Also available through the alias j(). This is particularly helpful in JavaScript responses, like:
17
+ #
18
+ # $('some_element').replaceWith('<%=j render 'some/element_template' %>');
50
19
  def escape_javascript(javascript)
51
20
  if javascript
52
- result = javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] }
53
- javascript.html_safe? ? result.html_safe : result
21
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
54
22
  else
55
23
  ''
56
24
  end
57
25
  end
58
26
 
27
+ alias_method :j, :escape_javascript
28
+
59
29
  # Returns a JavaScript tag with the +content+ inside. Example:
60
30
  # javascript_tag "alert('All is good')"
61
31
  #
@@ -66,8 +36,8 @@ module ActionView
66
36
  # //]]>
67
37
  # </script>
68
38
  #
69
- # +html_options+ may be a hash of attributes for the <tt>\<script></tt> tag.
70
- # Example:
39
+ # +html_options+ may be a hash of attributes for the <tt>\<script></tt>
40
+ # tag. Example:
71
41
  # javascript_tag "alert('All is good')", :defer => 'defer'
72
42
  # # => <script defer="defer" type="text/javascript">alert('All is good')</script>
73
43
  #
@@ -92,87 +62,34 @@ module ActionView
92
62
  "\n//#{cdata_section("\n#{content}\n//")}\n".html_safe
93
63
  end
94
64
 
95
- # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
96
- # onclick handler.
97
- #
98
- # The first argument +name+ is used as the button's value or display text.
65
+ # Returns a button whose +onclick+ handler triggers the passed JavaScript.
99
66
  #
100
- # The next arguments are optional and may include the javascript function definition and a hash of html_options.
67
+ # The helper receives a name, JavaScript code, and an optional hash of HTML options. The
68
+ # name is used as button label and the JavaScript code goes into its +onclick+ attribute.
69
+ # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+.
101
70
  #
102
- # The +function+ argument can be omitted in favor of an +update_page+
103
- # block, which evaluates to a string when the template is rendered
104
- # (instead of making an Ajax request first).
71
+ # button_to_function "Greeting", "alert('Hello world!')", :class => "ok"
72
+ # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" />
105
73
  #
106
- # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
107
- #
108
- # Note: if you choose to specify the javascript function in a block, but would like to pass html_options, set the +function+ parameter to nil
109
- #
110
- # Examples:
111
- # button_to_function "Greeting", "alert('Hello world!')"
112
- # button_to_function "Delete", "if (confirm('Really?')) do_delete()"
113
- # button_to_function "Details" do |page|
114
- # page[:details].visual_effect :toggle_slide
115
- # end
116
- # button_to_function "Details", :class => "details_button" do |page|
117
- # page[:details].visual_effect :toggle_slide
118
- # end
119
- def button_to_function(name, *args, &block)
120
- html_options = args.extract_options!.symbolize_keys
121
-
122
- function = block_given? ? update_page(&block) : args[0] || ''
74
+ def button_to_function(name, function=nil, html_options={})
123
75
  onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
124
76
 
125
77
  tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
126
78
  end
127
79
 
128
- # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the
129
- # onclick handler and return false after the fact.
80
+ # Returns a link whose +onclick+ handler triggers the passed JavaScript.
130
81
  #
131
- # The first argument +name+ is used as the link text.
82
+ # The helper receives a name, JavaScript code, and an optional hash of HTML options. The
83
+ # name is used as the link text and the JavaScript code goes into the +onclick+ attribute.
84
+ # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. Once all
85
+ # the JavaScript is set, the helper appends "; return false;".
132
86
  #
133
- # The next arguments are optional and may include the javascript function definition and a hash of html_options.
87
+ # The +href+ attribute of the tag is set to "#" unles +html_options+ has one.
134
88
  #
135
- # The +function+ argument can be omitted in favor of an +update_page+
136
- # block, which evaluates to a string when the template is rendered
137
- # (instead of making an Ajax request first).
89
+ # link_to_function "Greeting", "alert('Hello world!')", :class => "nav_link"
90
+ # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a>
138
91
  #
139
- # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
140
- #
141
- # Note: if you choose to specify the javascript function in a block, but would like to pass html_options, set the +function+ parameter to nil
142
- #
143
- #
144
- # Examples:
145
- # link_to_function "Greeting", "alert('Hello world!')"
146
- # Produces:
147
- # <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
148
- #
149
- # link_to_function(image_tag("delete"), "if (confirm('Really?')) do_delete()")
150
- # Produces:
151
- # <a onclick="if (confirm('Really?')) do_delete(); return false;" href="#">
152
- # <img src="/images/delete.png?" alt="Delete"/>
153
- # </a>
154
- #
155
- # link_to_function("Show me more", nil, :id => "more_link") do |page|
156
- # page[:details].visual_effect :toggle_blind
157
- # page[:more_link].replace_html "Show me less"
158
- # end
159
- # Produces:
160
- # <a href="#" id="more_link" onclick="try {
161
- # $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
162
- # $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
163
- # }
164
- # catch (e) {
165
- # alert('RJS error:\n\n' + e.toString());
166
- # alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
167
- # \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
168
- # throw e
169
- # };
170
- # return false;">Show me more</a>
171
- #
172
- def link_to_function(name, *args, &block)
173
- html_options = args.extract_options!.symbolize_keys
174
-
175
- function = block_given? ? update_page(&block) : args[0] || ''
92
+ def link_to_function(name, function, html_options={})
176
93
  onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
177
94
  href = html_options[:href] || '#'
178
95