actionpack 3.0.20 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (161) hide show
  1. data/CHANGELOG +88 -142
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +5 -6
  4. data/lib/abstract_controller.rb +1 -0
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +24 -19
  7. data/lib/abstract_controller/callbacks.rb +19 -19
  8. data/lib/abstract_controller/helpers.rb +11 -13
  9. data/lib/abstract_controller/layouts.rb +4 -5
  10. data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
  11. data/lib/abstract_controller/rendering.rb +34 -31
  12. data/lib/abstract_controller/url_for.rb +27 -0
  13. data/lib/abstract_controller/view_paths.rb +31 -6
  14. data/lib/action_controller.rb +5 -3
  15. data/lib/action_controller/base.rb +15 -16
  16. data/lib/action_controller/caching.rb +2 -2
  17. data/lib/action_controller/caching/actions.rb +11 -12
  18. data/lib/action_controller/caching/fragments.rb +41 -19
  19. data/lib/action_controller/caching/pages.rb +3 -9
  20. data/lib/action_controller/caching/sweeping.rb +0 -1
  21. data/lib/action_controller/deprecated.rb +1 -1
  22. data/lib/action_controller/log_subscriber.rb +1 -1
  23. data/lib/action_controller/metal.rb +78 -20
  24. data/lib/action_controller/metal/compatibility.rb +0 -9
  25. data/lib/action_controller/metal/conditional_get.rb +9 -9
  26. data/lib/action_controller/metal/data_streaming.rb +145 -0
  27. data/lib/action_controller/metal/force_ssl.rb +35 -0
  28. data/lib/action_controller/metal/head.rb +1 -1
  29. data/lib/action_controller/metal/helpers.rb +37 -44
  30. data/lib/action_controller/metal/hide_actions.rb +2 -3
  31. data/lib/action_controller/metal/http_authentication.rb +41 -38
  32. data/lib/action_controller/metal/implicit_render.rb +13 -13
  33. data/lib/action_controller/metal/instrumentation.rb +2 -2
  34. data/lib/action_controller/metal/mime_responds.rb +25 -19
  35. data/lib/action_controller/metal/params_wrapper.rb +224 -0
  36. data/lib/action_controller/metal/redirecting.rb +6 -2
  37. data/lib/action_controller/metal/renderers.rb +50 -36
  38. data/lib/action_controller/metal/rendering.rb +34 -25
  39. data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
  40. data/lib/action_controller/metal/responder.rb +47 -12
  41. data/lib/action_controller/metal/streaming.rb +244 -138
  42. data/lib/action_controller/metal/testing.rb +0 -9
  43. data/lib/action_controller/metal/url_for.rb +12 -14
  44. data/lib/action_controller/railtie.rb +19 -37
  45. data/lib/action_controller/railties/paths.rb +24 -0
  46. data/lib/action_controller/record_identifier.rb +4 -10
  47. data/lib/action_controller/test_case.rb +36 -19
  48. data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
  49. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
  50. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
  51. data/lib/action_dispatch.rb +4 -1
  52. data/lib/action_dispatch/http/cache.rb +5 -32
  53. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  54. data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
  55. data/lib/action_dispatch/http/mime_type.rb +45 -5
  56. data/lib/action_dispatch/http/rack_cache.rb +58 -0
  57. data/lib/action_dispatch/http/request.rb +27 -41
  58. data/lib/action_dispatch/http/response.rb +56 -54
  59. data/lib/action_dispatch/http/upload.rb +1 -11
  60. data/lib/action_dispatch/http/url.rb +102 -42
  61. data/lib/action_dispatch/middleware/callbacks.rb +8 -25
  62. data/lib/action_dispatch/middleware/closed_error.rb +7 -0
  63. data/lib/action_dispatch/middleware/cookies.rb +37 -15
  64. data/lib/action_dispatch/middleware/flash.rb +80 -11
  65. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  66. data/lib/action_dispatch/middleware/reloader.rb +76 -0
  67. data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
  68. data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
  69. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
  70. data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
  71. data/lib/action_dispatch/middleware/stack.rb +50 -17
  72. data/lib/action_dispatch/middleware/static.rb +41 -29
  73. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
  74. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  75. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
  76. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
  77. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
  78. data/lib/action_dispatch/railtie.rb +8 -0
  79. data/lib/action_dispatch/routing.rb +13 -1
  80. data/lib/action_dispatch/routing/mapper.rb +345 -227
  81. data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
  82. data/lib/action_dispatch/routing/redirection.rb +110 -0
  83. data/lib/action_dispatch/routing/route.rb +15 -13
  84. data/lib/action_dispatch/routing/route_set.rb +116 -90
  85. data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
  86. data/lib/action_dispatch/routing/url_for.rb +25 -1
  87. data/lib/action_dispatch/testing/assertions/response.rb +8 -10
  88. data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
  89. data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
  90. data/lib/action_dispatch/testing/integration.rb +37 -28
  91. data/lib/action_dispatch/testing/performance_test.rb +1 -3
  92. data/lib/action_dispatch/testing/test_process.rb +1 -1
  93. data/lib/action_dispatch/testing/test_request.rb +9 -3
  94. data/lib/action_dispatch/testing/test_response.rb +4 -111
  95. data/lib/action_pack.rb +1 -1
  96. data/lib/action_pack/version.rb +3 -3
  97. data/lib/action_view.rb +39 -24
  98. data/lib/action_view/base.rb +61 -86
  99. data/lib/action_view/buffers.rb +43 -0
  100. data/lib/action_view/context.rb +21 -24
  101. data/lib/action_view/flows.rb +79 -0
  102. data/lib/action_view/helpers.rb +8 -6
  103. data/lib/action_view/helpers/active_model_helper.rb +0 -23
  104. data/lib/action_view/helpers/asset_paths.rb +79 -0
  105. data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
  106. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
  107. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
  108. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
  109. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
  110. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  111. data/lib/action_view/helpers/cache_helper.rb +11 -19
  112. data/lib/action_view/helpers/capture_helper.rb +19 -8
  113. data/lib/action_view/helpers/controller_helper.rb +21 -0
  114. data/lib/action_view/helpers/csrf_helper.rb +22 -4
  115. data/lib/action_view/helpers/date_helper.rb +36 -22
  116. data/lib/action_view/helpers/form_helper.rb +199 -113
  117. data/lib/action_view/helpers/form_options_helper.rb +10 -11
  118. data/lib/action_view/helpers/form_tag_helper.rb +94 -22
  119. data/lib/action_view/helpers/javascript_helper.rb +24 -107
  120. data/lib/action_view/helpers/number_helper.rb +36 -33
  121. data/lib/action_view/helpers/output_safety_helper.rb +38 -0
  122. data/lib/action_view/helpers/record_tag_helper.rb +6 -6
  123. data/lib/action_view/helpers/rendering_helper.rb +90 -0
  124. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  125. data/lib/action_view/helpers/sprockets_helper.rb +69 -0
  126. data/lib/action_view/helpers/tag_helper.rb +34 -12
  127. data/lib/action_view/helpers/text_helper.rb +30 -145
  128. data/lib/action_view/helpers/translation_helper.rb +10 -17
  129. data/lib/action_view/helpers/url_helper.rb +70 -67
  130. data/lib/action_view/locale/en.yml +1 -1
  131. data/lib/action_view/lookup_context.rb +36 -14
  132. data/lib/action_view/{paths.rb → path_set.rb} +9 -8
  133. data/lib/action_view/railtie.rb +12 -4
  134. data/lib/action_view/renderer/abstract_renderer.rb +36 -0
  135. data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
  136. data/lib/action_view/renderer/renderer.rb +54 -0
  137. data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
  138. data/lib/action_view/renderer/template_renderer.rb +74 -0
  139. data/lib/action_view/template.rb +91 -54
  140. data/lib/action_view/template/error.rb +11 -8
  141. data/lib/action_view/template/handler.rb +9 -1
  142. data/lib/action_view/template/handlers.rb +9 -9
  143. data/lib/action_view/template/handlers/builder.rb +4 -4
  144. data/lib/action_view/template/handlers/erb.rb +21 -41
  145. data/lib/action_view/template/resolver.rb +171 -57
  146. data/lib/action_view/template/text.rb +0 -4
  147. data/lib/action_view/test_case.rb +32 -16
  148. data/lib/action_view/testing/resolvers.rb +16 -10
  149. data/lib/sprockets/railtie.rb +100 -0
  150. metadata +162 -140
  151. checksums.yaml +0 -7
  152. data/lib/action_controller/deprecated/base.rb +0 -143
  153. data/lib/action_controller/deprecated/dispatcher.rb +0 -28
  154. data/lib/action_controller/deprecated/url_writer.rb +0 -14
  155. data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
  156. data/lib/action_view/helpers/prototype_helper.rb +0 -851
  157. data/lib/action_view/helpers/raw_output_helper.rb +0 -18
  158. data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
  159. data/lib/action_view/render/layouts.rb +0 -83
  160. data/lib/action_view/render/rendering.rb +0 -67
  161. data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -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 nil if number.nil?
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
- if options[:raise]
57
- raise InvalidNumberError, number
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] || nil
61
+ area_code = options[:area_code]
66
62
  delimiter = options[:delimiter] || "-"
67
- extension = options[:extension].to_s.strip || nil
68
- country_code = options[:country_code] || nil
63
+ extension = options[:extension]
64
+ country_code = options[:country_code]
69
65
 
70
- str = ""
71
- str << "+#{country_code}#{delimiter}" unless country_code.blank?
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!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
76
- number.starts_with?('-') ? number.slice!(1..-1) : 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
- is_number_html_safe ? str.html_safe : str
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 => "&pound;", :separator => ",", :delimiter => "")
108
106
  # # => &pound;1234567890,50
109
107
  # number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "", :format => "%n %u")
110
108
  # # => 1234567890,50 &pound;
111
109
  def number_to_currency(number, options = {})
112
- return nil if number.nil?
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 nil if number.nil?
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.to_str.split('.')
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 = precision - digits
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) # => "500 MB"
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 < 1024
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(1024)).to_i # Convert to base 1024
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 /= 1024 ** exponent
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 mililiters", etc). You may define
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) # => "500 Million"
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: "gazilion-distance"
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 gazilion-distance"
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| DECIMAL_UNITS.invert[e_name] }.sort_by{|e| -e}
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>&lt;br /&gt;&lt;p&gt;bar&lt;/p&gt;"
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
- # <%=h @person.name %>
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><%=h @person.first_name %></td>
29
- # <td><%=h @person.last_name %></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, *args, &block)
56
- prefix = args.first.is_a?(Hash) ? nil : args.shift
57
- options = args.extract_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 {|attr| attr.to_sym })
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
- # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
29
- # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
30
- # symbols or strings for the attribute names.
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", { :type => 'text', :disabled => true })
50
+ # tag("input", :type => 'text', :disabled => true)
40
51
  # # => <input type="text" disabled="disabled" />
41
52
  #
42
- # tag("img", { :src => "open & shut.png" })
53
+ # tag("img", :src => "open & shut.png")
43
54
  # # => <img src="open &amp; shut.png" />
44
55
  #
45
- # tag("img", { :src => "open &amp; shut.png" }, false, false)
56
+ # tag("img", {:src => "open &amp; shut.png"}, false, false)
46
57
  # # => <img src="open &amp; shut.png" />
58
+ #
59
+ # tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
60
+ # # => <div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />
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 BOOLEAN_ATTRIBUTES.include?(key)
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