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.
- data/CHANGELOG +88 -142
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +24 -19
- data/lib/abstract_controller/callbacks.rb +19 -19
- data/lib/abstract_controller/helpers.rb +11 -13
- data/lib/abstract_controller/layouts.rb +4 -5
- data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
- data/lib/abstract_controller/rendering.rb +34 -31
- data/lib/abstract_controller/url_for.rb +27 -0
- data/lib/abstract_controller/view_paths.rb +31 -6
- data/lib/action_controller.rb +5 -3
- data/lib/action_controller/base.rb +15 -16
- data/lib/action_controller/caching.rb +2 -2
- data/lib/action_controller/caching/actions.rb +11 -12
- data/lib/action_controller/caching/fragments.rb +41 -19
- data/lib/action_controller/caching/pages.rb +3 -9
- data/lib/action_controller/caching/sweeping.rb +0 -1
- data/lib/action_controller/deprecated.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +78 -20
- data/lib/action_controller/metal/compatibility.rb +0 -9
- data/lib/action_controller/metal/conditional_get.rb +9 -9
- data/lib/action_controller/metal/data_streaming.rb +145 -0
- data/lib/action_controller/metal/force_ssl.rb +35 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +37 -44
- data/lib/action_controller/metal/hide_actions.rb +2 -3
- data/lib/action_controller/metal/http_authentication.rb +41 -38
- data/lib/action_controller/metal/implicit_render.rb +13 -13
- data/lib/action_controller/metal/instrumentation.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +25 -19
- data/lib/action_controller/metal/params_wrapper.rb +224 -0
- data/lib/action_controller/metal/redirecting.rb +6 -2
- data/lib/action_controller/metal/renderers.rb +50 -36
- data/lib/action_controller/metal/rendering.rb +34 -25
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
- data/lib/action_controller/metal/responder.rb +47 -12
- data/lib/action_controller/metal/streaming.rb +244 -138
- data/lib/action_controller/metal/testing.rb +0 -9
- data/lib/action_controller/metal/url_for.rb +12 -14
- data/lib/action_controller/railtie.rb +19 -37
- data/lib/action_controller/railties/paths.rb +24 -0
- data/lib/action_controller/record_identifier.rb +4 -10
- data/lib/action_controller/test_case.rb +36 -19
- data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +5 -32
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
- data/lib/action_dispatch/http/mime_type.rb +45 -5
- data/lib/action_dispatch/http/rack_cache.rb +58 -0
- data/lib/action_dispatch/http/request.rb +27 -41
- data/lib/action_dispatch/http/response.rb +56 -54
- data/lib/action_dispatch/http/upload.rb +1 -11
- data/lib/action_dispatch/http/url.rb +102 -42
- data/lib/action_dispatch/middleware/callbacks.rb +8 -25
- data/lib/action_dispatch/middleware/closed_error.rb +7 -0
- data/lib/action_dispatch/middleware/cookies.rb +37 -15
- data/lib/action_dispatch/middleware/flash.rb +80 -11
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
- data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
- data/lib/action_dispatch/middleware/stack.rb +50 -17
- data/lib/action_dispatch/middleware/static.rb +41 -29
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/routing.rb +13 -1
- data/lib/action_dispatch/routing/mapper.rb +345 -227
- data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
- data/lib/action_dispatch/routing/redirection.rb +110 -0
- data/lib/action_dispatch/routing/route.rb +15 -13
- data/lib/action_dispatch/routing/route_set.rb +116 -90
- data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
- data/lib/action_dispatch/routing/url_for.rb +25 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -10
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
- data/lib/action_dispatch/testing/integration.rb +37 -28
- data/lib/action_dispatch/testing/performance_test.rb +1 -3
- data/lib/action_dispatch/testing/test_process.rb +1 -1
- data/lib/action_dispatch/testing/test_request.rb +9 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -111
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +39 -24
- data/lib/action_view/base.rb +61 -86
- data/lib/action_view/buffers.rb +43 -0
- data/lib/action_view/context.rb +21 -24
- data/lib/action_view/flows.rb +79 -0
- data/lib/action_view/helpers.rb +8 -6
- data/lib/action_view/helpers/active_model_helper.rb +0 -23
- data/lib/action_view/helpers/asset_paths.rb +79 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +11 -19
- data/lib/action_view/helpers/capture_helper.rb +19 -8
- data/lib/action_view/helpers/controller_helper.rb +21 -0
- data/lib/action_view/helpers/csrf_helper.rb +22 -4
- data/lib/action_view/helpers/date_helper.rb +36 -22
- data/lib/action_view/helpers/form_helper.rb +199 -113
- data/lib/action_view/helpers/form_options_helper.rb +10 -11
- data/lib/action_view/helpers/form_tag_helper.rb +94 -22
- data/lib/action_view/helpers/javascript_helper.rb +24 -107
- data/lib/action_view/helpers/number_helper.rb +36 -33
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/sprockets_helper.rb +69 -0
- data/lib/action_view/helpers/tag_helper.rb +34 -12
- data/lib/action_view/helpers/text_helper.rb +30 -145
- data/lib/action_view/helpers/translation_helper.rb +10 -17
- data/lib/action_view/helpers/url_helper.rb +70 -67
- data/lib/action_view/locale/en.yml +1 -1
- data/lib/action_view/lookup_context.rb +36 -14
- data/lib/action_view/{paths.rb → path_set.rb} +9 -8
- data/lib/action_view/railtie.rb +12 -4
- data/lib/action_view/renderer/abstract_renderer.rb +36 -0
- data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
- data/lib/action_view/renderer/renderer.rb +54 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
- data/lib/action_view/renderer/template_renderer.rb +74 -0
- data/lib/action_view/template.rb +91 -54
- data/lib/action_view/template/error.rb +11 -8
- data/lib/action_view/template/handler.rb +9 -1
- data/lib/action_view/template/handlers.rb +9 -9
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb.rb +21 -41
- data/lib/action_view/template/resolver.rb +171 -57
- data/lib/action_view/template/text.rb +0 -4
- data/lib/action_view/test_case.rb +32 -16
- data/lib/action_view/testing/resolvers.rb +16 -10
- data/lib/sprockets/railtie.rb +100 -0
- metadata +162 -140
- checksums.yaml +0 -7
- data/lib/action_controller/deprecated/base.rb +0 -143
- data/lib/action_controller/deprecated/dispatcher.rb +0 -28
- data/lib/action_controller/deprecated/url_writer.rb +0 -14
- data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
- data/lib/action_view/helpers/prototype_helper.rb +0 -851
- data/lib/action_view/helpers/raw_output_helper.rb +0 -18
- data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
- data/lib/action_view/render/layouts.rb +0 -83
- data/lib/action_view/render/rendering.rb +0 -67
- 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::
|
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
|
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
|
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 =
|
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 =
|
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
|
-
|
50
|
-
|
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
|
-
|
97
|
-
|
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
|
-
|
101
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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 => "✓".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
|
-
|
649
|
+
def token_tag(token)
|
650
|
+
if token == false || !protect_against_forgery?
|
580
651
|
''
|
581
652
|
else
|
582
|
-
|
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
|
-
|
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>
|
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
|
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
|
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
|
-
#
|
103
|
-
#
|
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
|
-
|
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
|
129
|
-
# onclick handler and return false after the fact.
|
80
|
+
# Returns a link whose +onclick+ handler triggers the passed JavaScript.
|
130
81
|
#
|
131
|
-
# The
|
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
|
87
|
+
# The +href+ attribute of the tag is set to "#" unles +html_options+ has one.
|
134
88
|
#
|
135
|
-
#
|
136
|
-
#
|
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
|
-
|
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
|
-
# $("details").visualEffect("toggle_blind");
|
162
|
-
# $("more_link").update("Show me less");
|
163
|
-
# }
|
164
|
-
# catch (e) {
|
165
|
-
# alert('RJS error:\n\n' + e.toString());
|
166
|
-
# alert('$(\"details\").visualEffect(\"toggle_blind\");
|
167
|
-
# \n$(\"more_link\").update(\"Show me less\");');
|
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
|
|