activesupport 3.2.22.5 → 4.0.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 activesupport might be problematic. Click here for more details.

Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +325 -136
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -2
  5. data/lib/active_support.rb +8 -21
  6. data/lib/active_support/backtrace_cleaner.rb +33 -25
  7. data/lib/active_support/basic_object.rb +7 -17
  8. data/lib/active_support/benchmarkable.rb +19 -15
  9. data/lib/active_support/buffered_logger.rb +9 -113
  10. data/lib/active_support/cache.rb +203 -171
  11. data/lib/active_support/cache/file_store.rb +12 -12
  12. data/lib/active_support/cache/mem_cache_store.rb +24 -30
  13. data/lib/active_support/cache/memory_store.rb +2 -0
  14. data/lib/active_support/callbacks.rb +195 -247
  15. data/lib/active_support/concern.rb +16 -23
  16. data/lib/active_support/concurrency/latch.rb +27 -0
  17. data/lib/active_support/configurable.rb +69 -12
  18. data/lib/active_support/core_ext.rb +1 -0
  19. data/lib/active_support/core_ext/array.rb +0 -1
  20. data/lib/active_support/core_ext/array/access.rb +17 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +113 -55
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +21 -22
  24. data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
  25. data/lib/active_support/core_ext/array/wrap.rb +11 -14
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +7 -24
  27. data/lib/active_support/core_ext/class/attribute.rb +12 -8
  28. data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
  29. data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
  30. data/lib/active_support/core_ext/class/subclasses.rb +11 -5
  31. data/lib/active_support/core_ext/date.rb +6 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +34 -188
  33. data/lib/active_support/core_ext/date/conversions.rb +16 -38
  34. data/lib/active_support/core_ext/date/infinite_comparable.rb +5 -0
  35. data/lib/active_support/core_ext/date/zones.rb +25 -2
  36. data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
  37. data/lib/active_support/core_ext/date_time.rb +5 -0
  38. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
  39. data/lib/active_support/core_ext/date_time/calculations.rb +73 -65
  40. data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
  41. data/lib/active_support/core_ext/date_time/infinite_comparable.rb +5 -0
  42. data/lib/active_support/core_ext/date_time/zones.rb +11 -8
  43. data/lib/active_support/core_ext/enumerable.rb +26 -73
  44. data/lib/active_support/core_ext/file.rb +0 -1
  45. data/lib/active_support/core_ext/file/atomic.rb +27 -11
  46. data/lib/active_support/core_ext/hash.rb +0 -1
  47. data/lib/active_support/core_ext/hash/conversions.rb +145 -79
  48. data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
  49. data/lib/active_support/core_ext/hash/diff.rb +5 -4
  50. data/lib/active_support/core_ext/hash/except.rb +1 -9
  51. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
  52. data/lib/active_support/core_ext/hash/keys.rb +108 -24
  53. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  54. data/lib/active_support/core_ext/hash/slice.rb +12 -12
  55. data/lib/active_support/core_ext/infinite_comparable.rb +35 -0
  56. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  57. data/lib/active_support/core_ext/integer/time.rb +17 -12
  58. data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
  59. data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
  60. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  61. data/lib/active_support/core_ext/load_error.rb +7 -5
  62. data/lib/active_support/core_ext/logger.rb +7 -23
  63. data/lib/active_support/core_ext/marshal.rb +19 -0
  64. data/lib/active_support/core_ext/module.rb +1 -3
  65. data/lib/active_support/core_ext/module/aliasing.rb +8 -9
  66. data/lib/active_support/core_ext/module/anonymous.rb +2 -7
  67. data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
  68. data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
  69. data/lib/active_support/core_ext/module/delegation.rb +57 -40
  70. data/lib/active_support/core_ext/module/deprecation.rb +19 -3
  71. data/lib/active_support/core_ext/module/introspection.rb +17 -27
  72. data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
  73. data/lib/active_support/core_ext/module/remove_method.rb +1 -5
  74. data/lib/active_support/core_ext/numeric.rb +2 -0
  75. data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
  76. data/lib/active_support/core_ext/numeric/infinite_comparable.rb +9 -0
  77. data/lib/active_support/core_ext/numeric/time.rb +6 -6
  78. data/lib/active_support/core_ext/object.rb +1 -0
  79. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  80. data/lib/active_support/core_ext/object/blank.rb +7 -23
  81. data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
  82. data/lib/active_support/core_ext/object/duplicable.rb +1 -30
  83. data/lib/active_support/core_ext/object/inclusion.rb +6 -6
  84. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  85. data/lib/active_support/core_ext/object/to_json.rb +8 -0
  86. data/lib/active_support/core_ext/object/to_param.rb +5 -2
  87. data/lib/active_support/core_ext/object/try.rb +46 -25
  88. data/lib/active_support/core_ext/object/with_options.rb +7 -8
  89. data/lib/active_support/core_ext/proc.rb +3 -0
  90. data/lib/active_support/core_ext/range.rb +0 -2
  91. data/lib/active_support/core_ext/range/conversions.rb +0 -2
  92. data/lib/active_support/core_ext/range/include_range.rb +1 -1
  93. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  94. data/lib/active_support/core_ext/string.rb +2 -2
  95. data/lib/active_support/core_ext/string/access.rb +95 -90
  96. data/lib/active_support/core_ext/string/conversions.rb +29 -38
  97. data/lib/active_support/core_ext/string/encoding.rb +6 -9
  98. data/lib/active_support/core_ext/string/filters.rb +24 -18
  99. data/lib/active_support/core_ext/string/indent.rb +43 -0
  100. data/lib/active_support/core_ext/string/inflections.rb +70 -60
  101. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  102. data/lib/active_support/core_ext/string/multibyte.rb +41 -64
  103. data/lib/active_support/core_ext/string/output_safety.rb +59 -51
  104. data/lib/active_support/core_ext/string/zones.rb +13 -0
  105. data/lib/active_support/core_ext/struct.rb +6 -0
  106. data/lib/active_support/core_ext/thread.rb +74 -0
  107. data/lib/active_support/core_ext/time.rb +6 -0
  108. data/lib/active_support/core_ext/time/calculations.rb +105 -193
  109. data/lib/active_support/core_ext/time/conversions.rb +27 -51
  110. data/lib/active_support/core_ext/time/infinite_comparable.rb +5 -0
  111. data/lib/active_support/core_ext/time/marshal.rb +0 -27
  112. data/lib/active_support/core_ext/time/zones.rb +27 -17
  113. data/lib/active_support/core_ext/uri.rb +13 -17
  114. data/lib/active_support/dependencies.rb +160 -141
  115. data/lib/active_support/dependencies/autoload.rb +47 -20
  116. data/lib/active_support/deprecation.rb +39 -14
  117. data/lib/active_support/deprecation/behaviors.rb +44 -30
  118. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  119. data/lib/active_support/deprecation/method_wrappers.rb +33 -18
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
  121. data/lib/active_support/deprecation/reporting.rb +40 -11
  122. data/lib/active_support/descendants_tracker.rb +34 -19
  123. data/lib/active_support/duration.rb +6 -8
  124. data/lib/active_support/file_update_checker.rb +63 -47
  125. data/lib/active_support/gzip.rb +11 -5
  126. data/lib/active_support/hash_with_indifferent_access.rb +112 -37
  127. data/lib/active_support/i18n.rb +4 -0
  128. data/lib/active_support/i18n_railtie.rb +5 -22
  129. data/lib/active_support/inflections.rb +14 -12
  130. data/lib/active_support/inflector/inflections.rb +108 -71
  131. data/lib/active_support/inflector/methods.rb +181 -160
  132. data/lib/active_support/inflector/transliterate.rb +16 -17
  133. data/lib/active_support/json/decoding.rb +18 -17
  134. data/lib/active_support/json/encoding.rb +93 -39
  135. data/lib/active_support/json/variable.rb +10 -1
  136. data/lib/active_support/key_generator.rb +75 -0
  137. data/lib/active_support/lazy_load_hooks.rb +21 -19
  138. data/lib/active_support/locale/en.yml +100 -3
  139. data/lib/active_support/log_subscriber.rb +56 -36
  140. data/lib/active_support/log_subscriber/test_helper.rb +18 -15
  141. data/lib/active_support/logger.rb +57 -0
  142. data/lib/active_support/logger_silence.rb +24 -0
  143. data/lib/active_support/message_encryptor.rb +32 -29
  144. data/lib/active_support/message_verifier.rb +8 -14
  145. data/lib/active_support/multibyte.rb +5 -28
  146. data/lib/active_support/multibyte/chars.rb +80 -333
  147. data/lib/active_support/multibyte/unicode.rb +74 -64
  148. data/lib/active_support/notifications.rb +57 -25
  149. data/lib/active_support/notifications/fanout.rb +105 -18
  150. data/lib/active_support/notifications/instrumenter.rb +32 -13
  151. data/lib/active_support/number_helper.rb +636 -0
  152. data/lib/active_support/ordered_hash.rb +8 -190
  153. data/lib/active_support/ordered_options.rb +21 -23
  154. data/lib/active_support/proxy_object.rb +13 -0
  155. data/lib/active_support/rails.rb +27 -0
  156. data/lib/active_support/railtie.rb +12 -32
  157. data/lib/active_support/rescuable.rb +9 -4
  158. data/lib/active_support/string_inquirer.rb +13 -8
  159. data/lib/active_support/tagged_logging.rb +51 -73
  160. data/lib/active_support/test_case.rb +46 -17
  161. data/lib/active_support/testing/assertions.rb +56 -26
  162. data/lib/active_support/testing/autorun.rb +5 -0
  163. data/lib/active_support/testing/constant_lookup.rb +52 -0
  164. data/lib/active_support/testing/declarative.rb +1 -1
  165. data/lib/active_support/testing/deprecation.rb +0 -19
  166. data/lib/active_support/testing/isolation.rb +25 -58
  167. data/lib/active_support/testing/pending.rb +5 -43
  168. data/lib/active_support/testing/setup_and_teardown.rb +6 -92
  169. data/lib/active_support/testing/tagged_logging.rb +25 -0
  170. data/lib/active_support/time.rb +6 -21
  171. data/lib/active_support/time_with_zone.rb +78 -43
  172. data/lib/active_support/values/time_zone.rb +77 -58
  173. data/lib/active_support/values/unicode_tables.dat +0 -0
  174. data/lib/active_support/version.rb +4 -4
  175. data/lib/active_support/xml_mini.rb +35 -17
  176. data/lib/active_support/xml_mini/jdom.rb +9 -17
  177. data/lib/active_support/xml_mini/libxml.rb +1 -2
  178. data/lib/active_support/xml_mini/libxmlsax.rb +1 -2
  179. data/lib/active_support/xml_mini/nokogiri.rb +1 -2
  180. data/lib/active_support/xml_mini/nokogirisax.rb +1 -2
  181. data/lib/active_support/xml_mini/rexml.rb +6 -8
  182. metadata +107 -77
  183. data/lib/active_support/base64.rb +0 -54
  184. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  185. data/lib/active_support/core_ext/date/freeze.rb +0 -33
  186. data/lib/active_support/core_ext/exception.rb +0 -3
  187. data/lib/active_support/core_ext/file/path.rb +0 -5
  188. data/lib/active_support/core_ext/float.rb +0 -1
  189. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  190. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
  191. data/lib/active_support/core_ext/io.rb +0 -15
  192. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  193. data/lib/active_support/core_ext/module/synchronization.rb +0 -45
  194. data/lib/active_support/core_ext/process.rb +0 -1
  195. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  196. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  197. data/lib/active_support/core_ext/range/cover.rb +0 -3
  198. data/lib/active_support/core_ext/rexml.rb +0 -46
  199. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  200. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  201. data/lib/active_support/memoizable.rb +0 -116
  202. data/lib/active_support/multibyte/exceptions.rb +0 -8
  203. data/lib/active_support/multibyte/utils.rb +0 -60
  204. data/lib/active_support/ruby/shim.rb +0 -22
  205. data/lib/active_support/security_utils.rb +0 -27
  206. data/lib/active_support/testing/mochaing.rb +0 -7
  207. data/lib/active_support/testing/performance.rb +0 -317
  208. data/lib/active_support/testing/performance/jruby.rb +0 -115
  209. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  210. data/lib/active_support/testing/performance/ruby.rb +0 -152
  211. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  212. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  213. data/lib/active_support/time/autoload.rb +0 -5
  214. data/lib/active_support/whiny_nil.rb +0 -24
@@ -8,7 +8,7 @@ module ActiveSupport
8
8
  # Replaces non-ASCII characters with an ASCII approximation, or if none
9
9
  # exists, a replacement character which defaults to "?".
10
10
  #
11
- # transliterate("Ærøskøbing")
11
+ # transliterate('Ærøskøbing')
12
12
  # # => "AEroskobing"
13
13
  #
14
14
  # Default approximations are provided for Western/Latin characters,
@@ -30,33 +30,33 @@ module ActiveSupport
30
30
  # ö: "oe"
31
31
  #
32
32
  # # Or set them using Ruby
33
- # I18n.backend.store_translations(:de, :i18n => {
34
- # :transliterate => {
35
- # :rule => {
36
- # "ü" => "ue",
37
- # "ö" => "oe"
33
+ # I18n.backend.store_translations(:de, i18n: {
34
+ # transliterate: {
35
+ # rule: {
36
+ # 'ü' => 'ue',
37
+ # 'ö' => 'oe'
38
38
  # }
39
39
  # }
40
40
  # })
41
41
  #
42
- # The value for <tt>i18n.transliterate.rule</tt> can be a simple Hash that maps
43
- # characters to ASCII approximations as shown above, or, for more complex
44
- # requirements, a Proc:
42
+ # The value for <tt>i18n.transliterate.rule</tt> can be a simple Hash that
43
+ # maps characters to ASCII approximations as shown above, or, for more
44
+ # complex requirements, a Proc:
45
45
  #
46
- # I18n.backend.store_translations(:de, :i18n => {
47
- # :transliterate => {
48
- # :rule => lambda {|string| MyTransliterator.transliterate(string)}
46
+ # I18n.backend.store_translations(:de, i18n: {
47
+ # transliterate: {
48
+ # rule: ->(string) { MyTransliterator.transliterate(string) }
49
49
  # }
50
50
  # })
51
51
  #
52
52
  # Now you can have different transliterations for each locale:
53
53
  #
54
54
  # I18n.locale = :en
55
- # transliterate("Jürgen")
55
+ # transliterate('Jürgen')
56
56
  # # => "Jurgen"
57
57
  #
58
58
  # I18n.locale = :de
59
- # transliterate("Jürgen")
59
+ # transliterate('Jürgen')
60
60
  # # => "Juergen"
61
61
  def transliterate(string, replacement = "?")
62
62
  I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
@@ -64,9 +64,8 @@ module ActiveSupport
64
64
  :replacement => replacement)
65
65
  end
66
66
 
67
- # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
68
- #
69
- # ==== Examples
67
+ # Replaces special characters in a string so that it may be used as part of
68
+ # a 'pretty' URL.
70
69
  #
71
70
  # class Person
72
71
  # def to_param
@@ -8,14 +8,13 @@ module ActiveSupport
8
8
 
9
9
  module JSON
10
10
  class << self
11
+ # Parses a JSON string (JavaScript Object Notation) into a hash.
12
+ # See www.json.org for more info.
13
+ #
14
+ # ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
15
+ # => {"team" => "rails", "players" => "36"}
11
16
  def decode(json, options ={})
12
- # Can't reliably detect whether MultiJson responds to load, since it's
13
- # a reserved word. Use adapter as a proxy for new features.
14
- data = if MultiJson.respond_to?(:adapter)
15
- MultiJson.load(json, options)
16
- else
17
- MultiJson.decode(json, options)
18
- end
17
+ data = MultiJson.load(json, options)
19
18
  if ActiveSupport.parse_json_times
20
19
  convert_dates_from(data)
21
20
  else
@@ -24,20 +23,12 @@ module ActiveSupport
24
23
  end
25
24
 
26
25
  def engine
27
- if MultiJson.respond_to?(:adapter)
28
- MultiJson.adapter
29
- else
30
- MultiJson.engine
31
- end
26
+ MultiJson.adapter
32
27
  end
33
28
  alias :backend :engine
34
29
 
35
30
  def engine=(name)
36
- if MultiJson.respond_to?(:use)
37
- MultiJson.use name
38
- else
39
- MultiJson.engine = name
40
- end
31
+ MultiJson.use(name)
41
32
  end
42
33
  alias :backend= :engine=
43
34
 
@@ -48,6 +39,16 @@ module ActiveSupport
48
39
  self.backend = old_backend
49
40
  end
50
41
 
42
+ # Returns the class of the error that will be raised when there is an
43
+ # error in decoding JSON. Using this method means you won't directly
44
+ # depend on the ActiveSupport's JSON implementation, in case it changes
45
+ # in the future.
46
+ #
47
+ # begin
48
+ # obj = ActiveSupport::JSON.decode(some_string)
49
+ # rescue ActiveSupport::JSON.parse_error
50
+ # Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
51
+ # end
51
52
  def parse_error
52
53
  MultiJson::DecodeError
53
54
  end
@@ -1,11 +1,9 @@
1
1
  require 'active_support/core_ext/object/to_json'
2
2
  require 'active_support/core_ext/module/delegation'
3
3
  require 'active_support/json/variable'
4
- require 'active_support/ordered_hash'
5
4
 
6
5
  require 'bigdecimal'
7
6
  require 'active_support/core_ext/big_decimal/conversions' # for #to_s
8
- require 'active_support/core_ext/array/wrap'
9
7
  require 'active_support/core_ext/hash/except'
10
8
  require 'active_support/core_ext/hash/slice'
11
9
  require 'active_support/core_ext/object/instance_variables'
@@ -19,6 +17,7 @@ module ActiveSupport
19
17
  class << self
20
18
  delegate :use_standard_json_time_format, :use_standard_json_time_format=,
21
19
  :escape_html_entities_in_json, :escape_html_entities_in_json=,
20
+ :encode_big_decimal_as_string, :encode_big_decimal_as_string=,
22
21
  :to => :'ActiveSupport::JSON::Encoding'
23
22
  end
24
23
 
@@ -26,7 +25,11 @@ module ActiveSupport
26
25
  # matches YAML-formatted dates
27
26
  DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
28
27
 
29
- # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
28
+ # Dumps objects in JSON (JavaScript Object Notation).
29
+ # See www.json.org for more info.
30
+ #
31
+ # ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
32
+ # # => "{\"team\":\"rails\",\"players\":\"36\"}"
30
33
  def self.encode(value, options = nil)
31
34
  Encoding::Encoder.new(options).encode(value)
32
35
  end
@@ -49,7 +52,7 @@ module ActiveSupport
49
52
  end
50
53
  end
51
54
 
52
- # like encode, but only calls as_json, without encoding to string
55
+ # like encode, but only calls as_json, without encoding to string.
53
56
  def as_json(value, use_options = true)
54
57
  check_for_circular_references(value) do
55
58
  use_options ? value.as_json(options_for(value)) : value.as_json
@@ -58,7 +61,8 @@ module ActiveSupport
58
61
 
59
62
  def options_for(value)
60
63
  if value.is_a?(Array) || value.is_a?(Hash)
61
- # hashes and arrays need to get encoder in the options, so that they can detect circular references
64
+ # hashes and arrays need to get encoder in the options, so that
65
+ # they can detect circular references.
62
66
  options.merge(:encoder => self)
63
67
  else
64
68
  options.dup
@@ -103,9 +107,14 @@ module ActiveSupport
103
107
  '&' => '\u0026' }
104
108
 
105
109
  class << self
106
- # If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format.
110
+ # If true, use ISO 8601 format for dates and times. Otherwise, fall back
111
+ # to the Active Support legacy format.
107
112
  attr_accessor :use_standard_json_time_format
108
113
 
114
+ # If false, serializes BigDecimal objects as numeric instead of wrapping
115
+ # them in a string.
116
+ attr_accessor :encode_big_decimal_as_string
117
+
109
118
  attr_accessor :escape_regex
110
119
  attr_reader :escape_html_entities_in_json
111
120
 
@@ -119,24 +128,17 @@ module ActiveSupport
119
128
  end
120
129
 
121
130
  def escape(string)
122
- if string.respond_to?(:force_encoding)
123
- string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
124
- end
125
- json = string.
126
- gsub(escape_regex) { |s| ESCAPED_CHARS[s] }.
127
- gsub(/([\xC0-\xDF][\x80-\xBF]|
128
- [\xE0-\xEF][\x80-\xBF]{2}|
129
- [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
130
- s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
131
- }
131
+ string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
132
+ json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
132
133
  json = %("#{json}")
133
- json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
134
+ json.force_encoding(::Encoding::UTF_8)
134
135
  json
135
136
  end
136
137
  end
137
138
 
138
139
  self.use_standard_json_time_format = true
139
- self.escape_html_entities_in_json = false
140
+ self.escape_html_entities_in_json = true
141
+ self.encode_big_decimal_as_string = true
140
142
  end
141
143
  end
142
144
  end
@@ -158,32 +160,67 @@ class Struct #:nodoc:
158
160
  end
159
161
 
160
162
  class TrueClass
161
- def as_json(options = nil) self end #:nodoc:
162
- def encode_json(encoder) to_s end #:nodoc:
163
+ def as_json(options = nil) #:nodoc:
164
+ self
165
+ end
166
+
167
+ def encode_json(encoder) #:nodoc:
168
+ to_s
169
+ end
163
170
  end
164
171
 
165
172
  class FalseClass
166
- def as_json(options = nil) self end #:nodoc:
167
- def encode_json(encoder) to_s end #:nodoc:
173
+ def as_json(options = nil) #:nodoc:
174
+ self
175
+ end
176
+
177
+ def encode_json(encoder) #:nodoc:
178
+ to_s
179
+ end
168
180
  end
169
181
 
170
182
  class NilClass
171
- def as_json(options = nil) self end #:nodoc:
172
- def encode_json(encoder) 'null' end #:nodoc:
183
+ def as_json(options = nil) #:nodoc:
184
+ self
185
+ end
186
+
187
+ def encode_json(encoder) #:nodoc:
188
+ 'null'
189
+ end
173
190
  end
174
191
 
175
192
  class String
176
- def as_json(options = nil) self end #:nodoc:
177
- def encode_json(encoder) encoder.escape(self) end #:nodoc:
193
+ def as_json(options = nil) #:nodoc:
194
+ self
195
+ end
196
+
197
+ def encode_json(encoder) #:nodoc:
198
+ encoder.escape(self)
199
+ end
178
200
  end
179
201
 
180
202
  class Symbol
181
- def as_json(options = nil) to_s end #:nodoc:
203
+ def as_json(options = nil) #:nodoc:
204
+ to_s
205
+ end
182
206
  end
183
207
 
184
208
  class Numeric
185
- def as_json(options = nil) self end #:nodoc:
186
- def encode_json(encoder) to_s end #:nodoc:
209
+ def as_json(options = nil) #:nodoc:
210
+ self
211
+ end
212
+
213
+ def encode_json(encoder) #:nodoc:
214
+ to_s
215
+ end
216
+ end
217
+
218
+ class Float
219
+ # Encoding Infinity or NaN to JSON should return "null". The default returns
220
+ # "Infinity" or "NaN" which breaks parsing the JSON. E.g. JSON.parse('[NaN]').
221
+ def as_json(options = nil) #:nodoc:
222
+ finite? ? self : nil
223
+ end
187
224
  end
188
225
 
189
226
  class BigDecimal
@@ -192,14 +229,26 @@ class BigDecimal
192
229
  # those libraries would get in general a wrong number and no way to recover
193
230
  # other than manually inspecting the string with the JSON code itself.
194
231
  #
195
- # That's why a JSON string is returned. The JSON literal is not numeric, but if
196
- # the other end knows by contract that the data is supposed to be a BigDecimal,
197
- # it still has the chance to post-process the string and get the real value.
198
- def as_json(options = nil) to_s end #:nodoc:
232
+ # That's why a JSON string is returned. The JSON literal is not numeric, but
233
+ # if the other end knows by contract that the data is supposed to be a
234
+ # BigDecimal, it still has the chance to post-process the string and get the
235
+ # real value.
236
+ #
237
+ # Use <tt>ActiveSupport.use_standard_json_big_decimal_format = true</tt> to
238
+ # override this behavior.
239
+ def as_json(options = nil) #:nodoc:
240
+ if finite?
241
+ ActiveSupport.encode_big_decimal_as_string ? to_s : self
242
+ else
243
+ nil
244
+ end
245
+ end
199
246
  end
200
247
 
201
248
  class Regexp
202
- def as_json(options = nil) to_s end #:nodoc:
249
+ def as_json(options = nil) #:nodoc:
250
+ to_s
251
+ end
203
252
  end
204
253
 
205
254
  module Enumerable
@@ -208,6 +257,12 @@ module Enumerable
208
257
  end
209
258
  end
210
259
 
260
+ class Range
261
+ def as_json(options = nil) #:nodoc:
262
+ to_s
263
+ end
264
+ end
265
+
211
266
  class Array
212
267
  def as_json(options = nil) #:nodoc:
213
268
  # use encoder as a proxy to call as_json on all elements, to protect from circular references
@@ -226,9 +281,9 @@ class Hash
226
281
  # create a subset of the hash by applying :only or :except
227
282
  subset = if options
228
283
  if attrs = options[:only]
229
- slice(*Array.wrap(attrs))
284
+ slice(*Array(attrs))
230
285
  elsif attrs = options[:except]
231
- except(*Array.wrap(attrs))
286
+ except(*Array(attrs))
232
287
  else
233
288
  self
234
289
  end
@@ -238,11 +293,10 @@ class Hash
238
293
 
239
294
  # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
240
295
  encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
241
- result = self.is_a?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash : Hash
242
- result[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
296
+ Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
243
297
  end
244
298
 
245
- def encode_json(encoder)
299
+ def encode_json(encoder) #:nodoc:
246
300
  # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be
247
301
  # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields);
248
302
 
@@ -1,7 +1,16 @@
1
+ require 'active_support/deprecation'
2
+
1
3
  module ActiveSupport
2
4
  module JSON
3
- # A string that returns itself as its JSON-encoded form.
5
+ # Deprecated: A string that returns itself as its JSON-encoded form.
4
6
  class Variable < String
7
+ def initialize(*args)
8
+ message = 'ActiveSupport::JSON::Variable is deprecated and will be removed in Rails 4.1. ' \
9
+ 'For your own custom JSON literals, define #as_json and #encode_json yourself.'
10
+ ActiveSupport::Deprecation.warn message
11
+ super
12
+ end
13
+
5
14
  def as_json(options = nil) self end #:nodoc:
6
15
  def encode_json(encoder) self end #:nodoc:
7
16
  end
@@ -0,0 +1,75 @@
1
+ require 'thread_safe'
2
+ require 'openssl'
3
+
4
+ module ActiveSupport
5
+ # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
6
+ # It can be used to derive a number of keys for various purposes from a given secret.
7
+ # This lets rails applications have a single secure secret, but avoid reusing that
8
+ # key in multiple incompatible contexts.
9
+ class KeyGenerator
10
+ def initialize(secret, options = {})
11
+ @secret = secret
12
+ # The default iterations are higher than required for our key derivation uses
13
+ # on the off chance someone uses this for password storage
14
+ @iterations = options[:iterations] || 2**16
15
+ end
16
+
17
+ # Returns a derived key suitable for use. The default key_size is chosen
18
+ # to be compatible with the default settings of ActiveSupport::MessageVerifier.
19
+ # i.e. OpenSSL::Digest::SHA1#block_length
20
+ def generate_key(salt, key_size=64)
21
+ OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
22
+ end
23
+ end
24
+
25
+ # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
26
+ # re-executing the key generation process when it's called using the same salt and
27
+ # key_size
28
+ class CachingKeyGenerator
29
+ def initialize(key_generator)
30
+ @key_generator = key_generator
31
+ @cache_keys = ThreadSafe::Cache.new
32
+ end
33
+
34
+ # Returns a derived key suitable for use. The default key_size is chosen
35
+ # to be compatible with the default settings of ActiveSupport::MessageVerifier.
36
+ # i.e. OpenSSL::Digest::SHA1#block_length
37
+ def generate_key(salt, key_size=64)
38
+ @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
39
+ end
40
+ end
41
+
42
+ class DummyKeyGenerator # :nodoc:
43
+ SECRET_MIN_LENGTH = 30 # Characters
44
+
45
+ def initialize(secret)
46
+ ensure_secret_secure(secret)
47
+ @secret = secret
48
+ end
49
+
50
+ def generate_key(salt)
51
+ @secret
52
+ end
53
+
54
+ private
55
+
56
+ # To prevent users from using something insecure like "Password" we make sure that the
57
+ # secret they've provided is at least 30 characters in length.
58
+ def ensure_secret_secure(secret)
59
+ if secret.blank?
60
+ raise ArgumentError, "A secret is required to generate an " +
61
+ "integrity hash for cookie session data. Use " +
62
+ "config.secret_key_base = \"some secret phrase of at " +
63
+ "least #{SECRET_MIN_LENGTH} characters\"" +
64
+ "in config/initializers/secret_token.rb"
65
+ end
66
+
67
+ if secret.length < SECRET_MIN_LENGTH
68
+ raise ArgumentError, "Secret should be something secure, " +
69
+ "like \"#{SecureRandom.hex(16)}\". The value you " +
70
+ "provided, \"#{secret}\", is shorter than the minimum length " +
71
+ "of #{SECRET_MIN_LENGTH} characters"
72
+ end
73
+ end
74
+ end
75
+ end