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

Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +283 -508
  3. data/README.rdoc +1 -1
  4. data/lib/active_support.rb +7 -1
  5. data/lib/active_support/backtrace_cleaner.rb +5 -5
  6. data/lib/active_support/benchmarkable.rb +0 -10
  7. data/lib/active_support/cache.rb +62 -26
  8. data/lib/active_support/cache/file_store.rb +27 -22
  9. data/lib/active_support/cache/mem_cache_store.rb +2 -2
  10. data/lib/active_support/cache/memory_store.rb +1 -0
  11. data/lib/active_support/cache/strategy/local_cache.rb +3 -0
  12. data/lib/active_support/callbacks.rb +416 -245
  13. data/lib/active_support/concern.rb +13 -5
  14. data/lib/active_support/core_ext.rb +0 -1
  15. data/lib/active_support/core_ext/array.rb +0 -1
  16. data/lib/active_support/core_ext/array/access.rb +2 -0
  17. data/lib/active_support/core_ext/array/conversions.rb +2 -17
  18. data/lib/active_support/core_ext/array/grouping.rb +24 -12
  19. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
  20. data/lib/active_support/core_ext/class.rb +0 -1
  21. data/lib/active_support/core_ext/class/attribute.rb +1 -2
  22. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  23. data/lib/active_support/core_ext/date/calculations.rb +10 -0
  24. data/lib/active_support/core_ext/date/conversions.rb +5 -6
  25. data/lib/active_support/core_ext/date/zones.rb +2 -33
  26. data/lib/active_support/core_ext/date_and_time/calculations.rb +30 -11
  27. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  28. data/lib/active_support/core_ext/date_time/calculations.rb +12 -25
  29. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  30. data/lib/active_support/core_ext/date_time/zones.rb +3 -21
  31. data/lib/active_support/core_ext/hash.rb +0 -1
  32. data/lib/active_support/core_ext/hash/conversions.rb +6 -3
  33. data/lib/active_support/core_ext/hash/deep_merge.rb +11 -22
  34. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
  35. data/lib/active_support/core_ext/hash/keys.rb +27 -47
  36. data/lib/active_support/core_ext/kernel/reporting.rb +2 -6
  37. data/lib/active_support/core_ext/module.rb +1 -0
  38. data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
  39. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  40. data/lib/active_support/core_ext/module/delegation.rb +14 -4
  41. data/lib/active_support/core_ext/module/deprecation.rb +0 -2
  42. data/lib/active_support/core_ext/module/introspection.rb +0 -16
  43. data/lib/active_support/core_ext/module/method_transplanting.rb +11 -0
  44. data/lib/active_support/core_ext/numeric/time.rb +8 -0
  45. data/lib/active_support/core_ext/object.rb +1 -1
  46. data/lib/active_support/core_ext/object/blank.rb +1 -1
  47. data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
  48. data/lib/active_support/core_ext/object/inclusion.rb +4 -15
  49. data/lib/active_support/core_ext/object/json.rb +197 -0
  50. data/lib/active_support/core_ext/object/to_json.rb +4 -26
  51. data/lib/active_support/core_ext/object/to_param.rb +58 -1
  52. data/lib/active_support/core_ext/object/to_query.rb +7 -56
  53. data/lib/active_support/core_ext/object/try.rb +1 -1
  54. data/lib/active_support/core_ext/range/each.rb +2 -1
  55. data/lib/active_support/core_ext/string/access.rb +31 -31
  56. data/lib/active_support/core_ext/string/conversions.rb +9 -8
  57. data/lib/active_support/core_ext/string/exclude.rb +3 -3
  58. data/lib/active_support/core_ext/string/filters.rb +14 -4
  59. data/lib/active_support/core_ext/string/inflections.rb +11 -9
  60. data/lib/active_support/core_ext/string/output_safety.rb +65 -24
  61. data/lib/active_support/core_ext/string/zones.rb +1 -0
  62. data/lib/active_support/core_ext/thread.rb +4 -4
  63. data/lib/active_support/core_ext/time/calculations.rb +10 -57
  64. data/lib/active_support/core_ext/time/conversions.rb +3 -1
  65. data/lib/active_support/core_ext/time/zones.rb +2 -21
  66. data/lib/active_support/dependencies.rb +29 -13
  67. data/lib/active_support/deprecation.rb +4 -4
  68. data/lib/active_support/deprecation/behaviors.rb +3 -3
  69. data/lib/active_support/duration.rb +5 -7
  70. data/lib/active_support/file_update_checker.rb +1 -1
  71. data/lib/active_support/hash_with_indifferent_access.rb +4 -9
  72. data/lib/active_support/i18n.rb +4 -4
  73. data/lib/active_support/i18n_railtie.rb +2 -6
  74. data/lib/active_support/inflections.rb +0 -1
  75. data/lib/active_support/inflector/inflections.rb +17 -17
  76. data/lib/active_support/inflector/methods.rb +34 -17
  77. data/lib/active_support/json/decoding.rb +14 -21
  78. data/lib/active_support/json/encoding.rb +113 -285
  79. data/lib/active_support/key_generator.rb +1 -1
  80. data/lib/active_support/lazy_load_hooks.rb +1 -1
  81. data/lib/active_support/log_subscriber/test_helper.rb +1 -1
  82. data/lib/active_support/logger.rb +1 -1
  83. data/lib/active_support/message_encryptor.rb +3 -3
  84. data/lib/active_support/message_verifier.rb +6 -1
  85. data/lib/active_support/multibyte/chars.rb +1 -2
  86. data/lib/active_support/multibyte/unicode.rb +27 -39
  87. data/lib/active_support/notifications.rb +3 -3
  88. data/lib/active_support/notifications/instrumenter.rb +2 -1
  89. data/lib/active_support/number_helper.rb +20 -311
  90. data/lib/active_support/number_helper/number_converter.rb +182 -0
  91. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  92. data/lib/active_support/number_helper/number_to_delimited_converter.rb +21 -0
  93. data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
  94. data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
  95. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  96. data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
  97. data/lib/active_support/number_helper/number_to_rounded_converter.rb +62 -0
  98. data/lib/active_support/option_merger.rb +1 -1
  99. data/lib/active_support/ordered_hash.rb +0 -8
  100. data/lib/active_support/ordered_options.rb +8 -0
  101. data/lib/active_support/per_thread_registry.rb +9 -8
  102. data/lib/active_support/subscriber.rb +26 -3
  103. data/lib/active_support/test_case.rb +9 -10
  104. data/lib/active_support/testing/assertions.rb +0 -30
  105. data/lib/active_support/testing/autorun.rb +2 -2
  106. data/lib/active_support/testing/declarative.rb +18 -8
  107. data/lib/active_support/testing/isolation.rb +13 -65
  108. data/lib/active_support/testing/setup_and_teardown.rb +17 -2
  109. data/lib/active_support/testing/tagged_logging.rb +1 -1
  110. data/lib/active_support/testing/time_helpers.rb +55 -0
  111. data/lib/active_support/time_with_zone.rb +4 -4
  112. data/lib/active_support/values/time_zone.rb +18 -15
  113. data/lib/active_support/version.rb +1 -1
  114. data/lib/active_support/xml_mini.rb +2 -4
  115. metadata +71 -61
  116. data/lib/active_support/basic_object.rb +0 -11
  117. data/lib/active_support/buffered_logger.rb +0 -21
  118. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  119. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  120. data/lib/active_support/core_ext/logger.rb +0 -67
  121. data/lib/active_support/core_ext/proc.rb +0 -17
  122. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  123. data/lib/active_support/json/variable.rb +0 -18
  124. data/lib/active_support/testing/pending.rb +0 -14
@@ -1,20 +1,30 @@
1
1
  require 'active_support/core_ext/module/attribute_accessors'
2
2
  require 'active_support/core_ext/module/delegation'
3
- require 'multi_json'
3
+ require 'json'
4
4
 
5
5
  module ActiveSupport
6
6
  # Look for and parse json strings that look like ISO 8601 times.
7
7
  mattr_accessor :parse_json_times
8
8
 
9
9
  module JSON
10
+ # matches YAML-formatted dates
11
+ 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})?))$/
12
+
10
13
  class << self
11
14
  # Parses a JSON string (JavaScript Object Notation) into a hash.
12
15
  # See www.json.org for more info.
13
16
  #
14
17
  # ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
15
18
  # => {"team" => "rails", "players" => "36"}
16
- def decode(json, options ={})
17
- data = MultiJson.load(json, options)
19
+ def decode(json, options = {})
20
+ if options.present?
21
+ raise ArgumentError, "In Rails 4.1, ActiveSupport::JSON.decode no longer " \
22
+ "accepts an options hash for MultiJSON. MultiJSON reached its end of life " \
23
+ "and has been removed."
24
+ end
25
+
26
+ data = ::JSON.parse(json, quirks_mode: true)
27
+
18
28
  if ActiveSupport.parse_json_times
19
29
  convert_dates_from(data)
20
30
  else
@@ -22,23 +32,6 @@ module ActiveSupport
22
32
  end
23
33
  end
24
34
 
25
- def engine
26
- MultiJson.adapter
27
- end
28
- alias :backend :engine
29
-
30
- def engine=(name)
31
- MultiJson.use(name)
32
- end
33
- alias :backend= :engine=
34
-
35
- def with_backend(name)
36
- old_backend, self.backend = backend, name
37
- yield
38
- ensure
39
- self.backend = old_backend
40
- end
41
-
42
35
  # Returns the class of the error that will be raised when there is an
43
36
  # error in decoding JSON. Using this method means you won't directly
44
37
  # depend on the ActiveSupport's JSON implementation, in case it changes
@@ -50,7 +43,7 @@ module ActiveSupport
50
43
  # Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
51
44
  # end
52
45
  def parse_error
53
- MultiJson::DecodeError
46
+ ::JSON::ParserError
54
47
  end
55
48
 
56
49
  private
@@ -1,338 +1,166 @@
1
- require 'active_support/core_ext/object/to_json'
1
+ require 'active_support/core_ext/object/json'
2
2
  require 'active_support/core_ext/module/delegation'
3
- require 'active_support/json/variable'
4
-
5
- require 'bigdecimal'
6
- require 'active_support/core_ext/big_decimal/conversions' # for #to_s
7
- require 'active_support/core_ext/hash/except'
8
- require 'active_support/core_ext/hash/slice'
9
- require 'active_support/core_ext/object/instance_variables'
10
- require 'time'
11
- require 'active_support/core_ext/time/conversions'
12
- require 'active_support/core_ext/date_time/conversions'
13
- require 'active_support/core_ext/date/conversions'
14
- require 'set'
15
3
 
16
4
  module ActiveSupport
17
5
  class << self
18
6
  delegate :use_standard_json_time_format, :use_standard_json_time_format=,
19
7
  :escape_html_entities_in_json, :escape_html_entities_in_json=,
20
8
  :encode_big_decimal_as_string, :encode_big_decimal_as_string=,
9
+ :json_encoder, :json_encoder=,
21
10
  :to => :'ActiveSupport::JSON::Encoding'
22
11
  end
23
12
 
24
13
  module JSON
25
- # matches YAML-formatted dates
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})?))$/
27
-
28
14
  # Dumps objects in JSON (JavaScript Object Notation).
29
15
  # See www.json.org for more info.
30
16
  #
31
17
  # ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
32
18
  # # => "{\"team\":\"rails\",\"players\":\"36\"}"
33
19
  def self.encode(value, options = nil)
34
- Encoding::Encoder.new(options).encode(value)
20
+ Encoding.json_encoder.new(options).encode(value)
35
21
  end
36
22
 
37
23
  module Encoding #:nodoc:
38
- class CircularReferenceError < StandardError; end
39
-
40
- class Encoder
24
+ class JSONGemEncoder #:nodoc:
41
25
  attr_reader :options
42
26
 
43
27
  def initialize(options = nil)
44
28
  @options = options || {}
45
- @seen = Set.new
46
29
  end
47
30
 
48
- def encode(value, use_options = true)
49
- check_for_circular_references(value) do
50
- jsonified = use_options ? value.as_json(options_for(value)) : value.as_json
51
- jsonified.encode_json(self)
52
- end
31
+ # Encode the given object into a JSON string
32
+ def encode(value)
33
+ stringify jsonify value.as_json(options.dup)
53
34
  end
54
35
 
55
- # like encode, but only calls as_json, without encoding to string.
56
- def as_json(value, use_options = true)
57
- check_for_circular_references(value) do
58
- use_options ? value.as_json(options_for(value)) : value.as_json
36
+ private
37
+ # Rails does more escaping than the JSON gem natively does (we
38
+ # escape \u2028 and \u2029 and optionally >, <, & to work around
39
+ # certain browser problems).
40
+ ESCAPED_CHARS = {
41
+ "\u2028" => '\u2028',
42
+ "\u2029" => '\u2029',
43
+ '>' => '\u003e',
44
+ '<' => '\u003c',
45
+ '&' => '\u0026',
46
+ }
47
+
48
+ ESCAPE_REGEX_WITH_HTML_ENTITIES = /[\u2028\u2029><&]/u
49
+ ESCAPE_REGEX_WITHOUT_HTML_ENTITIES = /[\u2028\u2029]/u
50
+
51
+ # This class wraps all the strings we see and does the extra escaping
52
+ class EscapedString < String #:nodoc:
53
+ def to_json(*)
54
+ if Encoding.escape_html_entities_in_json
55
+ super.gsub ESCAPE_REGEX_WITH_HTML_ENTITIES, ESCAPED_CHARS
56
+ else
57
+ super.gsub ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
58
+ end
59
+ end
59
60
  end
60
- end
61
61
 
62
- def options_for(value)
63
- if value.is_a?(Array) || value.is_a?(Hash)
64
- # hashes and arrays need to get encoder in the options, so that
65
- # they can detect circular references.
66
- options.merge(:encoder => self)
67
- else
68
- options.dup
62
+ # Mark these as private so we don't leak encoding-specific constructs
63
+ private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
64
+ :ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
65
+
66
+ # Convert an object into a "JSON-ready" representation composed of
67
+ # primitives like Hash, Array, String, Numeric, and true/false/nil.
68
+ # Recursively calls #as_json to the object to recursively build a
69
+ # fully JSON-ready object.
70
+ #
71
+ # This allows developers to implement #as_json without having to
72
+ # worry about what base types of objects they are allowed to return
73
+ # or having to remember to call #as_json recursively.
74
+ #
75
+ # Note: the +options+ hash passed to +object.to_json+ is only passed
76
+ # to +object.as_json+, not any of this method's recursive +#as_json+
77
+ # calls.
78
+ def jsonify(value)
79
+ case value
80
+ when String
81
+ EscapedString.new(value)
82
+ when Numeric, NilClass, TrueClass, FalseClass
83
+ value
84
+ when Hash
85
+ Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
86
+ when Array
87
+ value.map { |v| jsonify(v) }
88
+ else
89
+ jsonify value.as_json
90
+ end
69
91
  end
70
- end
71
-
72
- def escape(string)
73
- Encoding.escape(string)
74
- end
75
92
 
76
- private
77
- def check_for_circular_references(value)
78
- unless @seen.add?(value.__id__)
79
- raise CircularReferenceError, 'object references itself'
80
- end
81
- yield
82
- ensure
83
- @seen.delete(value.__id__)
93
+ # Encode a "jsonified" Ruby data structure using the JSON gem
94
+ def stringify(jsonified)
95
+ ::JSON.generate(jsonified, quirks_mode: true, max_nesting: false)
84
96
  end
85
97
  end
86
98
 
87
-
88
- ESCAPED_CHARS = {
89
- "\x00" => '\u0000', "\x01" => '\u0001', "\x02" => '\u0002',
90
- "\x03" => '\u0003', "\x04" => '\u0004', "\x05" => '\u0005',
91
- "\x06" => '\u0006', "\x07" => '\u0007', "\x0B" => '\u000B',
92
- "\x0E" => '\u000E', "\x0F" => '\u000F', "\x10" => '\u0010',
93
- "\x11" => '\u0011', "\x12" => '\u0012', "\x13" => '\u0013',
94
- "\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016',
95
- "\x17" => '\u0017', "\x18" => '\u0018', "\x19" => '\u0019',
96
- "\x1A" => '\u001A', "\x1B" => '\u001B', "\x1C" => '\u001C',
97
- "\x1D" => '\u001D', "\x1E" => '\u001E', "\x1F" => '\u001F',
98
- "\010" => '\b',
99
- "\f" => '\f',
100
- "\n" => '\n',
101
- "\r" => '\r',
102
- "\t" => '\t',
103
- '"' => '\"',
104
- '\\' => '\\\\',
105
- '>' => '\u003E',
106
- '<' => '\u003C',
107
- '&' => '\u0026' }
108
-
109
99
  class << self
110
100
  # If true, use ISO 8601 format for dates and times. Otherwise, fall back
111
101
  # to the Active Support legacy format.
112
102
  attr_accessor :use_standard_json_time_format
113
103
 
114
- # If false, serializes BigDecimal objects as numeric instead of wrapping
115
- # them in a string.
116
- attr_accessor :encode_big_decimal_as_string
104
+ # If true, encode >, <, & as escaped unicode sequences (e.g. > as \u003e)
105
+ # as a safety measure.
106
+ attr_accessor :escape_html_entities_in_json
117
107
 
118
- attr_accessor :escape_regex
119
- attr_reader :escape_html_entities_in_json
108
+ # Sets the encoder used by Rails to encode Ruby objects into JSON strings
109
+ # in +Object#to_json+ and +ActiveSupport::JSON.encode+.
110
+ attr_accessor :json_encoder
120
111
 
121
- def escape_html_entities_in_json=(value)
122
- self.escape_regex = \
123
- if @escape_html_entities_in_json = value
124
- /[\x00-\x1F"\\><&]/
125
- else
126
- /[\x00-\x1F"\\]/
127
- end
128
- end
112
+ def encode_big_decimal_as_string=(as_string)
113
+ message = \
114
+ "The JSON encoder in Rails 4.1 no longer supports encoding BigDecimals as JSON numbers. Instead, " \
115
+ "the new encoder will always encode them as strings.\n\n" \
116
+ "You are seeing this error because you have 'active_support.encode_big_decimal_as_string' in " \
117
+ "your configuration file. If you have been setting this to true, you can safely remove it from " \
118
+ "your configuration. Otherwise, you should add the 'activesupport-json_encoder' gem to your " \
119
+ "Gemfile in order to restore this functionality."
129
120
 
130
- def escape(string)
131
- string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
132
- json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
133
- json = %("#{json}")
134
- json.force_encoding(::Encoding::UTF_8)
135
- json
121
+ raise NotImplementedError, message
136
122
  end
137
- end
138
-
139
- self.use_standard_json_time_format = true
140
- self.escape_html_entities_in_json = true
141
- self.encode_big_decimal_as_string = true
142
- end
143
- end
144
- end
145
-
146
- class Object
147
- def as_json(options = nil) #:nodoc:
148
- if respond_to?(:to_hash)
149
- to_hash
150
- else
151
- instance_values
152
- end
153
- end
154
- end
155
-
156
- class Struct #:nodoc:
157
- def as_json(options = nil)
158
- Hash[members.zip(values)]
159
- end
160
- end
161
-
162
- class TrueClass
163
- def as_json(options = nil) #:nodoc:
164
- self
165
- end
166
-
167
- def encode_json(encoder) #:nodoc:
168
- to_s
169
- end
170
- end
171
-
172
- class FalseClass
173
- def as_json(options = nil) #:nodoc:
174
- self
175
- end
176
-
177
- def encode_json(encoder) #:nodoc:
178
- to_s
179
- end
180
- end
181
-
182
- class NilClass
183
- def as_json(options = nil) #:nodoc:
184
- self
185
- end
186
-
187
- def encode_json(encoder) #:nodoc:
188
- 'null'
189
- end
190
- end
191
-
192
- class String
193
- def as_json(options = nil) #:nodoc:
194
- self
195
- end
196
123
 
197
- def encode_json(encoder) #:nodoc:
198
- encoder.escape(self)
199
- end
200
- end
201
-
202
- class Symbol
203
- def as_json(options = nil) #:nodoc:
204
- to_s
205
- end
206
- end
207
-
208
- class Numeric
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
224
- end
124
+ def encode_big_decimal_as_string
125
+ message = \
126
+ "The JSON encoder in Rails 4.1 no longer supports encoding BigDecimals as JSON numbers. Instead, " \
127
+ "the new encoder will always encode them as strings.\n\n" \
128
+ "You are seeing this error because you are trying to check the value of the related configuration, " \
129
+ "'active_support.encode_big_decimal_as_string'. If your application depends on this option, you should " \
130
+ "add the 'activesupport-json_encoder' gem to your Gemfile. For now, this option will always be true. " \
131
+ "In the future, it will be removed from Rails, so you should stop checking its value."
225
132
 
226
- class BigDecimal
227
- # A BigDecimal would be naturally represented as a JSON number. Most libraries,
228
- # however, parse non-integer JSON numbers directly as floats. Clients using
229
- # those libraries would get in general a wrong number and no way to recover
230
- # other than manually inspecting the string with the JSON code itself.
231
- #
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.encode_big_decimal_as_string = 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
246
- end
133
+ ActiveSupport::Deprecation.warn message
247
134
 
248
- class Regexp
249
- def as_json(options = nil) #:nodoc:
250
- to_s
251
- end
252
- end
253
-
254
- module Enumerable
255
- def as_json(options = nil) #:nodoc:
256
- to_a.as_json(options)
257
- end
258
- end
259
-
260
- class Range
261
- def as_json(options = nil) #:nodoc:
262
- to_s
263
- end
264
- end
265
-
266
- class Array
267
- def as_json(options = nil) #:nodoc:
268
- # use encoder as a proxy to call as_json on all elements, to protect from circular references
269
- encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
270
- map { |v| encoder.as_json(v, options) }
271
- end
272
-
273
- def encode_json(encoder) #:nodoc:
274
- # we assume here that the encoder has already run as_json on self and the elements, so we run encode_json directly
275
- "[#{map { |v| v.encode_json(encoder) } * ','}]"
276
- end
277
- end
135
+ true
136
+ end
278
137
 
279
- class Hash
280
- def as_json(options = nil) #:nodoc:
281
- # create a subset of the hash by applying :only or :except
282
- subset = if options
283
- if attrs = options[:only]
284
- slice(*Array(attrs))
285
- elsif attrs = options[:except]
286
- except(*Array(attrs))
287
- else
288
- self
138
+ # Deprecate CircularReferenceError
139
+ def const_missing(name)
140
+ if name == :CircularReferenceError
141
+ message = "The JSON encoder in Rails 4.1 no longer offers protection from circular references. " \
142
+ "You are seeing this warning because you are rescuing from (or otherwise referencing) " \
143
+ "ActiveSupport::Encoding::CircularReferenceError. In the future, this error will be " \
144
+ "removed from Rails. You should remove these rescue blocks from your code and ensure " \
145
+ "that your data structures are free of circular references so they can be properly " \
146
+ "serialized into JSON.\n\n" \
147
+ "For example, the following Hash contains a circular reference to itself:\n" \
148
+ " h = {}\n" \
149
+ " h['circular'] = h\n" \
150
+ "In this case, calling h.to_json would not work properly."
151
+
152
+ ActiveSupport::Deprecation.warn message
153
+
154
+ SystemStackError
155
+ else
156
+ super
157
+ end
158
+ end
289
159
  end
290
- else
291
- self
292
- end
293
-
294
- # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
295
- encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
296
- Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
297
- end
298
160
 
299
- def encode_json(encoder) #:nodoc:
300
- # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be
301
- # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields);
302
-
303
- # on the other hand, we need to run as_json on the elements, because the model representation may contain fields
304
- # like Time/Date in their original (not jsonified) form, etc.
305
-
306
- "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}"
307
- end
308
- end
309
-
310
- class Time
311
- def as_json(options = nil) #:nodoc:
312
- if ActiveSupport.use_standard_json_time_format
313
- xmlschema
314
- else
315
- %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
316
- end
317
- end
318
- end
319
-
320
- class Date
321
- def as_json(options = nil) #:nodoc:
322
- if ActiveSupport.use_standard_json_time_format
323
- strftime("%Y-%m-%d")
324
- else
325
- strftime("%Y/%m/%d")
326
- end
327
- end
328
- end
329
-
330
- class DateTime
331
- def as_json(options = nil) #:nodoc:
332
- if ActiveSupport.use_standard_json_time_format
333
- xmlschema
334
- else
335
- strftime('%Y/%m/%d %H:%M:%S %z')
161
+ self.use_standard_json_time_format = true
162
+ self.escape_html_entities_in_json = true
163
+ self.json_encoder = JSONGemEncoder
336
164
  end
337
165
  end
338
166
  end