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
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_support/core_ext/big_decimal/conversions'
|
2
2
|
require 'active_support/core_ext/float/rounding'
|
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 Number Helpers
|
@@ -47,36 +48,33 @@ module ActionView
|
|
47
48
|
# number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".")
|
48
49
|
# => +1.123.555.1234 x 1343
|
49
50
|
def number_to_phone(number, options = {})
|
50
|
-
return
|
51
|
+
return unless number
|
51
52
|
|
52
53
|
begin
|
53
54
|
Float(number)
|
54
|
-
is_number_html_safe = true
|
55
55
|
rescue ArgumentError, TypeError
|
56
|
-
|
57
|
-
|
58
|
-
else
|
59
|
-
is_number_html_safe = number.to_s.html_safe?
|
60
|
-
end
|
61
|
-
end
|
56
|
+
raise InvalidNumberError, number
|
57
|
+
end if options[:raise]
|
62
58
|
|
63
59
|
number = number.to_s.strip
|
64
60
|
options = options.symbolize_keys
|
65
|
-
area_code = options[:area_code]
|
61
|
+
area_code = options[:area_code]
|
66
62
|
delimiter = options[:delimiter] || "-"
|
67
|
-
extension = options[:extension]
|
68
|
-
country_code = options[:country_code]
|
63
|
+
extension = options[:extension]
|
64
|
+
country_code = options[:country_code]
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
str << if area_code
|
73
|
-
number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{delimiter}\\3")
|
66
|
+
if area_code
|
67
|
+
number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
|
74
68
|
else
|
75
|
-
number.gsub!(/(
|
76
|
-
number.
|
69
|
+
number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
|
70
|
+
number.slice!(0, 1) if number.starts_with?('-')
|
77
71
|
end
|
72
|
+
|
73
|
+
str = []
|
74
|
+
str << "+#{country_code}#{delimiter}" unless country_code.blank?
|
75
|
+
str << number
|
78
76
|
str << " x #{extension}" unless extension.blank?
|
79
|
-
|
77
|
+
ERB::Util.html_escape(str.join)
|
80
78
|
end
|
81
79
|
|
82
80
|
# Formats a +number+ into a currency string (e.g., $13.65). You can customize the format
|
@@ -102,14 +100,14 @@ module ActionView
|
|
102
100
|
# number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
|
103
101
|
# number_to_currency(1234567890.506, :locale => :fr) # => 1 234 567 890,506 €
|
104
102
|
#
|
105
|
-
# number_to_currency(1234567890.50, :negative_format => "(%u%n)")
|
103
|
+
# number_to_currency(-1234567890.50, :negative_format => "(%u%n)")
|
106
104
|
# # => ($1,234,567,890.51)
|
107
105
|
# number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "")
|
108
106
|
# # => £1234567890,50
|
109
107
|
# number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
|
110
108
|
# # => 1234567890,50 £
|
111
109
|
def number_to_currency(number, options = {})
|
112
|
-
return
|
110
|
+
return unless number
|
113
111
|
|
114
112
|
options.symbolize_keys!
|
115
113
|
|
@@ -160,7 +158,7 @@ module ActionView
|
|
160
158
|
# number_to_percentage(302.24398923423, :precision => 5) # => 302.24399%
|
161
159
|
# number_to_percentage(1000, :locale => :fr) # => 1 000,000%
|
162
160
|
def number_to_percentage(number, options = {})
|
163
|
-
return
|
161
|
+
return unless number
|
164
162
|
|
165
163
|
options.symbolize_keys!
|
166
164
|
|
@@ -213,7 +211,7 @@ module ActionView
|
|
213
211
|
defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
|
214
212
|
options = options.reverse_merge(defaults)
|
215
213
|
|
216
|
-
parts = number.to_s.
|
214
|
+
parts = number.to_s.split('.')
|
217
215
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
218
216
|
parts.join(options[:separator]).html_safe
|
219
217
|
|
@@ -240,7 +238,7 @@ module ActionView
|
|
240
238
|
# number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
|
241
239
|
# number_with_precision(13, :precision => 5, :significant => true) # => 13.000
|
242
240
|
# number_with_precision(111.234, :locale => :fr) # => 111,234
|
243
|
-
# number_with_precision(13, :precision => 5, :significant => true, strip_insignificant_zeros => true)
|
241
|
+
# number_with_precision(13, :precision => 5, :significant => true, :strip_insignificant_zeros => true)
|
244
242
|
# # => 13
|
245
243
|
# number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
|
246
244
|
# number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
|
@@ -275,7 +273,7 @@ module ActionView
|
|
275
273
|
rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
|
276
274
|
digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
|
277
275
|
end
|
278
|
-
precision
|
276
|
+
precision -= digits
|
279
277
|
precision = precision > 0 ? precision : 0 #don't let it be negative
|
280
278
|
else
|
281
279
|
rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
|
@@ -306,6 +304,7 @@ module ActionView
|
|
306
304
|
# * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
|
307
305
|
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
308
306
|
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
|
307
|
+
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI prefix (defaults to :binary)
|
309
308
|
# ==== Examples
|
310
309
|
# number_to_human_size(123) # => 123 Bytes
|
311
310
|
# number_to_human_size(1234) # => 1.21 KB
|
@@ -320,7 +319,7 @@ module ActionView
|
|
320
319
|
# Non-significant zeros after the fractional separator are stripped out by default (set
|
321
320
|
# <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
|
322
321
|
# number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
|
323
|
-
# number_to_human_size(524288000, :precision=>5)
|
322
|
+
# number_to_human_size(524288000, :precision => 5) # => "500 MB"
|
324
323
|
def number_to_human_size(number, options = {})
|
325
324
|
options.symbolize_keys!
|
326
325
|
|
@@ -343,15 +342,17 @@ module ActionView
|
|
343
342
|
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
344
343
|
|
345
344
|
storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
|
345
|
+
|
346
|
+
base = options[:prefix] == :si ? 1000 : 1024
|
346
347
|
|
347
|
-
if number.to_i <
|
348
|
+
if number.to_i < base
|
348
349
|
unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
|
349
350
|
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit).html_safe
|
350
351
|
else
|
351
352
|
max_exp = STORAGE_UNITS.size - 1
|
352
|
-
exponent = (Math.log(number) / Math.log(
|
353
|
+
exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base
|
353
354
|
exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
|
354
|
-
number /=
|
355
|
+
number /= base ** exponent
|
355
356
|
|
356
357
|
unit_key = STORAGE_UNITS[exponent]
|
357
358
|
unit = I18n.translate(:"number.human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
|
@@ -371,7 +372,7 @@ module ActionView
|
|
371
372
|
# See <tt>number_to_human_size</tt> if you want to print a file size.
|
372
373
|
#
|
373
374
|
# You can also define you own unit-quantifier names if you want to use other decimal units
|
374
|
-
# (eg.: 1500 becomes "1.5 kilometers", 0.150 becomes "150
|
375
|
+
# (eg.: 1500 becomes "1.5 kilometers", 0.150 becomes "150 milliliters", etc). You may define
|
375
376
|
# a wide range of unit quantifiers, even fractional ones (centi, deci, mili, etc).
|
376
377
|
#
|
377
378
|
# ==== Options
|
@@ -409,7 +410,7 @@ module ActionView
|
|
409
410
|
# Unsignificant zeros after the decimal separator are stripped out by default (set
|
410
411
|
# <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
|
411
412
|
# number_to_human(12345012345, :significant_digits => 6) # => "12.345 Billion"
|
412
|
-
# number_to_human(500000000, :precision=>5)
|
413
|
+
# number_to_human(500000000, :precision => 5) # => "500 Million"
|
413
414
|
#
|
414
415
|
# ==== Custom Unit Quantifiers
|
415
416
|
#
|
@@ -427,13 +428,13 @@ module ActionView
|
|
427
428
|
# thousand:
|
428
429
|
# one: "kilometer"
|
429
430
|
# other: "kilometers"
|
430
|
-
# billion: "
|
431
|
+
# billion: "gazillion-distance"
|
431
432
|
#
|
432
433
|
# Then you could do:
|
433
434
|
#
|
434
435
|
# number_to_human(543934, :units => :distance) # => "544 kilometers"
|
435
436
|
# number_to_human(54393498, :units => :distance) # => "54400 kilometers"
|
436
|
-
# number_to_human(54393498000, :units => :distance) # => "54.4
|
437
|
+
# number_to_human(54393498000, :units => :distance) # => "54.4 gazillion-distance"
|
437
438
|
# number_to_human(343, :units => :distance, :precision => 1) # => "300 meters"
|
438
439
|
# number_to_human(1, :units => :distance) # => "1 meter"
|
439
440
|
# number_to_human(0.34, :units => :distance) # => "34 centimeters"
|
@@ -459,6 +460,8 @@ module ActionView
|
|
459
460
|
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
460
461
|
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
461
462
|
|
463
|
+
inverted_du = DECIMAL_UNITS.invert
|
464
|
+
|
462
465
|
units = options.delete :units
|
463
466
|
unit_exponents = case units
|
464
467
|
when Hash
|
@@ -469,7 +472,7 @@ module ActionView
|
|
469
472
|
I18n.translate(:"number.human.decimal_units.units", :locale => options[:locale], :raise => true)
|
470
473
|
else
|
471
474
|
raise ArgumentError, ":units must be a Hash or String translation scope."
|
472
|
-
end.keys.map{|e_name|
|
475
|
+
end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e}
|
473
476
|
|
474
477
|
number_exponent = number != 0 ? Math.log10(number.abs).floor : 0
|
475
478
|
display_exponent = unit_exponents.find{ |e| number_exponent >= e } || 0
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support/core_ext/string/output_safety'
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
# = Action View Raw Output Helper
|
5
|
+
module Helpers #:nodoc:
|
6
|
+
module OutputSafetyHelper
|
7
|
+
# This method outputs without escaping a string. Since escaping tags is
|
8
|
+
# now default, this can be used when you don't want Rails to automatically
|
9
|
+
# escape tags. This is not recommended if the data is coming from the user's
|
10
|
+
# input.
|
11
|
+
#
|
12
|
+
# For example:
|
13
|
+
#
|
14
|
+
# <%=raw @user.name %>
|
15
|
+
def raw(stringish)
|
16
|
+
stringish.to_s.html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
# This method returns a html safe string similar to what <tt>Array#join</tt>
|
20
|
+
# would return. All items in the array, including the supplied separator, are
|
21
|
+
# html escaped unless they are html safe, and the returned string is marked
|
22
|
+
# as html safe.
|
23
|
+
#
|
24
|
+
# safe_join(["<p>foo</p>".html_safe, "<p>bar</p>"], "<br />")
|
25
|
+
# # => "<p>foo</p><br /><p>bar</p>"
|
26
|
+
#
|
27
|
+
# safe_join(["<p>foo</p>".html_safe, "<p>bar</p>".html_safe], "<br />".html_safe)
|
28
|
+
# # => "<p>foo</p><br /><p>bar</p>"
|
29
|
+
#
|
30
|
+
def safe_join(array, sep=$,)
|
31
|
+
sep ||= "".html_safe
|
32
|
+
sep = ERB::Util.html_escape(sep)
|
33
|
+
|
34
|
+
array.map { |i| ERB::Util.html_escape(i) }.join(sep).html_safe
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -10,7 +10,7 @@ module ActionView
|
|
10
10
|
# relate to the specified Active Record object. Usage example:
|
11
11
|
#
|
12
12
|
# <%= div_for(@person, :class => "foo") do %>
|
13
|
-
# <%=
|
13
|
+
# <%= @person.name %>
|
14
14
|
# <% end %>
|
15
15
|
#
|
16
16
|
# produces:
|
@@ -25,8 +25,8 @@ module ActionView
|
|
25
25
|
# that relate to the specified Active Record object. For example:
|
26
26
|
#
|
27
27
|
# <%= content_tag_for(:tr, @person) do %>
|
28
|
-
# <td><%=
|
29
|
-
# <td><%=
|
28
|
+
# <td><%= @person.first_name %></td>
|
29
|
+
# <td><%= @person.last_name %></td>
|
30
30
|
# <% end %>
|
31
31
|
#
|
32
32
|
# would produce the following HTML (assuming @person is an instance of
|
@@ -52,9 +52,9 @@ module ActionView
|
|
52
52
|
#
|
53
53
|
# <li id="person_123" class="person bar">...
|
54
54
|
#
|
55
|
-
def content_tag_for(tag_name, record,
|
56
|
-
prefix
|
57
|
-
options
|
55
|
+
def content_tag_for(tag_name, record, prefix = nil, options = nil, &block)
|
56
|
+
options, prefix = prefix, nil if prefix.is_a?(Hash)
|
57
|
+
options ||= {}
|
58
58
|
options.merge!({ :class => "#{dom_class(record, prefix)} #{options[:class]}".strip, :id => dom_id(record, prefix) })
|
59
59
|
content_tag(tag_name, options, &block)
|
60
60
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
# = Action View Rendering
|
4
|
+
#
|
5
|
+
# Implements methods that allow rendering from a view context.
|
6
|
+
# In order to use this module, all you need is to implement
|
7
|
+
# view_renderer that returns an ActionView::Renderer object.
|
8
|
+
module RenderingHelper
|
9
|
+
# Returns the result of a render that's dictated by the options hash. The primary options are:
|
10
|
+
#
|
11
|
+
# * <tt>:partial</tt> - See ActionView::Partials.
|
12
|
+
# * <tt>:file</tt> - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
|
13
|
+
# * <tt>:inline</tt> - Renders an inline template similar to how it's done in the controller.
|
14
|
+
# * <tt>:text</tt> - Renders the text passed in out.
|
15
|
+
#
|
16
|
+
# If no options hash is passed or :update specified, the default is to render a partial and use the second parameter
|
17
|
+
# as the locals hash.
|
18
|
+
def render(options = {}, locals = {}, &block)
|
19
|
+
case options
|
20
|
+
when Hash
|
21
|
+
if block_given?
|
22
|
+
view_renderer.render_partial(self, options.merge(:partial => options[:layout]), &block)
|
23
|
+
else
|
24
|
+
view_renderer.render(self, options)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
view_renderer.render_partial(self, :partial => options, :locals => locals)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Overwrites _layout_for in the context object so it supports the case a block is
|
32
|
+
# passed to a partial. Returns the contents that are yielded to a layout, given a
|
33
|
+
# name or a block.
|
34
|
+
#
|
35
|
+
# You can think of a layout as a method that is called with a block. If the user calls
|
36
|
+
# <tt>yield :some_name</tt>, the block, by default, returns <tt>content_for(:some_name)</tt>.
|
37
|
+
# If the user calls simply +yield+, the default block returns <tt>content_for(:layout)</tt>.
|
38
|
+
#
|
39
|
+
# The user can override this default by passing a block to the layout:
|
40
|
+
#
|
41
|
+
# # The template
|
42
|
+
# <%= render :layout => "my_layout" do %>
|
43
|
+
# Content
|
44
|
+
# <% end %>
|
45
|
+
#
|
46
|
+
# # The layout
|
47
|
+
# <html>
|
48
|
+
# <%= yield %>
|
49
|
+
# </html>
|
50
|
+
#
|
51
|
+
# In this case, instead of the default block, which would return <tt>content_for(:layout)</tt>,
|
52
|
+
# this method returns the block that was passed in to <tt>render :layout</tt>, and the response
|
53
|
+
# would be
|
54
|
+
#
|
55
|
+
# <html>
|
56
|
+
# Content
|
57
|
+
# </html>
|
58
|
+
#
|
59
|
+
# Finally, the block can take block arguments, which can be passed in by +yield+:
|
60
|
+
#
|
61
|
+
# # The template
|
62
|
+
# <%= render :layout => "my_layout" do |customer| %>
|
63
|
+
# Hello <%= customer.name %>
|
64
|
+
# <% end %>
|
65
|
+
#
|
66
|
+
# # The layout
|
67
|
+
# <html>
|
68
|
+
# <%= yield Struct.new(:name).new("David") %>
|
69
|
+
# </html>
|
70
|
+
#
|
71
|
+
# In this case, the layout would receive the block passed into <tt>render :layout</tt>,
|
72
|
+
# and the struct specified would be passed into the block as an argument. The result
|
73
|
+
# would be
|
74
|
+
#
|
75
|
+
# <html>
|
76
|
+
# Hello David
|
77
|
+
# </html>
|
78
|
+
#
|
79
|
+
def _layout_for(*args, &block)
|
80
|
+
name = args.first
|
81
|
+
|
82
|
+
if block && !name.is_a?(Symbol)
|
83
|
+
capture(*args, &block)
|
84
|
+
else
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -81,7 +81,7 @@ module ActionView
|
|
81
81
|
# strip_tags("<div id='top-bar'>Welcome to my website!</div>")
|
82
82
|
# # => Welcome to my website!
|
83
83
|
def strip_tags(html)
|
84
|
-
self.class.full_sanitizer.sanitize(html)
|
84
|
+
self.class.full_sanitizer.sanitize(html).try(:html_safe)
|
85
85
|
end
|
86
86
|
|
87
87
|
# Strips all link tags from +text+ leaving just the link text.
|
@@ -94,7 +94,7 @@ module ActionView
|
|
94
94
|
# # => Please e-mail me at me@email.com.
|
95
95
|
#
|
96
96
|
# strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
|
97
|
-
# # => Blog: Visit
|
97
|
+
# # => Blog: Visit.
|
98
98
|
def strip_links(html)
|
99
99
|
self.class.link_sanitizer.sanitize(html)
|
100
100
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'action_view/helpers/asset_paths'
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
module Helpers
|
6
|
+
module SprocketsHelper
|
7
|
+
def asset_path(source, default_ext = nil)
|
8
|
+
sprockets_asset_paths.compute_public_path(source, 'assets', default_ext, true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def sprockets_javascript_include_tag(source, options = {})
|
12
|
+
options = {
|
13
|
+
'type' => "text/javascript",
|
14
|
+
'src' => asset_path(source, 'js')
|
15
|
+
}.merge(options.stringify_keys)
|
16
|
+
|
17
|
+
content_tag 'script', "", options
|
18
|
+
end
|
19
|
+
|
20
|
+
def sprockets_stylesheet_link_tag(source, options = {})
|
21
|
+
options = {
|
22
|
+
'rel' => "stylesheet",
|
23
|
+
'type' => "text/css",
|
24
|
+
'media' => "screen",
|
25
|
+
'href' => asset_path(source, 'css')
|
26
|
+
}.merge(options.stringify_keys)
|
27
|
+
|
28
|
+
tag 'link', options
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def sprockets_asset_paths
|
34
|
+
@sprockets_asset_paths ||= begin
|
35
|
+
config = self.config if respond_to?(:config)
|
36
|
+
controller = self.controller if respond_to?(:controller)
|
37
|
+
SprocketsHelper::AssetPaths.new(config, controller)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
|
42
|
+
def rewrite_asset_path(source, dir)
|
43
|
+
if source[0] == ?/
|
44
|
+
source
|
45
|
+
else
|
46
|
+
assets.path(source, performing_caching?, dir)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def rewrite_extension(source, dir, ext)
|
51
|
+
if ext && File.extname(source).empty?
|
52
|
+
"#{source}.#{ext}"
|
53
|
+
else
|
54
|
+
source
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def assets
|
59
|
+
Rails.application.assets
|
60
|
+
end
|
61
|
+
|
62
|
+
# When included in Sprockets::Context, we need to ask the top-level config as the controller is not available
|
63
|
+
def performing_caching?
|
64
|
+
@config ? @config.perform_caching : Rails.application.config.action_controller.perform_caching
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_support/core_ext/string/output_safety'
|
2
3
|
require 'set'
|
3
4
|
|
4
5
|
module ActionView
|
@@ -7,16 +8,14 @@ module ActionView
|
|
7
8
|
# Provides methods to generate HTML tags programmatically when you can't use
|
8
9
|
# a Builder. By default, they output XHTML compliant tags.
|
9
10
|
module TagHelper
|
10
|
-
include ERB::Util
|
11
|
-
|
12
11
|
extend ActiveSupport::Concern
|
13
12
|
include CaptureHelper
|
14
13
|
|
15
14
|
BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer
|
16
15
|
autoplay controls loop selected hidden scoped async
|
17
16
|
defer reversed ismap seemless muted required
|
18
|
-
autofocus novalidate formnovalidate open).to_set
|
19
|
-
BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|
|
17
|
+
autofocus novalidate formnovalidate open pubdate).to_set
|
18
|
+
BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attribute| attribute.to_sym })
|
20
19
|
|
21
20
|
# Returns an empty HTML tag of type +name+ which by default is XHTML
|
22
21
|
# compliant. Set +open+ to true to create an open tag compatible
|
@@ -25,9 +24,21 @@ module ActionView
|
|
25
24
|
# escaping.
|
26
25
|
#
|
27
26
|
# ==== Options
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
27
|
+
# You can use symbols or strings for the attribute names.
|
28
|
+
#
|
29
|
+
# Use +true+ with boolean attributes that can render with no value, like
|
30
|
+
# +disabled+ and +readonly+.
|
31
|
+
#
|
32
|
+
# HTML5 <tt>data-*</tt> attributes can be set with a single +data+ key
|
33
|
+
# pointing to a hash of sub-attributes.
|
34
|
+
#
|
35
|
+
# To play nicely with JavaScript conventions sub-attributes are dasherized.
|
36
|
+
# For example, a key +user_id+ would render as <tt>data-user-id</tt> and
|
37
|
+
# thus accessed as <tt>dataset.userId</tt>.
|
38
|
+
#
|
39
|
+
# Values are encoded to JSON, with the exception of strings and symbols.
|
40
|
+
# This may come in handy when using jQuery's HTML5-aware <tt>.data()<tt>
|
41
|
+
# from 1.4.3.
|
31
42
|
#
|
32
43
|
# ==== Examples
|
33
44
|
# tag("br")
|
@@ -36,14 +47,17 @@ module ActionView
|
|
36
47
|
# tag("br", nil, true)
|
37
48
|
# # => <br>
|
38
49
|
#
|
39
|
-
# tag("input",
|
50
|
+
# tag("input", :type => 'text', :disabled => true)
|
40
51
|
# # => <input type="text" disabled="disabled" />
|
41
52
|
#
|
42
|
-
# tag("img",
|
53
|
+
# tag("img", :src => "open & shut.png")
|
43
54
|
# # => <img src="open & shut.png" />
|
44
55
|
#
|
45
|
-
# tag("img", {
|
56
|
+
# tag("img", {:src => "open & shut.png"}, false, false)
|
46
57
|
# # => <img src="open & shut.png" />
|
58
|
+
#
|
59
|
+
# tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
|
60
|
+
# # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
|
47
61
|
def tag(name, options = nil, open = false, escape = true)
|
48
62
|
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
|
49
63
|
end
|
@@ -118,11 +132,19 @@ module ActionView
|
|
118
132
|
unless options.blank?
|
119
133
|
attrs = []
|
120
134
|
options.each_pair do |key, value|
|
121
|
-
if
|
135
|
+
if key.to_s == 'data' && value.is_a?(Hash)
|
136
|
+
value.each do |k, v|
|
137
|
+
if !v.is_a?(String) && !v.is_a?(Symbol)
|
138
|
+
v = v.to_json
|
139
|
+
end
|
140
|
+
v = ERB::Util.html_escape(v) if escape
|
141
|
+
attrs << %(data-#{k.to_s.dasherize}="#{v}")
|
142
|
+
end
|
143
|
+
elsif BOOLEAN_ATTRIBUTES.include?(key)
|
122
144
|
attrs << %(#{key}="#{key}") if value
|
123
145
|
elsif !value.nil?
|
124
146
|
final_value = value.is_a?(Array) ? value.join(" ") : value
|
125
|
-
final_value = html_escape(final_value) if escape
|
147
|
+
final_value = ERB::Util.html_escape(final_value) if escape
|
126
148
|
attrs << %(#{key}="#{final_value}")
|
127
149
|
end
|
128
150
|
end
|