activesupport 3.2.13 → 3.2.14.rc1

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.

@@ -1,9 +1,34 @@
1
- ## unreleased ##
1
+ ## Rails 3.2.14.rc1 (Jul 8, 2013) ##
2
2
 
3
- * No changes.
3
+ * Make `Time.at_with_coercion` retain the second fraction and return local time.
4
+
5
+ Fixes #11350
6
+
7
+ *Neer Friedman*, *Andrew White*
8
+
9
+ * Fix `ActiveSupport::TaggedLogging` incorrectly providing program name the same as log message
10
+ even when block is not provided.
11
+
12
+ *Carson Reinke*
13
+
14
+ * Override `Time.at` to support the passing of Time-like values when called with a single argument.
15
+
16
+ *Andrew White*
17
+
18
+ * Revert the changes on unicode character encoding from `ActiveSupport::JSON.encode`.
19
+ This was causing a regression where the resulting string is always returning UTF-8.
20
+ Also it changes the behavior of this method on a stable release.
21
+ Fixes #9498.
22
+
23
+ *Rafael Mendonça França*
24
+
25
+ * Fix `ActiveSupport::TimeZone.parse` when time is at a local DST jump.
26
+ Fixes #9678.
27
+
28
+ *Andrew White*
4
29
 
5
30
 
6
- ## Rails 3.2.13 (Feb 17, 2013) ##
31
+ ## Rails 3.2.13 (Mar 18, 2013) ##
7
32
 
8
33
 
9
34
  * Fix DateTime comparison with DateTime::Infinity object.
@@ -67,7 +67,7 @@ class Class
67
67
  # object.setting = false # => NoMethodError
68
68
  def class_attribute(*attrs)
69
69
  options = attrs.extract_options!
70
- instance_reader = options.fetch(:instance_reader, true)
70
+ instance_reader = instance_reader = options.fetch(:instance_reader, true)
71
71
  instance_writer = options.fetch(:instance_writer, true)
72
72
 
73
73
  attrs.each do |name|
@@ -1,3 +1,4 @@
1
+ require 'date'
1
2
  require 'active_support/core_ext/object/acts_like'
2
3
 
3
4
  class DateTime
@@ -45,6 +45,23 @@ class Time
45
45
  def current
46
46
  ::Time.zone ? ::Time.zone.now : ::Time.now
47
47
  end
48
+
49
+ # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
50
+ # instances can be used when called with a single argument
51
+ def at_with_coercion(*args)
52
+ return at_without_coercion(*args) if args.size != 1
53
+
54
+ # Time.at can be called with a time or numerical value
55
+ time_or_number = args.first
56
+
57
+ if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
58
+ at_without_coercion(time_or_number.to_f).getlocal
59
+ else
60
+ at_without_coercion(time_or_number)
61
+ end
62
+ end
63
+ alias_method :at_without_coercion, :at
64
+ alias_method :at, :at_with_coercion
48
65
  end
49
66
 
50
67
  # Tells whether the Time object's time lies in the past
@@ -0,0 +1,272 @@
1
+ require 'active_support/core_ext/hash/keys'
2
+
3
+ module ActiveSupport
4
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
5
+ # to be the same.
6
+ #
7
+ # rgb = ActiveSupport::HashWithIndifferentAccess.new
8
+ #
9
+ # rgb[:black] = '#000000'
10
+ # rgb[:black] # => '#000000'
11
+ # rgb['black'] # => '#000000'
12
+ #
13
+ # rgb['white'] = '#FFFFFF'
14
+ # rgb[:white] # => '#FFFFFF'
15
+ # rgb['white'] # => '#FFFFFF'
16
+ #
17
+ # Internally symbols are mapped to strings when used as keys in the entire
18
+ # writing interface (calling <tt>[]=</tt>, <tt>merge</tt>, etc). This
19
+ # mapping belongs to the public interface. For example, given:
20
+ #
21
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
22
+ #
23
+ # You are guaranteed that the key is returned as a string:
24
+ #
25
+ # hash.keys # => ["a"]
26
+ #
27
+ # Technically other types of keys are accepted:
28
+ #
29
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
30
+ # hash[0] = 0
31
+ # hash # => {"a"=>1, 0=>0}
32
+ #
33
+ # but this class is intended for use cases where strings or symbols are the
34
+ # expected keys and it is convenient to understand both as the same. For
35
+ # example the +params+ hash in Ruby on Rails.
36
+ #
37
+ # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
38
+ #
39
+ # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
40
+ #
41
+ # which may be handy.
42
+ class HashWithIndifferentAccess < Hash
43
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
44
+ # this class.
45
+ def extractable_options?
46
+ true
47
+ end
48
+
49
+ def with_indifferent_access
50
+ dup
51
+ end
52
+
53
+ def nested_under_indifferent_access
54
+ self
55
+ end
56
+
57
+ def initialize(constructor = {})
58
+ if constructor.is_a?(Hash)
59
+ super()
60
+ update(constructor)
61
+ else
62
+ super(constructor)
63
+ end
64
+ end
65
+
66
+ def default(key = nil)
67
+ if key.is_a?(Symbol) && include?(key = key.to_s)
68
+ self[key]
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ def self.new_from_hash_copying_default(hash)
75
+ new(hash).tap do |new_hash|
76
+ new_hash.default = hash.default
77
+ end
78
+ end
79
+
80
+ def self.[](*args)
81
+ new.merge!(Hash[*args])
82
+ end
83
+
84
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
85
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
86
+
87
+ # Assigns a new value to the hash:
88
+ #
89
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
90
+ # hash[:key] = 'value'
91
+ #
92
+ # This value can be later fetched using either +:key+ or +'key'+.
93
+ def []=(key, value)
94
+ regular_writer(convert_key(key), convert_value(value, for: :assignment))
95
+ end
96
+
97
+ alias_method :store, :[]=
98
+
99
+ # Updates the receiver in-place, merging in the hash passed as argument:
100
+ #
101
+ # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
102
+ # hash_1[:key] = 'value'
103
+ #
104
+ # hash_2 = ActiveSupport::HashWithIndifferentAccess.new
105
+ # hash_2[:key] = 'New Value!'
106
+ #
107
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
108
+ #
109
+ # The argument can be either an
110
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
111
+ # In either case the merge respects the semantics of indifferent access.
112
+ #
113
+ # If the argument is a regular hash with keys +:key+ and +"key"+ only one
114
+ # of the values end up in the receiver, but which one is unspecified.
115
+ #
116
+ # When given a block, the value for duplicated keys will be determined
117
+ # by the result of invoking the block with the duplicated key, the value
118
+ # in the receiver, and the value in +other_hash+. The rules for duplicated
119
+ # keys follow the semantics of indifferent access:
120
+ #
121
+ # hash_1[:key] = 10
122
+ # hash_2['key'] = 12
123
+ # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
124
+ def update(other_hash)
125
+ if other_hash.is_a? HashWithIndifferentAccess
126
+ super(other_hash)
127
+ else
128
+ other_hash.each_pair do |key, value|
129
+ if block_given? && key?(key)
130
+ value = yield(convert_key(key), self[key], value)
131
+ end
132
+ regular_writer(convert_key(key), convert_value(value))
133
+ end
134
+ self
135
+ end
136
+ end
137
+
138
+ alias_method :merge!, :update
139
+
140
+ # Checks the hash for a key matching the argument passed in:
141
+ #
142
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
143
+ # hash['key'] = 'value'
144
+ # hash.key?(:key) # => true
145
+ # hash.key?('key') # => true
146
+ def key?(key)
147
+ super(convert_key(key))
148
+ end
149
+
150
+ alias_method :include?, :key?
151
+ alias_method :has_key?, :key?
152
+ alias_method :member?, :key?
153
+
154
+ # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
155
+ # either a string or a symbol:
156
+ #
157
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
158
+ # counters[:foo] = 1
159
+ #
160
+ # counters.fetch('foo') # => 1
161
+ # counters.fetch(:bar, 0) # => 0
162
+ # counters.fetch(:bar) {|key| 0} # => 0
163
+ # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
164
+ def fetch(key, *extras)
165
+ super(convert_key(key), *extras)
166
+ end
167
+
168
+ # Returns an array of the values at the specified indices:
169
+ #
170
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
171
+ # hash[:a] = 'x'
172
+ # hash[:b] = 'y'
173
+ # hash.values_at('a', 'b') # => ["x", "y"]
174
+ def values_at(*indices)
175
+ indices.collect {|key| self[convert_key(key)]}
176
+ end
177
+
178
+ # Returns an exact copy of the hash.
179
+ def dup
180
+ self.class.new(self).tap do |new_hash|
181
+ new_hash.default = default
182
+ end
183
+ end
184
+
185
+ # This method has the same semantics of +update+, except it does not
186
+ # modify the receiver but rather returns a new hash with indifferent
187
+ # access with the result of the merge.
188
+ def merge(hash, &block)
189
+ self.dup.update(hash, &block)
190
+ end
191
+
192
+ # Like +merge+ but the other way around: Merges the receiver into the
193
+ # argument and returns a new hash with indifferent access as result:
194
+ #
195
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
196
+ # hash['a'] = nil
197
+ # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
198
+ def reverse_merge(other_hash)
199
+ super(self.class.new_from_hash_copying_default(other_hash))
200
+ end
201
+
202
+ # Same semantics as +reverse_merge+ but modifies the receiver in-place.
203
+ def reverse_merge!(other_hash)
204
+ replace(reverse_merge( other_hash ))
205
+ end
206
+
207
+ # Replaces the contents of this hash with other_hash.
208
+ #
209
+ # h = { "a" => 100, "b" => 200 }
210
+ # h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
211
+ def replace(other_hash)
212
+ super(self.class.new_from_hash_copying_default(other_hash))
213
+ end
214
+
215
+ # Removes the specified key from the hash.
216
+ def delete(key)
217
+ super(convert_key(key))
218
+ end
219
+
220
+ def stringify_keys!; self end
221
+ def deep_stringify_keys!; self end
222
+ def stringify_keys; dup end
223
+ def deep_stringify_keys; dup end
224
+ undef :symbolize_keys!
225
+ undef :deep_symbolize_keys!
226
+ def symbolize_keys; to_hash.symbolize_keys! end
227
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys end
228
+ def to_options!; self end
229
+
230
+ # Convert to a regular hash with string keys.
231
+ def to_hash
232
+ _new_hash= {}
233
+ each do |key, value|
234
+ <<<<<<< HEAD
235
+ _new_hash[convert_key(key)] = convert_value(value,true)
236
+ =======
237
+ _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
238
+ >>>>>>> 424fa92... Merge pull request #10784 from senny/10526_prevent_key_transformation
239
+ end
240
+ Hash.new(default).merge!(_new_hash)
241
+ end
242
+
243
+ protected
244
+ def convert_key(key)
245
+ key.kind_of?(Symbol) ? key.to_s : key
246
+ end
247
+
248
+ def convert_value(value, options = {})
249
+ if value.is_a? Hash
250
+ if options[:for] == :to_hash
251
+ value.to_hash
252
+ else
253
+ value.nested_under_indifferent_access
254
+ end
255
+ elsif value.is_a?(Array)
256
+ <<<<<<< HEAD
257
+ value = value.dup if value.frozen?
258
+ value.map! { |e| convert_value(e) }
259
+ =======
260
+ unless options[:for] == :assignment
261
+ value = value.dup
262
+ end
263
+ value.map! { |e| convert_value(e, options) }
264
+ >>>>>>> 424fa92... Merge pull request #10784 from senny/10526_prevent_key_transformation
265
+ else
266
+ value
267
+ end
268
+ end
269
+ end
270
+ end
271
+
272
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -122,7 +122,13 @@ module ActiveSupport
122
122
  if string.respond_to?(:force_encoding)
123
123
  string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
124
124
  end
125
- json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
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
+ }
126
132
  json = %("#{json}")
127
133
  json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
128
134
  json
@@ -0,0 +1,351 @@
1
+ #encoding: us-ascii
2
+
3
+ require 'active_support/core_ext/object/to_json'
4
+ require 'active_support/core_ext/module/delegation'
5
+ require 'active_support/json/variable'
6
+
7
+ require 'bigdecimal'
8
+ require 'active_support/core_ext/big_decimal/conversions' # for #to_s
9
+ require 'active_support/core_ext/hash/except'
10
+ require 'active_support/core_ext/hash/slice'
11
+ require 'active_support/core_ext/object/instance_variables'
12
+ require 'time'
13
+ require 'active_support/core_ext/time/conversions'
14
+ require 'active_support/core_ext/date_time/conversions'
15
+ require 'active_support/core_ext/date/conversions'
16
+ require 'set'
17
+
18
+ module ActiveSupport
19
+ class << self
20
+ delegate :use_standard_json_time_format, :use_standard_json_time_format=,
21
+ :escape_html_entities_in_json, :escape_html_entities_in_json=,
22
+ :encode_big_decimal_as_string, :encode_big_decimal_as_string=,
23
+ :to => :'ActiveSupport::JSON::Encoding'
24
+ end
25
+
26
+ module JSON
27
+ # matches YAML-formatted dates
28
+ 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})?))$/
29
+
30
+ # Dumps objects in JSON (JavaScript Object Notation).
31
+ # See www.json.org for more info.
32
+ #
33
+ # ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
34
+ # # => "{\"team\":\"rails\",\"players\":\"36\"}"
35
+ def self.encode(value, options = nil)
36
+ Encoding::Encoder.new(options).encode(value)
37
+ end
38
+
39
+ module Encoding #:nodoc:
40
+ class CircularReferenceError < StandardError; end
41
+
42
+ class Encoder
43
+ attr_reader :options
44
+
45
+ def initialize(options = nil)
46
+ @options = options || {}
47
+ @seen = Set.new
48
+ end
49
+
50
+ def encode(value, use_options = true)
51
+ check_for_circular_references(value) do
52
+ jsonified = use_options ? value.as_json(options_for(value)) : value.as_json
53
+ jsonified.encode_json(self)
54
+ end
55
+ end
56
+
57
+ # like encode, but only calls as_json, without encoding to string.
58
+ def as_json(value, use_options = true)
59
+ check_for_circular_references(value) do
60
+ use_options ? value.as_json(options_for(value)) : value.as_json
61
+ end
62
+ end
63
+
64
+ def options_for(value)
65
+ if value.is_a?(Array) || value.is_a?(Hash)
66
+ # hashes and arrays need to get encoder in the options, so that
67
+ # they can detect circular references.
68
+ options.merge(:encoder => self)
69
+ else
70
+ options.dup
71
+ end
72
+ end
73
+
74
+ def escape(string)
75
+ Encoding.escape(string)
76
+ end
77
+
78
+ private
79
+ def check_for_circular_references(value)
80
+ unless @seen.add?(value.__id__)
81
+ raise CircularReferenceError, 'object references itself'
82
+ end
83
+ yield
84
+ ensure
85
+ @seen.delete(value.__id__)
86
+ end
87
+ end
88
+
89
+
90
+ ESCAPED_CHARS = {
91
+ "\x00" => '\u0000', "\x01" => '\u0001', "\x02" => '\u0002',
92
+ "\x03" => '\u0003', "\x04" => '\u0004', "\x05" => '\u0005',
93
+ "\x06" => '\u0006', "\x07" => '\u0007', "\x0B" => '\u000B',
94
+ "\x0E" => '\u000E', "\x0F" => '\u000F', "\x10" => '\u0010',
95
+ "\x11" => '\u0011', "\x12" => '\u0012', "\x13" => '\u0013',
96
+ "\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016',
97
+ "\x17" => '\u0017', "\x18" => '\u0018', "\x19" => '\u0019',
98
+ "\x1A" => '\u001A', "\x1B" => '\u001B', "\x1C" => '\u001C',
99
+ "\x1D" => '\u001D', "\x1E" => '\u001E', "\x1F" => '\u001F',
100
+ "\010" => '\b',
101
+ "\f" => '\f',
102
+ "\n" => '\n',
103
+ "\xe2\x80\xa8" => '\u2028',
104
+ "\xe2\x80\xa9" => '\u2029',
105
+ "\r" => '\r',
106
+ "\t" => '\t',
107
+ '"' => '\"',
108
+ '\\' => '\\\\',
109
+ '>' => '\u003E',
110
+ '<' => '\u003C',
111
+ '&' => '\u0026',
112
+ "#{0xe2.chr}#{0x80.chr}#{0xa8.chr}" => '\u2028',
113
+ "#{0xe2.chr}#{0x80.chr}#{0xa9.chr}" => '\u2029',
114
+ }
115
+
116
+ class << self
117
+ # If true, use ISO 8601 format for dates and times. Otherwise, fall back
118
+ # to the Active Support legacy format.
119
+ attr_accessor :use_standard_json_time_format
120
+
121
+ # If false, serializes BigDecimal objects as numeric instead of wrapping
122
+ # them in a string.
123
+ attr_accessor :encode_big_decimal_as_string
124
+
125
+ attr_accessor :escape_regex
126
+ attr_reader :escape_html_entities_in_json
127
+
128
+ def escape_html_entities_in_json=(value)
129
+ self.escape_regex = \
130
+ if @escape_html_entities_in_json = value
131
+ <<<<<<< HEAD
132
+ /\xe2\x80\xa8|\xe2\x80\xa9|[\x00-\x1F"\\><&]/
133
+ else
134
+ /\xe2\x80\xa8|\xe2\x80\xa9|[\x00-\x1F"\\]/
135
+ =======
136
+ /[\x00-\x1F"\\><&]|#{0xe2.chr}#{0x80.chr}#{0xa8.chr}|#{0xe2.chr}#{0x80.chr}#{0xa9.chr}/
137
+ else
138
+ /[\x00-\x1F"\\]|#{0xe2.chr}#{0x80.chr}#{0xa8.chr}|#{0xe2.chr}#{0x80.chr}#{0xa9.chr}/
139
+ >>>>>>> cmaruz/master
140
+ end
141
+ end
142
+
143
+ def escape(string)
144
+ string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
145
+ json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
146
+ json = %("#{json}")
147
+ json.force_encoding(::Encoding::UTF_8)
148
+ json
149
+ end
150
+ end
151
+
152
+ self.use_standard_json_time_format = true
153
+ self.escape_html_entities_in_json = true
154
+ self.encode_big_decimal_as_string = true
155
+ end
156
+ end
157
+ end
158
+
159
+ class Object
160
+ def as_json(options = nil) #:nodoc:
161
+ if respond_to?(:to_hash)
162
+ to_hash
163
+ else
164
+ instance_values
165
+ end
166
+ end
167
+ end
168
+
169
+ class Struct #:nodoc:
170
+ def as_json(options = nil)
171
+ Hash[members.zip(values)]
172
+ end
173
+ end
174
+
175
+ class TrueClass
176
+ def as_json(options = nil) #:nodoc:
177
+ self
178
+ end
179
+
180
+ def encode_json(encoder) #:nodoc:
181
+ to_s
182
+ end
183
+ end
184
+
185
+ class FalseClass
186
+ def as_json(options = nil) #:nodoc:
187
+ self
188
+ end
189
+
190
+ def encode_json(encoder) #:nodoc:
191
+ to_s
192
+ end
193
+ end
194
+
195
+ class NilClass
196
+ def as_json(options = nil) #:nodoc:
197
+ self
198
+ end
199
+
200
+ def encode_json(encoder) #:nodoc:
201
+ 'null'
202
+ end
203
+ end
204
+
205
+ class String
206
+ def as_json(options = nil) #:nodoc:
207
+ self
208
+ end
209
+
210
+ def encode_json(encoder) #:nodoc:
211
+ encoder.escape(self)
212
+ end
213
+ end
214
+
215
+ class Symbol
216
+ def as_json(options = nil) #:nodoc:
217
+ to_s
218
+ end
219
+ end
220
+
221
+ class Numeric
222
+ def as_json(options = nil) #:nodoc:
223
+ self
224
+ end
225
+
226
+ def encode_json(encoder) #:nodoc:
227
+ to_s
228
+ end
229
+ end
230
+
231
+ class Float
232
+ # Encoding Infinity or NaN to JSON should return "null". The default returns
233
+ # "Infinity" or "NaN" which breaks parsing the JSON. E.g. JSON.parse('[NaN]').
234
+ def as_json(options = nil) #:nodoc:
235
+ finite? ? self : nil
236
+ end
237
+ end
238
+
239
+ class BigDecimal
240
+ # A BigDecimal would be naturally represented as a JSON number. Most libraries,
241
+ # however, parse non-integer JSON numbers directly as floats. Clients using
242
+ # those libraries would get in general a wrong number and no way to recover
243
+ # other than manually inspecting the string with the JSON code itself.
244
+ #
245
+ # That's why a JSON string is returned. The JSON literal is not numeric, but
246
+ # if the other end knows by contract that the data is supposed to be a
247
+ # BigDecimal, it still has the chance to post-process the string and get the
248
+ # real value.
249
+ #
250
+ # Use <tt>ActiveSupport.use_standard_json_big_decimal_format = true</tt> to
251
+ # override this behavior.
252
+ def as_json(options = nil) #:nodoc:
253
+ if finite?
254
+ ActiveSupport.encode_big_decimal_as_string ? to_s : self
255
+ else
256
+ nil
257
+ end
258
+ end
259
+ end
260
+
261
+ class Regexp
262
+ def as_json(options = nil) #:nodoc:
263
+ to_s
264
+ end
265
+ end
266
+
267
+ module Enumerable
268
+ def as_json(options = nil) #:nodoc:
269
+ to_a.as_json(options)
270
+ end
271
+ end
272
+
273
+ class Range
274
+ def as_json(options = nil) #:nodoc:
275
+ to_s
276
+ end
277
+ end
278
+
279
+ class Array
280
+ def as_json(options = nil) #:nodoc:
281
+ # use encoder as a proxy to call as_json on all elements, to protect from circular references
282
+ encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
283
+ map { |v| encoder.as_json(v, options) }
284
+ end
285
+
286
+ def encode_json(encoder) #:nodoc:
287
+ # we assume here that the encoder has already run as_json on self and the elements, so we run encode_json directly
288
+ "[#{map { |v| v.encode_json(encoder) } * ','}]"
289
+ end
290
+ end
291
+
292
+ class Hash
293
+ def as_json(options = nil) #:nodoc:
294
+ # create a subset of the hash by applying :only or :except
295
+ subset = if options
296
+ if attrs = options[:only]
297
+ slice(*Array(attrs))
298
+ elsif attrs = options[:except]
299
+ except(*Array(attrs))
300
+ else
301
+ self
302
+ end
303
+ else
304
+ self
305
+ end
306
+
307
+ # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
308
+ encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
309
+ Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
310
+ end
311
+
312
+ def encode_json(encoder) #:nodoc:
313
+ # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be
314
+ # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields);
315
+
316
+ # on the other hand, we need to run as_json on the elements, because the model representation may contain fields
317
+ # like Time/Date in their original (not jsonified) form, etc.
318
+
319
+ "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}"
320
+ end
321
+ end
322
+
323
+ class Time
324
+ def as_json(options = nil) #:nodoc:
325
+ if ActiveSupport.use_standard_json_time_format
326
+ xmlschema
327
+ else
328
+ %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
329
+ end
330
+ end
331
+ end
332
+
333
+ class Date
334
+ def as_json(options = nil) #:nodoc:
335
+ if ActiveSupport.use_standard_json_time_format
336
+ strftime("%Y-%m-%d")
337
+ else
338
+ strftime("%Y/%m/%d")
339
+ end
340
+ end
341
+ end
342
+
343
+ class DateTime
344
+ def as_json(options = nil) #:nodoc:
345
+ if ActiveSupport.use_standard_json_time_format
346
+ xmlschema
347
+ else
348
+ strftime('%Y/%m/%d %H:%M:%S %z')
349
+ end
350
+ end
351
+ end
@@ -44,7 +44,14 @@ module ActiveSupport
44
44
  deprecate :silence
45
45
 
46
46
  def add(severity, message = nil, progname = nil, &block)
47
- message = (block_given? ? block.call : progname) if message.nil?
47
+ if message.nil?
48
+ if block_given?
49
+ message = block.call
50
+ else
51
+ message = progname
52
+ progname = nil #No instance variable for this like Logger
53
+ end
54
+ end
48
55
  @logger.add(severity, "#{tags_text}#{message}", progname)
49
56
  end
50
57
 
@@ -23,7 +23,7 @@ module ActiveSupport
23
23
 
24
24
  # each implementation should define metrics and freeze the defaults
25
25
  DEFAULTS =
26
- if ARGV.include?('--benchmark') # HAX for rake test
26
+ if ENV["BENCHMARK_TESTS"]
27
27
  { :runs => 4,
28
28
  :output => 'tmp/performance',
29
29
  :benchmark => true }
@@ -6,7 +6,7 @@ module ActiveSupport
6
6
  module Testing
7
7
  module Performance
8
8
  DEFAULTS.merge!(
9
- if ARGV.include?('--benchmark')
9
+ if ENV["BENCHMARK_TESTS"]
10
10
  {:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]}
11
11
  else
12
12
  { :metrics => [:wall_time],
@@ -4,7 +4,7 @@ module ActiveSupport
4
4
  module Testing
5
5
  module Performance
6
6
  DEFAULTS.merge!(
7
- if ARGV.include?('--benchmark')
7
+ if ENV["BENCHMARK_TESTS"]
8
8
  {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}
9
9
  else
10
10
  { :metrics => [:wall_time],
@@ -9,7 +9,7 @@ module ActiveSupport
9
9
  module Testing
10
10
  module Performance
11
11
  DEFAULTS.merge!(
12
- if ARGV.include?('--benchmark')
12
+ if ENV["BENCHMARK_TESTS"]
13
13
  { :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time] }
14
14
  else
15
15
  { :min_percent => 0.01,
@@ -268,13 +268,23 @@ module ActiveSupport
268
268
  # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
269
269
  # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
270
270
  def parse(str, now=now)
271
- date_parts = Date._parse(str)
272
- return if date_parts.blank?
273
- time = Time.parse(str, now) rescue DateTime.parse(str)
274
- if date_parts[:offset].nil?
275
- ActiveSupport::TimeWithZone.new(nil, self, time)
271
+ parts = Date._parse(str, false)
272
+ return if parts.empty?
273
+
274
+ time = Time.utc(
275
+ parts.fetch(:year, now.year),
276
+ parts.fetch(:mon, now.month),
277
+ parts.fetch(:mday, now.day),
278
+ parts.fetch(:hour, 0),
279
+ parts.fetch(:min, 0),
280
+ parts.fetch(:sec, 0),
281
+ parts.fetch(:sec_fraction, 0) * 1000000
282
+ )
283
+
284
+ if parts[:offset]
285
+ TimeWithZone.new(time - parts[:offset], self)
276
286
  else
277
- time.in_time_zone(self)
287
+ TimeWithZone.new(nil, self, time)
278
288
  end
279
289
  end
280
290
 
@@ -2,8 +2,8 @@ module ActiveSupport
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
- TINY = 13
6
- PRE = nil
5
+ TINY = 14
6
+ PRE = "rc1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
metadata CHANGED
@@ -1,51 +1,72 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
- version: !ruby/object:Gem::Version
4
- version: 3.2.13
3
+ version: !ruby/object:Gem::Version
4
+ hash: 1423556129
5
+ prerelease: 7
6
+ segments:
7
+ - 3
8
+ - 2
9
+ - 14
10
+ - rc
11
+ - 1
12
+ version: 3.2.14.rc1
5
13
  platform: ruby
6
- authors:
14
+ authors:
7
15
  - David Heinemeier Hansson
8
16
  autorequire:
9
17
  bindir: bin
10
18
  cert_chain: []
11
- date: 2013-03-18 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: i18n
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '='
18
- - !ruby/object:Gem::Version
19
- version: 0.6.1
19
+
20
+ date: 2013-07-12 00:00:00 -03:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 0
32
+ - 6
33
+ version: "0.6"
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ hash: 15
37
+ segments:
38
+ - 0
39
+ - 6
40
+ - 4
41
+ version: 0.6.4
20
42
  type: :runtime
43
+ name: i18n
44
+ version_requirements: *id001
21
45
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '='
25
- - !ruby/object:Gem::Version
26
- version: 0.6.1
27
- - !ruby/object:Gem::Dependency
28
- name: multi_json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
46
+ - !ruby/object:Gem::Dependency
47
+ requirement: &id002 !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
31
50
  - - ~>
32
- - !ruby/object:Gem::Version
33
- version: '1.0'
51
+ - !ruby/object:Gem::Version
52
+ hash: 15
53
+ segments:
54
+ - 1
55
+ - 0
56
+ version: "1.0"
34
57
  type: :runtime
58
+ name: multi_json
59
+ version_requirements: *id002
35
60
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ~>
39
- - !ruby/object:Gem::Version
40
- version: '1.0'
41
- description: A toolkit of support libraries and Ruby core extensions extracted from
42
- the Rails framework. Rich support for multibyte strings, internationalization, time
43
- zones, and testing.
61
+ description: A toolkit of support libraries and Ruby core extensions extracted from the Rails framework. Rich support for multibyte strings, internationalization, time zones, and testing.
44
62
  email: david@loudthinking.com
45
63
  executables: []
64
+
46
65
  extensions: []
66
+
47
67
  extra_rdoc_files: []
48
- files:
68
+
69
+ files:
49
70
  - CHANGELOG.md
50
71
  - MIT-LICENSE
51
72
  - README.rdoc
@@ -196,6 +217,7 @@ files:
196
217
  - lib/active_support/file_watcher.rb
197
218
  - lib/active_support/gzip.rb
198
219
  - lib/active_support/hash_with_indifferent_access.rb
220
+ - lib/active_support/hash_with_indifferent_access.rb.orig
199
221
  - lib/active_support/i18n.rb
200
222
  - lib/active_support/i18n_railtie.rb
201
223
  - lib/active_support/inflections.rb
@@ -205,6 +227,7 @@ files:
205
227
  - lib/active_support/inflector.rb
206
228
  - lib/active_support/json/decoding.rb
207
229
  - lib/active_support/json/encoding.rb
230
+ - lib/active_support/json/encoding.rb.orig
208
231
  - lib/active_support/json/variable.rb
209
232
  - lib/active_support/json.rb
210
233
  - lib/active_support/lazy_load_hooks.rb
@@ -259,30 +282,44 @@ files:
259
282
  - lib/active_support/xml_mini/rexml.rb
260
283
  - lib/active_support/xml_mini.rb
261
284
  - lib/active_support.rb
285
+ has_rdoc: true
262
286
  homepage: http://www.rubyonrails.org
263
- licenses: []
264
- metadata: {}
287
+ licenses:
288
+ - MIT
265
289
  post_install_message:
266
- rdoc_options:
290
+ rdoc_options:
267
291
  - --encoding
268
292
  - UTF-8
269
- require_paths:
293
+ require_paths:
270
294
  - lib
271
- required_ruby_version: !ruby/object:Gem::Requirement
272
- requirements:
273
- - - '>='
274
- - !ruby/object:Gem::Version
295
+ required_ruby_version: !ruby/object:Gem::Requirement
296
+ none: false
297
+ requirements:
298
+ - - ">="
299
+ - !ruby/object:Gem::Version
300
+ hash: 57
301
+ segments:
302
+ - 1
303
+ - 8
304
+ - 7
275
305
  version: 1.8.7
276
- required_rubygems_version: !ruby/object:Gem::Requirement
277
- requirements:
278
- - - '>='
279
- - !ruby/object:Gem::Version
280
- version: '0'
306
+ required_rubygems_version: !ruby/object:Gem::Requirement
307
+ none: false
308
+ requirements:
309
+ - - ">"
310
+ - !ruby/object:Gem::Version
311
+ hash: 25
312
+ segments:
313
+ - 1
314
+ - 3
315
+ - 1
316
+ version: 1.3.1
281
317
  requirements: []
318
+
282
319
  rubyforge_project:
283
- rubygems_version: 2.0.2
320
+ rubygems_version: 1.6.2
284
321
  signing_key:
285
- specification_version: 4
286
- summary: A toolkit of support libraries and Ruby core extensions extracted from the
287
- Rails framework.
322
+ specification_version: 3
323
+ summary: A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.
288
324
  test_files: []
325
+
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: c6d00c3317a3cee1653b4afd2e30f5214cfb9522
4
- data.tar.gz: 4224817317c51c2c74e03f8fec3f87cb54a2249c
5
- SHA512:
6
- metadata.gz: 26714413159c1268613e17639f89de58bbc2a7e87b8ac798ec2c343308e2a74eff9852f939ca76e84f1d6e24793c54c1f036fe4b0c2c5aeb72689605d6e711cc
7
- data.tar.gz: 74e44db1d704d2c1adbd9032d88ccaaa3ff94c74386eda3966617e67b28c0ab1b5fe9cc1227e779baa8a8a6a9482defff0d7cca0953c9618cda24864cb668c6d