actionview 4.2.10 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +141 -272
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view/base.rb +33 -21
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +52 -20
- data/lib/action_view/digestor.rb +86 -83
- data/lib/action_view/flows.rb +9 -11
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +8 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +74 -38
- data/lib/action_view/helpers/asset_url_helper.rb +160 -59
- data/lib/action_view/helpers/atom_feed_helper.rb +16 -16
- data/lib/action_view/helpers/cache_helper.rb +90 -35
- data/lib/action_view/helpers/capture_helper.rb +7 -6
- data/lib/action_view/helpers/controller_helper.rb +3 -2
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +156 -108
- data/lib/action_view/helpers/debug_helper.rb +3 -4
- data/lib/action_view/helpers/form_helper.rb +475 -94
- data/lib/action_view/helpers/form_options_helper.rb +87 -47
- data/lib/action_view/helpers/form_tag_helper.rb +88 -57
- data/lib/action_view/helpers/javascript_helper.rb +10 -10
- data/lib/action_view/helpers/number_helper.rb +76 -59
- data/lib/action_view/helpers/output_safety_helper.rb +34 -4
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +3 -3
- data/lib/action_view/helpers/sanitize_helper.rb +17 -14
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +132 -97
- data/lib/action_view/helpers/tags/check_box.rb +17 -17
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +9 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +68 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +3 -11
- data/lib/action_view/helpers/tags/collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/date_select.rb +36 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/label.rb +5 -1
- data/lib/action_view/helpers/tags/password_field.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/radio_button.rb +4 -4
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/select.rb +9 -9
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +5 -6
- data/lib/action_view/helpers/tags/translator.rb +15 -13
- data/lib/action_view/helpers/text_helper.rb +47 -30
- data/lib/action_view/helpers/translation_helper.rb +60 -30
- data/lib/action_view/helpers/url_helper.rb +132 -104
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/layouts.rb +59 -54
- data/lib/action_view/log_subscriber.rb +56 -7
- data/lib/action_view/lookup_context.rb +76 -61
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +28 -19
- data/lib/action_view/railtie.rb +30 -6
- data/lib/action_view/record_identifier.rb +51 -25
- data/lib/action_view/renderer/abstract_renderer.rb +19 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +55 -0
- data/lib/action_view/renderer/partial_renderer.rb +208 -206
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +46 -48
- data/lib/action_view/renderer/template_renderer.rb +65 -66
- data/lib/action_view/rendering.rb +16 -9
- data/lib/action_view/routing_url_for.rb +25 -17
- data/lib/action_view/tasks/cache_digests.rake +23 -0
- data/lib/action_view/template/error.rb +14 -13
- data/lib/action_view/template/handlers/builder.rb +7 -7
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +9 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +81 -0
- data/lib/action_view/template/handlers/erb/erubis.rb +81 -0
- data/lib/action_view/template/handlers/erb.rb +9 -76
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/handlers.rb +8 -6
- data/lib/action_view/template/html.rb +2 -4
- data/lib/action_view/template/resolver.rb +133 -109
- data/lib/action_view/template/text.rb +5 -8
- data/lib/action_view/template/types.rb +15 -17
- data/lib/action_view/template.rb +51 -28
- data/lib/action_view/test_case.rb +32 -27
- data/lib/action_view/testing/resolvers.rb +29 -31
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +26 -32
- data/lib/action_view.rb +5 -5
- data/lib/assets/compiled/rails-ujs.js +685 -0
- metadata +23 -23
- data/lib/action_view/tasks/dependencies.rake +0 -23
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
1
|
+
require "action_view/helpers/javascript_helper"
|
|
2
|
+
require "active_support/core_ext/array/access"
|
|
3
|
+
require "active_support/core_ext/hash/keys"
|
|
4
|
+
require "active_support/core_ext/string/output_safety"
|
|
5
5
|
|
|
6
6
|
module ActionView
|
|
7
7
|
# = Action View URL Helpers
|
|
@@ -35,20 +35,30 @@ module ActionView
|
|
|
35
35
|
when :back
|
|
36
36
|
_back_url
|
|
37
37
|
else
|
|
38
|
-
raise ArgumentError, "arguments passed to url_for can't be handled. Please require "
|
|
38
|
+
raise ArgumentError, "arguments passed to url_for can't be handled. Please require " \
|
|
39
39
|
"routes or provide your own implementation"
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def _back_url # :nodoc:
|
|
44
|
-
|
|
45
|
-
referrer || 'javascript:history.back()'
|
|
44
|
+
_filtered_referrer || "javascript:history.back()"
|
|
46
45
|
end
|
|
47
46
|
protected :_back_url
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
def _filtered_referrer # :nodoc:
|
|
49
|
+
if controller.respond_to?(:request)
|
|
50
|
+
referrer = controller.request.env["HTTP_REFERER"]
|
|
51
|
+
if referrer && URI(referrer).scheme != "javascript"
|
|
52
|
+
referrer
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
rescue URI::InvalidURIError
|
|
56
|
+
end
|
|
57
|
+
protected :_filtered_referrer
|
|
58
|
+
|
|
59
|
+
# Creates an anchor element of the given +name+ using a URL created by the set of +options+.
|
|
50
60
|
# See the valid options in the documentation for +url_for+. It's also possible to
|
|
51
|
-
# pass a String instead of an options hash, which generates
|
|
61
|
+
# pass a String instead of an options hash, which generates an anchor element that uses the
|
|
52
62
|
# value of the String as the href for the link. Using a <tt>:back</tt> Symbol instead
|
|
53
63
|
# of an options hash will generate a link to the referrer (a JavaScript back link
|
|
54
64
|
# will be used in place of a referrer if none exists). If +nil+ is passed as the name
|
|
@@ -95,10 +105,9 @@ module ActionView
|
|
|
95
105
|
# driver to prompt with the question specified (in this case, the
|
|
96
106
|
# resulting text would be <tt>question?</tt>. If the user accepts, the
|
|
97
107
|
# link is processed normally, otherwise no action is taken.
|
|
98
|
-
# * <tt>:disable_with</tt> - Value of this parameter will be
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
# by the unobtrusive JavaScript driver.
|
|
108
|
+
# * <tt>:disable_with</tt> - Value of this parameter will be used as the
|
|
109
|
+
# name for a disabled version of the link. This feature is provided by
|
|
110
|
+
# the unobtrusive JavaScript driver.
|
|
102
111
|
#
|
|
103
112
|
# ==== Examples
|
|
104
113
|
# Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
|
|
@@ -172,6 +181,11 @@ module ActionView
|
|
|
172
181
|
#
|
|
173
182
|
# link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
|
|
174
183
|
# # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
|
|
184
|
+
#
|
|
185
|
+
# Also you can set any link attributes such as <tt>target</tt>, <tt>rel</tt>, <tt>type</tt>:
|
|
186
|
+
#
|
|
187
|
+
# link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow"
|
|
188
|
+
# # => <a href="http://www.rubyonrails.org/" target="_blank" rel="nofollow">External link</a>
|
|
175
189
|
def link_to(name = nil, options = nil, html_options = nil, &block)
|
|
176
190
|
html_options, options, name = options, name, block if block_given?
|
|
177
191
|
options ||= {}
|
|
@@ -179,9 +193,9 @@ module ActionView
|
|
|
179
193
|
html_options = convert_options_to_data_attributes(options, html_options)
|
|
180
194
|
|
|
181
195
|
url = url_for(options)
|
|
182
|
-
html_options[
|
|
196
|
+
html_options["href".freeze] ||= url
|
|
183
197
|
|
|
184
|
-
content_tag(
|
|
198
|
+
content_tag("a".freeze, name || url, html_options, &block)
|
|
185
199
|
end
|
|
186
200
|
|
|
187
201
|
# Generates a form containing a single button that submits to the URL created
|
|
@@ -280,42 +294,46 @@ module ActionView
|
|
|
280
294
|
html_options, options = options, name if block_given?
|
|
281
295
|
options ||= {}
|
|
282
296
|
html_options ||= {}
|
|
283
|
-
|
|
284
297
|
html_options = html_options.stringify_keys
|
|
285
|
-
convert_boolean_attributes!(html_options, %w(disabled))
|
|
286
298
|
|
|
287
299
|
url = options.is_a?(String) ? options : url_for(options)
|
|
288
|
-
remote = html_options.delete(
|
|
289
|
-
params = html_options.delete(
|
|
290
|
-
|
|
291
|
-
method = html_options.delete(
|
|
292
|
-
method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) :
|
|
293
|
-
|
|
294
|
-
form_method = method ==
|
|
295
|
-
form_options = html_options.delete(
|
|
296
|
-
form_options[:class] ||= html_options.delete(
|
|
297
|
-
form_options
|
|
298
|
-
form_options
|
|
299
|
-
|
|
300
|
-
|
|
300
|
+
remote = html_options.delete("remote")
|
|
301
|
+
params = html_options.delete("params")
|
|
302
|
+
|
|
303
|
+
method = html_options.delete("method").to_s
|
|
304
|
+
method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".freeze.html_safe
|
|
305
|
+
|
|
306
|
+
form_method = method == "get" ? "get" : "post"
|
|
307
|
+
form_options = html_options.delete("form") || {}
|
|
308
|
+
form_options[:class] ||= html_options.delete("form_class") || "button_to"
|
|
309
|
+
form_options[:method] = form_method
|
|
310
|
+
form_options[:action] = url
|
|
311
|
+
form_options[:'data-remote'] = true if remote
|
|
312
|
+
|
|
313
|
+
request_token_tag = if form_method == "post"
|
|
314
|
+
request_method = method.empty? ? "post" : method
|
|
315
|
+
token_tag(nil, form_options: { action: url, method: request_method })
|
|
316
|
+
else
|
|
317
|
+
"".freeze
|
|
318
|
+
end
|
|
301
319
|
|
|
302
320
|
html_options = convert_options_to_data_attributes(options, html_options)
|
|
303
|
-
html_options[
|
|
321
|
+
html_options["type"] = "submit"
|
|
304
322
|
|
|
305
323
|
button = if block_given?
|
|
306
|
-
content_tag(
|
|
324
|
+
content_tag("button", html_options, &block)
|
|
307
325
|
else
|
|
308
|
-
html_options[
|
|
309
|
-
tag(
|
|
326
|
+
html_options["value"] = name || url
|
|
327
|
+
tag("input", html_options)
|
|
310
328
|
end
|
|
311
329
|
|
|
312
330
|
inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
|
|
313
331
|
if params
|
|
314
|
-
params.each do |
|
|
315
|
-
inner_tags.safe_concat tag(:input, type: "hidden", name:
|
|
332
|
+
to_form_params(params).each do |param|
|
|
333
|
+
inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value])
|
|
316
334
|
end
|
|
317
335
|
end
|
|
318
|
-
content_tag(
|
|
336
|
+
content_tag("form", inner_tags, form_options)
|
|
319
337
|
end
|
|
320
338
|
|
|
321
339
|
# Creates a link tag of the given +name+ using a URL created by the set of
|
|
@@ -428,6 +446,7 @@ module ActionView
|
|
|
428
446
|
# * <tt>:body</tt> - Preset the body of the email.
|
|
429
447
|
# * <tt>:cc</tt> - Carbon Copy additional recipients on the email.
|
|
430
448
|
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
|
|
449
|
+
# * <tt>:reply_to</tt> - Preset the Reply-To field of the email.
|
|
431
450
|
#
|
|
432
451
|
# ==== Obfuscation
|
|
433
452
|
# Prior to Rails 4.0, +mail_to+ provided options for encoding the address
|
|
@@ -457,73 +476,64 @@ module ActionView
|
|
|
457
476
|
html_options, name = name, nil if block_given?
|
|
458
477
|
html_options = (html_options || {}).stringify_keys
|
|
459
478
|
|
|
460
|
-
extras = %w{ cc bcc body subject }.map! { |item|
|
|
461
|
-
option = html_options.delete(item) || next
|
|
462
|
-
"#{item}=#{
|
|
479
|
+
extras = %w{ cc bcc body subject reply_to }.map! { |item|
|
|
480
|
+
option = html_options.delete(item).presence || next
|
|
481
|
+
"#{item.dasherize}=#{ERB::Util.url_encode(option)}"
|
|
463
482
|
}.compact
|
|
464
|
-
extras = extras.empty? ?
|
|
483
|
+
extras = extras.empty? ? "".freeze : "?" + extras.join("&")
|
|
465
484
|
|
|
466
|
-
encoded_email_address = ERB::Util.url_encode(email_address
|
|
485
|
+
encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@")
|
|
467
486
|
html_options["href"] = "mailto:#{encoded_email_address}#{extras}"
|
|
468
487
|
|
|
469
|
-
content_tag(
|
|
488
|
+
content_tag("a".freeze, name || email_address, html_options, &block)
|
|
470
489
|
end
|
|
471
490
|
|
|
472
491
|
# True if the current request URI was generated by the given +options+.
|
|
473
492
|
#
|
|
474
493
|
# ==== Examples
|
|
475
|
-
# Let's say we're in the <tt>http://www.example.com/shop/checkout?order=desc</tt> action.
|
|
494
|
+
# Let's say we're in the <tt>http://www.example.com/shop/checkout?order=desc&page=1</tt> action.
|
|
476
495
|
#
|
|
477
496
|
# current_page?(action: 'process')
|
|
478
497
|
# # => false
|
|
479
498
|
#
|
|
480
|
-
# current_page?(controller: 'shop', action: 'checkout')
|
|
481
|
-
# # => true
|
|
482
|
-
#
|
|
483
|
-
# current_page?(controller: 'shop', action: 'checkout', order: 'asc')
|
|
484
|
-
# # => false
|
|
485
|
-
#
|
|
486
499
|
# current_page?(action: 'checkout')
|
|
487
500
|
# # => true
|
|
488
501
|
#
|
|
489
502
|
# current_page?(controller: 'library', action: 'checkout')
|
|
490
503
|
# # => false
|
|
491
504
|
#
|
|
492
|
-
# current_page?('
|
|
493
|
-
# # => true
|
|
494
|
-
#
|
|
495
|
-
# current_page?('/shop/checkout')
|
|
505
|
+
# current_page?(controller: 'shop', action: 'checkout')
|
|
496
506
|
# # => true
|
|
497
507
|
#
|
|
498
|
-
#
|
|
499
|
-
#
|
|
500
|
-
# current_page?(action: 'process')
|
|
508
|
+
# current_page?(controller: 'shop', action: 'checkout', order: 'asc')
|
|
501
509
|
# # => false
|
|
502
510
|
#
|
|
503
|
-
# current_page?(controller: 'shop', action: 'checkout')
|
|
504
|
-
# # => true
|
|
505
|
-
#
|
|
506
511
|
# current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '1')
|
|
507
512
|
# # => true
|
|
508
513
|
#
|
|
509
514
|
# current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '2')
|
|
510
515
|
# # => false
|
|
511
516
|
#
|
|
512
|
-
# current_page?(
|
|
517
|
+
# current_page?('http://www.example.com/shop/checkout')
|
|
518
|
+
# # => true
|
|
519
|
+
#
|
|
520
|
+
# current_page?('http://www.example.com/shop/checkout', check_parameters: true)
|
|
513
521
|
# # => false
|
|
514
522
|
#
|
|
515
|
-
# current_page?(
|
|
523
|
+
# current_page?('/shop/checkout')
|
|
516
524
|
# # => true
|
|
517
525
|
#
|
|
518
|
-
# current_page?(
|
|
519
|
-
# # =>
|
|
526
|
+
# current_page?('http://www.example.com/shop/checkout?order=desc&page=1')
|
|
527
|
+
# # => true
|
|
520
528
|
#
|
|
521
529
|
# Let's say we're in the <tt>http://www.example.com/products</tt> action with method POST in case of invalid product.
|
|
522
530
|
#
|
|
523
531
|
# current_page?(controller: 'product', action: 'index')
|
|
524
532
|
# # => false
|
|
525
533
|
#
|
|
526
|
-
|
|
534
|
+
# We can also pass in the symbol arguments instead of strings.
|
|
535
|
+
#
|
|
536
|
+
def current_page?(options, check_parameters: false)
|
|
527
537
|
unless request
|
|
528
538
|
raise "You cannot use helpers that need to determine the current " \
|
|
529
539
|
"page unless your view context provides a Request object " \
|
|
@@ -532,15 +542,19 @@ module ActionView
|
|
|
532
542
|
|
|
533
543
|
return false unless request.get? || request.head?
|
|
534
544
|
|
|
545
|
+
check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
|
|
535
546
|
url_string = URI.parser.unescape(url_for(options)).force_encoding(Encoding::BINARY)
|
|
536
547
|
|
|
537
548
|
# We ignore any extra parameters in the request_uri if the
|
|
538
549
|
# submitted url doesn't have any either. This lets the function
|
|
539
550
|
# work with things like ?order=asc
|
|
540
|
-
|
|
551
|
+
# the behaviour can be disabled with check_parameters: true
|
|
552
|
+
request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
|
|
541
553
|
request_uri = URI.parser.unescape(request_uri).force_encoding(Encoding::BINARY)
|
|
542
554
|
|
|
543
|
-
if url_string
|
|
555
|
+
url_string.chomp!("/") if url_string.start_with?("/") && url_string != "/"
|
|
556
|
+
|
|
557
|
+
if %r{^\w+://}.match?(url_string)
|
|
544
558
|
url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
|
|
545
559
|
else
|
|
546
560
|
url_string == request_uri
|
|
@@ -551,70 +565,84 @@ module ActionView
|
|
|
551
565
|
def convert_options_to_data_attributes(options, html_options)
|
|
552
566
|
if html_options
|
|
553
567
|
html_options = html_options.stringify_keys
|
|
554
|
-
html_options[
|
|
568
|
+
html_options["data-remote"] = "true".freeze if link_to_remote_options?(options) || link_to_remote_options?(html_options)
|
|
555
569
|
|
|
556
|
-
method
|
|
570
|
+
method = html_options.delete("method".freeze)
|
|
557
571
|
|
|
558
572
|
add_method_to_attributes!(html_options, method) if method
|
|
559
573
|
|
|
560
574
|
html_options
|
|
561
575
|
else
|
|
562
|
-
link_to_remote_options?(options) ? {
|
|
576
|
+
link_to_remote_options?(options) ? { "data-remote" => "true".freeze } : {}
|
|
563
577
|
end
|
|
564
578
|
end
|
|
565
579
|
|
|
566
580
|
def link_to_remote_options?(options)
|
|
567
581
|
if options.is_a?(Hash)
|
|
568
|
-
options.delete(
|
|
582
|
+
options.delete("remote".freeze) || options.delete(:remote)
|
|
569
583
|
end
|
|
570
584
|
end
|
|
571
585
|
|
|
572
586
|
def add_method_to_attributes!(html_options, method)
|
|
573
|
-
if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/
|
|
574
|
-
html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip
|
|
587
|
+
if method && method.to_s.downcase != "get".freeze && html_options["rel".freeze] !~ /nofollow/
|
|
588
|
+
html_options["rel".freeze] = "#{html_options["rel".freeze]} nofollow".lstrip
|
|
575
589
|
end
|
|
576
|
-
html_options["data-method"] = method
|
|
590
|
+
html_options["data-method".freeze] = method
|
|
577
591
|
end
|
|
578
592
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
593
|
+
def token_tag(token = nil, form_options: {})
|
|
594
|
+
if token != false && protect_against_forgery?
|
|
595
|
+
token ||= form_authenticity_token(form_options: form_options)
|
|
596
|
+
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
|
|
597
|
+
else
|
|
598
|
+
"".freeze
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def method_tag(method)
|
|
603
|
+
tag("input", type: "hidden", name: "_method", value: method.to_s)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
# Returns an array of hashes each containing :name and :value keys
|
|
607
|
+
# suitable for use as the names and values of form input fields:
|
|
586
608
|
#
|
|
587
|
-
#
|
|
609
|
+
# to_form_params(name: 'David', nationality: 'Danish')
|
|
610
|
+
# # => [{name: :name, value: 'David'}, {name: 'nationality', value: 'Danish'}]
|
|
588
611
|
#
|
|
589
|
-
#
|
|
590
|
-
#
|
|
591
|
-
# removed from the +html_options+ hash. (See the XHTML 1.0 spec,
|
|
592
|
-
# section 4.5 "Attribute Minimization" for more:
|
|
593
|
-
# http://www.w3.org/TR/xhtml1/#h-4.5)
|
|
612
|
+
# to_form_params(country: {name: 'Denmark'})
|
|
613
|
+
# # => [{name: 'country[name]', value: 'Denmark'}]
|
|
594
614
|
#
|
|
595
|
-
#
|
|
596
|
-
#
|
|
615
|
+
# to_form_params(countries: ['Denmark', 'Sweden']})
|
|
616
|
+
# # => [{name: 'countries[]', value: 'Denmark'}, {name: 'countries[]', value: 'Sweden'}]
|
|
597
617
|
#
|
|
598
|
-
#
|
|
618
|
+
# An optional namespace can be passed to enclose key names:
|
|
599
619
|
#
|
|
600
|
-
#
|
|
601
|
-
#
|
|
602
|
-
def
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
620
|
+
# to_form_params({ name: 'Denmark' }, 'country')
|
|
621
|
+
# # => [{name: 'country[name]', value: 'Denmark'}]
|
|
622
|
+
def to_form_params(attribute, namespace = nil)
|
|
623
|
+
attribute = if attribute.respond_to?(:permitted?)
|
|
624
|
+
attribute.to_h
|
|
625
|
+
else
|
|
626
|
+
attribute
|
|
627
|
+
end
|
|
606
628
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
629
|
+
params = []
|
|
630
|
+
case attribute
|
|
631
|
+
when Hash
|
|
632
|
+
attribute.each do |key, value|
|
|
633
|
+
prefix = namespace ? "#{namespace}[#{key}]" : key
|
|
634
|
+
params.push(*to_form_params(value, prefix))
|
|
635
|
+
end
|
|
636
|
+
when Array
|
|
637
|
+
array_prefix = "#{namespace}[]"
|
|
638
|
+
attribute.each do |value|
|
|
639
|
+
params.push(*to_form_params(value, array_prefix))
|
|
640
|
+
end
|
|
611
641
|
else
|
|
612
|
-
|
|
642
|
+
params << { name: namespace, value: attribute.to_param }
|
|
613
643
|
end
|
|
614
|
-
end
|
|
615
644
|
|
|
616
|
-
|
|
617
|
-
tag('input', type: 'hidden', name: '_method', value: method.to_s)
|
|
645
|
+
params.sort_by { |pair| pair[:name] }
|
|
618
646
|
end
|
|
619
647
|
end
|
|
620
648
|
end
|
data/lib/action_view/helpers.rb
CHANGED
data/lib/action_view/layouts.rb
CHANGED
|
@@ -91,16 +91,16 @@ module ActionView
|
|
|
91
91
|
# layout false
|
|
92
92
|
#
|
|
93
93
|
# In these examples, we have three implicit lookup scenarios:
|
|
94
|
-
# * The BankController uses the "bank" layout.
|
|
95
|
-
# * The ExchangeController uses the "exchange" layout.
|
|
96
|
-
# * The CurrencyController inherits the layout from BankController.
|
|
94
|
+
# * The +BankController+ uses the "bank" layout.
|
|
95
|
+
# * The +ExchangeController+ uses the "exchange" layout.
|
|
96
|
+
# * The +CurrencyController+ inherits the layout from BankController.
|
|
97
97
|
#
|
|
98
98
|
# However, when a layout is explicitly set, the explicitly set layout wins:
|
|
99
|
-
# * The InformationController uses the "information" layout, explicitly set.
|
|
100
|
-
# * The TellerController also uses the "information" layout, because the parent explicitly set it.
|
|
101
|
-
# * The EmployeeController uses the "employee" layout, because it set the layout to nil
|
|
102
|
-
# * The VaultController chooses a layout dynamically by calling the <tt>access_level_layout</tt> method.
|
|
103
|
-
# * The TillController does not use a layout at all.
|
|
99
|
+
# * The +InformationController+ uses the "information" layout, explicitly set.
|
|
100
|
+
# * The +TellerController+ also uses the "information" layout, because the parent explicitly set it.
|
|
101
|
+
# * The +EmployeeController+ uses the "employee" layout, because it set the layout to +nil+, resetting the parent configuration.
|
|
102
|
+
# * The +VaultController+ chooses a layout dynamically by calling the <tt>access_level_layout</tt> method.
|
|
103
|
+
# * The +TillController+ does not use a layout at all.
|
|
104
104
|
#
|
|
105
105
|
# == Types of layouts
|
|
106
106
|
#
|
|
@@ -148,8 +148,8 @@ module ActionView
|
|
|
148
148
|
# The template will be looked always in <tt>app/views/layouts/</tt> folder. But you can point
|
|
149
149
|
# <tt>layouts</tt> folder direct also. <tt>layout "layouts/demo"</tt> is the same as <tt>layout "demo"</tt>.
|
|
150
150
|
#
|
|
151
|
-
# Setting the layout to nil forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists.
|
|
152
|
-
# Setting it to nil is useful to re-enable template lookup overriding a previous configuration set in the parent:
|
|
151
|
+
# Setting the layout to +nil+ forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists.
|
|
152
|
+
# Setting it to +nil+ is useful to re-enable template lookup overriding a previous configuration set in the parent:
|
|
153
153
|
#
|
|
154
154
|
# class ApplicationController < ActionController::Base
|
|
155
155
|
# layout "application"
|
|
@@ -204,7 +204,7 @@ module ActionView
|
|
|
204
204
|
include ActionView::Rendering
|
|
205
205
|
|
|
206
206
|
included do
|
|
207
|
-
class_attribute :_layout, :_layout_conditions, :
|
|
207
|
+
class_attribute :_layout, :_layout_conditions, instance_accessor: false
|
|
208
208
|
self._layout = nil
|
|
209
209
|
self._layout_conditions = {}
|
|
210
210
|
_write_layout_method
|
|
@@ -223,36 +223,39 @@ module ActionView
|
|
|
223
223
|
module LayoutConditions # :nodoc:
|
|
224
224
|
private
|
|
225
225
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
226
|
+
# Determines whether the current action has a layout definition by
|
|
227
|
+
# checking the action name against the :only and :except conditions
|
|
228
|
+
# set by the <tt>layout</tt> method.
|
|
229
|
+
#
|
|
230
|
+
# ==== Returns
|
|
231
|
+
# * <tt>Boolean</tt> - True if the action has a layout definition, false otherwise.
|
|
232
|
+
def _conditional_layout?
|
|
233
|
+
return unless super
|
|
234
|
+
|
|
235
|
+
conditions = _layout_conditions
|
|
236
|
+
|
|
237
|
+
if only = conditions[:only]
|
|
238
|
+
only.include?(action_name)
|
|
239
|
+
elsif except = conditions[:except]
|
|
240
|
+
!except.include?(action_name)
|
|
241
|
+
else
|
|
242
|
+
true
|
|
243
|
+
end
|
|
243
244
|
end
|
|
244
|
-
end
|
|
245
245
|
end
|
|
246
246
|
|
|
247
247
|
# Specify the layout to use for this class.
|
|
248
248
|
#
|
|
249
249
|
# If the specified layout is a:
|
|
250
250
|
# String:: the String is the template name
|
|
251
|
-
# Symbol:: call the method specified by the symbol
|
|
251
|
+
# Symbol:: call the method specified by the symbol
|
|
252
|
+
# Proc:: call the passed Proc
|
|
252
253
|
# false:: There is no layout
|
|
253
254
|
# true:: raise an ArgumentError
|
|
254
255
|
# nil:: Force default layout behavior with inheritance
|
|
255
256
|
#
|
|
257
|
+
# Return value of +Proc+ and +Symbol+ arguments should be +String+, +false+, +true+ or +nil+
|
|
258
|
+
# with the same meaning as described above.
|
|
256
259
|
# ==== Parameters
|
|
257
260
|
# * <tt>layout</tt> - The layout to use.
|
|
258
261
|
#
|
|
@@ -262,7 +265,7 @@ module ActionView
|
|
|
262
265
|
def layout(layout, conditions = {})
|
|
263
266
|
include LayoutConditions unless conditions.empty?
|
|
264
267
|
|
|
265
|
-
conditions.each {|k, v| conditions[k] = Array(v).map
|
|
268
|
+
conditions.each { |k, v| conditions[k] = Array(v).map(&:to_s) }
|
|
266
269
|
self._layout_conditions = conditions
|
|
267
270
|
|
|
268
271
|
self._layout = layout
|
|
@@ -276,8 +279,8 @@ module ActionView
|
|
|
276
279
|
def _write_layout_method # :nodoc:
|
|
277
280
|
remove_possible_method(:_layout)
|
|
278
281
|
|
|
279
|
-
prefixes
|
|
280
|
-
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}).first || super"
|
|
282
|
+
prefixes = /\blayouts/.match?(_implied_layout_name) ? [] : ["layouts"]
|
|
283
|
+
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
|
|
281
284
|
name_clause = if name
|
|
282
285
|
default_behavior
|
|
283
286
|
else
|
|
@@ -286,7 +289,8 @@ module ActionView
|
|
|
286
289
|
RUBY
|
|
287
290
|
end
|
|
288
291
|
|
|
289
|
-
layout_definition =
|
|
292
|
+
layout_definition = \
|
|
293
|
+
case _layout
|
|
290
294
|
when String
|
|
291
295
|
_layout.inspect
|
|
292
296
|
when Symbol
|
|
@@ -313,10 +317,10 @@ module ActionView
|
|
|
313
317
|
raise ArgumentError, "Layouts must be specified as a String, Symbol, Proc, false, or nil"
|
|
314
318
|
when nil
|
|
315
319
|
name_clause
|
|
316
|
-
|
|
320
|
+
end
|
|
317
321
|
|
|
318
|
-
|
|
319
|
-
def _layout
|
|
322
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
323
|
+
def _layout(formats)
|
|
320
324
|
if _conditional_layout?
|
|
321
325
|
#{layout_definition}
|
|
322
326
|
else
|
|
@@ -329,14 +333,14 @@ module ActionView
|
|
|
329
333
|
|
|
330
334
|
private
|
|
331
335
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
336
|
+
# If no layout is supplied, look for a template named the return
|
|
337
|
+
# value of this method.
|
|
338
|
+
#
|
|
339
|
+
# ==== Returns
|
|
340
|
+
# * <tt>String</tt> - A template name
|
|
341
|
+
def _implied_layout_name
|
|
342
|
+
controller_path
|
|
343
|
+
end
|
|
340
344
|
end
|
|
341
345
|
|
|
342
346
|
def _normalize_options(options) # :nodoc:
|
|
@@ -372,7 +376,7 @@ module ActionView
|
|
|
372
376
|
end
|
|
373
377
|
|
|
374
378
|
# This will be overwritten by _write_layout_method
|
|
375
|
-
def _layout; end
|
|
379
|
+
def _layout(*); end
|
|
376
380
|
|
|
377
381
|
# Determine the layout for a given name, taking into account the name type.
|
|
378
382
|
#
|
|
@@ -382,8 +386,8 @@ module ActionView
|
|
|
382
386
|
case name
|
|
383
387
|
when String then _normalize_layout(name)
|
|
384
388
|
when Proc then name
|
|
385
|
-
when true then Proc.new { _default_layout(true) }
|
|
386
|
-
when :default then Proc.new { _default_layout(false) }
|
|
389
|
+
when true then Proc.new { |formats| _default_layout(formats, true) }
|
|
390
|
+
when :default then Proc.new { |formats| _default_layout(formats, false) }
|
|
387
391
|
when false, nil then nil
|
|
388
392
|
else
|
|
389
393
|
raise ArgumentError,
|
|
@@ -399,14 +403,15 @@ module ActionView
|
|
|
399
403
|
# Optionally raises an exception if the layout could not be found.
|
|
400
404
|
#
|
|
401
405
|
# ==== Parameters
|
|
402
|
-
# * <tt>
|
|
403
|
-
#
|
|
406
|
+
# * <tt>formats</tt> - The formats accepted to this layout
|
|
407
|
+
# * <tt>require_layout</tt> - If set to +true+ and layout is not found,
|
|
408
|
+
# an +ArgumentError+ exception is raised (defaults to +false+)
|
|
404
409
|
#
|
|
405
410
|
# ==== Returns
|
|
406
|
-
# * <tt>template</tt> - The template object for the default layout (or nil)
|
|
407
|
-
def _default_layout(require_layout = false)
|
|
411
|
+
# * <tt>template</tt> - The template object for the default layout (or +nil+)
|
|
412
|
+
def _default_layout(formats, require_layout = false)
|
|
408
413
|
begin
|
|
409
|
-
value = _layout if action_has_layout?
|
|
414
|
+
value = _layout(formats) if action_has_layout?
|
|
410
415
|
rescue NameError => e
|
|
411
416
|
raise e, "Could not render layout: #{e.message}"
|
|
412
417
|
end
|
|
@@ -420,7 +425,7 @@ module ActionView
|
|
|
420
425
|
end
|
|
421
426
|
|
|
422
427
|
def _include_layout?(options)
|
|
423
|
-
(options.keys & [:body, :
|
|
428
|
+
(options.keys & [:body, :plain, :html, :inline, :partial]).empty? || options.key?(:layout)
|
|
424
429
|
end
|
|
425
430
|
end
|
|
426
431
|
end
|