activesupport 4.1.0 → 4.1.11

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +209 -0
  3. data/lib/active_support/cache/strategy/local_cache.rb +1 -0
  4. data/lib/active_support/cache.rb +1 -1
  5. data/lib/active_support/callbacks.rb +118 -76
  6. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  7. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -11
  8. data/lib/active_support/core_ext/hash/keys.rb +38 -16
  9. data/lib/active_support/core_ext/object/duplicable.rb +10 -0
  10. data/lib/active_support/core_ext/object/json.rb +3 -3
  11. data/lib/active_support/core_ext/object/to_param.rb +1 -62
  12. data/lib/active_support/core_ext/object/to_query.rb +58 -7
  13. data/lib/active_support/core_ext/string/filters.rb +1 -1
  14. data/lib/active_support/core_ext/string/output_safety.rb +7 -3
  15. data/lib/active_support/core_ext/time/zones.rb +1 -0
  16. data/lib/active_support/dependencies.rb +4 -4
  17. data/lib/active_support/duration.rb +5 -1
  18. data/lib/active_support/gem_version.rb +1 -1
  19. data/lib/active_support/hash_with_indifferent_access.rb +2 -1
  20. data/lib/active_support/i18n_railtie.rb +5 -1
  21. data/lib/active_support/inflector/methods.rb +1 -1
  22. data/lib/active_support/json/encoding.rb +4 -0
  23. data/lib/active_support/multibyte/unicode.rb +0 -1
  24. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
  25. data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -6
  26. data/lib/active_support/option_merger.rb +1 -1
  27. data/lib/active_support/subscriber.rb +10 -1
  28. data/lib/active_support/values/time_zone.rb +5 -2
  29. data/lib/active_support/xml_mini/jdom.rb +6 -5
  30. data/lib/active_support/xml_mini/rexml.rb +6 -5
  31. data/lib/active_support/xml_mini.rb +3 -0
  32. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c936ce5651934fea6a06f172e8292e7b8fb4d23f
4
- data.tar.gz: ffed9ceb345137266ba5654dc932f1b701912f3f
3
+ metadata.gz: 54422272f221596ea76d050a34d6b83f1f1ae6c9
4
+ data.tar.gz: a05f3b1deef3c7cd943ec76a3e5a66b0987b5b93
5
5
  SHA512:
6
- metadata.gz: d97b61358252646f0bd110a609de014a449d5a0567c583a8a0b350134fa652c0d846bfd4dac4039c385fdd28423280ef91f59369e7a73af8a16ab25d604261ea
7
- data.tar.gz: d58a57c9ea281d9a9605a220e62206b7a3d0059d28844213c2d0cc1b9256180a8854ecb2efb73711e296b9349c2b1254f49dafc25b6a52cfe37d3e4ddd23d4be
6
+ metadata.gz: 0c2db7529fd5bc8dc419715c51b865b637e650d76802b40087127893bd3b37defe381608442a7f539dd4a06293cf852b28635b8bac87afbc01aff4ddd6bebf85
7
+ data.tar.gz: 99497a90dae4da6b174fe25984d1bc362b410b1a5025421774f51c4fcd1162453fd2d58a6a8dd881bd342c576a068618f0c63f14d137d5346fab49424f89c5f5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,212 @@
1
+ ## Rails 4.1.11 (June 16, 2015) ##
2
+
3
+ * Fix XSS vulnerability in `ActiveSupport::JSON.encode` method.
4
+
5
+ CVE-2015-3226.
6
+
7
+ *Rafael Mendonça França*
8
+
9
+ * Fix denial of service vulnerability in the XML processing.
10
+
11
+ CVE-2015-3227.
12
+
13
+ *Aaron Patterson*
14
+
15
+
16
+ ## Rails 4.1.10 (March 19, 2015) ##
17
+
18
+ * Fixed a roundtrip problem with AS::SafeBuffer where primitive-like strings
19
+ will be dumped as primitives:
20
+
21
+ Before:
22
+
23
+ YAML.load ActiveSupport::SafeBuffer.new("Hello").to_yaml # => "Hello"
24
+ YAML.load ActiveSupport::SafeBuffer.new("true").to_yaml # => true
25
+ YAML.load ActiveSupport::SafeBuffer.new("false").to_yaml # => false
26
+ YAML.load ActiveSupport::SafeBuffer.new("1").to_yaml # => 1
27
+ YAML.load ActiveSupport::SafeBuffer.new("1.1").to_yaml # => 1.1
28
+
29
+ After:
30
+
31
+ YAML.load ActiveSupport::SafeBuffer.new("Hello").to_yaml # => "Hello"
32
+ YAML.load ActiveSupport::SafeBuffer.new("true").to_yaml # => "true"
33
+ YAML.load ActiveSupport::SafeBuffer.new("false").to_yaml # => "false"
34
+ YAML.load ActiveSupport::SafeBuffer.new("1").to_yaml # => "1"
35
+ YAML.load ActiveSupport::SafeBuffer.new("1.1").to_yaml # => "1.1"
36
+
37
+ *Godfrey Chan*
38
+
39
+ * Replace fixed `:en` with `I18n.default_locale` in `Duration#inspect`.
40
+
41
+ *Dominik Masur*
42
+
43
+ * Add missing time zone definitions for Russian Federation and sync them
44
+ with `zone.tab` file from tzdata version 2014j (latest).
45
+
46
+ *Andrey Novikov*
47
+
48
+
49
+ ## Rails 4.1.9 (January 6, 2015) ##
50
+
51
+ * No changes.
52
+
53
+
54
+ ## Rails 4.1.8 (November 16, 2014) ##
55
+
56
+ * `Method` objects now report themselves as not `duplicable?`. This allows
57
+ hashes and arrays containing `Method` objects to be `deep_dup`ed.
58
+
59
+ *Peter Jaros*
60
+
61
+
62
+ ## Rails 4.1.7.1 (November 19, 2014) ##
63
+
64
+ * No changes.
65
+
66
+
67
+ ## Rails 4.1.7 (October 29, 2014) ##
68
+
69
+ * No changes.
70
+
71
+
72
+ ## Rails 4.1.6 (September 11, 2014) ##
73
+
74
+ * Fix DateTime comparison with DateTime::Infinity object.
75
+
76
+ *Rafael Mendonça França*
77
+
78
+ * Fixed a compatibility issue with the `Oj` gem when cherry-picking the file
79
+ `active_support/core_ext/object/json` without requiring `active_support/json`.
80
+
81
+ Fixes #16131.
82
+
83
+ *Godfrey Chan*
84
+
85
+ * Make Dependencies pass a name to NameError error.
86
+
87
+ *arthurnn*, *Yuki Nishijima*
88
+
89
+ * Fixed precision error in NumberHelper when using Rationals.
90
+
91
+ before:
92
+ ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
93
+ #=> "330.00"
94
+ after:
95
+ ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
96
+ #=> "333.33"
97
+
98
+ See #15379.
99
+
100
+ *Juanjo Bazán*
101
+
102
+
103
+ ## Rails 4.1.5 (August 18, 2014) ##
104
+
105
+ * No changes.
106
+
107
+
108
+ ## Rails 4.1.4 (July 2, 2014) ##
109
+
110
+ * No changes.
111
+
112
+
113
+ ## Rails 4.1.3 (July 2, 2014) ##
114
+
115
+ * No changes.
116
+
117
+
118
+ ## Rails 4.1.2 (June 26, 2014) ##
119
+
120
+ * `Hash#deep_transform_keys` and `Hash#deep_transform_keys!` now transform hashes
121
+ in nested arrays. This change also applies to `Hash#deep_stringify_keys`,
122
+ `Hash#deep_stringify_keys!`, `Hash#deep_symbolize_keys` and
123
+ `Hash#deep_symbolize_keys!`.
124
+
125
+ *OZAWA Sakuro*
126
+
127
+ * Fixed `ActiveSupport::Subscriber` so that no duplicate subscriber is created
128
+ when a subscriber method is redefined.
129
+
130
+ *Dennis Schön*
131
+
132
+ * Fixed an issue when using
133
+ `ActiveSupport::NumberHelper::NumberToDelimitedConverter` to
134
+ convert a value that is an `ActiveSupport::SafeBuffer` introduced
135
+ in 2da9d67.
136
+
137
+ For more info see #15064.
138
+
139
+ *Mark J. Titorenko*
140
+
141
+ * Fixed backward compatibility isues introduced in 326e652.
142
+
143
+ Empty Hash or Array should not present in serialization result.
144
+
145
+ {a: []}.to_query # => ""
146
+ {a: {}}.to_query # => ""
147
+
148
+ For more info see #14948.
149
+
150
+ *Bogdan Gusiev*
151
+ * Fixed `ActiveSupport::Duration#eql?` so that `1.second.eql?(1.second)` is
152
+ true.
153
+
154
+ This fixes the current situation of:
155
+
156
+ 1.second.eql?(1.second) #=> false
157
+
158
+ `eql?` also requires that the other object is an `ActiveSupport::Duration`.
159
+ This requirement makes `ActiveSupport::Duration`'s behavior consistent with
160
+ the behavior of Ruby's numeric types:
161
+
162
+ 1.eql?(1.0) #=> false
163
+ 1.0.eql?(1) #=> false
164
+
165
+ 1.second.eql?(1) #=> false (was true)
166
+ 1.eql?(1.second) #=> false
167
+
168
+ { 1 => "foo", 1.0 => "bar" }
169
+ #=> { 1 => "foo", 1.0 => "bar" }
170
+
171
+ { 1 => "foo", 1.second => "bar" }
172
+ # now => { 1 => "foo", 1.second => "bar" }
173
+ # was => { 1 => "bar" }
174
+
175
+ And though the behavior of these hasn't changed, for reference:
176
+
177
+ 1 == 1.0 #=> true
178
+ 1.0 == 1 #=> true
179
+
180
+ 1 == 1.second #=> true
181
+ 1.second == 1 #=> true
182
+
183
+ *Emily Dobervich*
184
+
185
+ * `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies
186
+ instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is
187
+ deprecated.
188
+
189
+ *Pavel Pravosud*
190
+
191
+ * `HashWithIndifferentAccess` better respects `#to_hash` on objects it's
192
+ given. In particular `#update`, `#merge`, `#replace` all accept objects
193
+ which respond to `#to_hash`, even if those objects are not Hashes directly.
194
+
195
+ Currently, if `HashWithIndifferentAccess.new` is given a non-Hash (even if
196
+ it responds to `#to_hash`) that object is treated as the default value,
197
+ rather than the initial keys and value. Changing that could break existing
198
+ code, so it will be updated in the next minor version.
199
+
200
+ *Peter Jaros*
201
+
202
+
203
+ ## Rails 4.1.1 (May 6, 2014) ##
204
+
205
+ * No changes.
206
+
207
+
208
+ ## Rails 4.1.0 (April 8, 2014) ##
209
+
1
210
  * Added `Object#presence_in` to simplify value whitelisting.
2
211
 
3
212
  Before:
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext/object/duplicable'
2
2
  require 'active_support/core_ext/string/inflections'
3
+ require 'active_support/per_thread_registry'
3
4
 
4
5
  module ActiveSupport
5
6
  module Cache
@@ -624,7 +624,7 @@ module ActiveSupport
624
624
  # Check if the entry is expired. The +expires_in+ parameter can override
625
625
  # the value set when the entry was created.
626
626
  def expired?
627
- convert_version_4beta1_entry! if defined?(@value)
627
+ convert_version_4beta1_entry! if defined?(@v)
628
628
  @expires_in && @created_at + @expires_in <= Time.now.to_f
629
629
  end
630
630
 
@@ -117,24 +117,24 @@ module ActiveSupport
117
117
  ENDING = End.new
118
118
 
119
119
  class Before
120
- def self.build(next_callback, user_callback, user_conditions, chain_config, filter)
120
+ def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
121
121
  halted_lambda = chain_config[:terminator]
122
122
 
123
123
  if chain_config.key?(:terminator) && user_conditions.any?
124
- halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
124
+ halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
125
125
  elsif chain_config.key? :terminator
126
- halting(next_callback, user_callback, halted_lambda, filter)
126
+ halting(callback_sequence, user_callback, halted_lambda, filter)
127
127
  elsif user_conditions.any?
128
- conditional(next_callback, user_callback, user_conditions)
128
+ conditional(callback_sequence, user_callback, user_conditions)
129
129
  else
130
- simple next_callback, user_callback
130
+ simple callback_sequence, user_callback
131
131
  end
132
132
  end
133
133
 
134
134
  private
135
135
 
136
- def self.halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
137
- lambda { |env|
136
+ def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
137
+ callback_sequence.before do |env|
138
138
  target = env.target
139
139
  value = env.value
140
140
  halted = env.halted
@@ -146,12 +146,13 @@ module ActiveSupport
146
146
  target.send :halted_callback_hook, filter
147
147
  end
148
148
  end
149
- next_callback.call env
150
- }
149
+
150
+ env
151
+ end
151
152
  end
152
153
 
153
- def self.halting(next_callback, user_callback, halted_lambda, filter)
154
- lambda { |env|
154
+ def self.halting(callback_sequence, user_callback, halted_lambda, filter)
155
+ callback_sequence.before do |env|
155
156
  target = env.target
156
157
  value = env.value
157
158
  halted = env.halted
@@ -163,56 +164,58 @@ module ActiveSupport
163
164
  target.send :halted_callback_hook, filter
164
165
  end
165
166
  end
166
- next_callback.call env
167
- }
167
+
168
+ env
169
+ end
168
170
  end
169
171
 
170
- def self.conditional(next_callback, user_callback, user_conditions)
171
- lambda { |env|
172
+ def self.conditional(callback_sequence, user_callback, user_conditions)
173
+ callback_sequence.before do |env|
172
174
  target = env.target
173
175
  value = env.value
174
176
 
175
177
  if user_conditions.all? { |c| c.call(target, value) }
176
178
  user_callback.call target, value
177
179
  end
178
- next_callback.call env
179
- }
180
+
181
+ env
182
+ end
180
183
  end
181
184
 
182
- def self.simple(next_callback, user_callback)
183
- lambda { |env|
185
+ def self.simple(callback_sequence, user_callback)
186
+ callback_sequence.before do |env|
184
187
  user_callback.call env.target, env.value
185
- next_callback.call env
186
- }
188
+
189
+ env
190
+ end
187
191
  end
188
192
  end
189
193
 
190
194
  class After
191
- def self.build(next_callback, user_callback, user_conditions, chain_config)
195
+ def self.build(callback_sequence, user_callback, user_conditions, chain_config)
192
196
  if chain_config[:skip_after_callbacks_if_terminated]
193
197
  if chain_config.key?(:terminator) && user_conditions.any?
194
- halting_and_conditional(next_callback, user_callback, user_conditions)
198
+ halting_and_conditional(callback_sequence, user_callback, user_conditions)
195
199
  elsif chain_config.key?(:terminator)
196
- halting(next_callback, user_callback)
200
+ halting(callback_sequence, user_callback)
197
201
  elsif user_conditions.any?
198
- conditional next_callback, user_callback, user_conditions
202
+ conditional callback_sequence, user_callback, user_conditions
199
203
  else
200
- simple next_callback, user_callback
204
+ simple callback_sequence, user_callback
201
205
  end
202
206
  else
203
207
  if user_conditions.any?
204
- conditional next_callback, user_callback, user_conditions
208
+ conditional callback_sequence, user_callback, user_conditions
205
209
  else
206
- simple next_callback, user_callback
210
+ simple callback_sequence, user_callback
207
211
  end
208
212
  end
209
213
  end
210
214
 
211
215
  private
212
216
 
213
- def self.halting_and_conditional(next_callback, user_callback, user_conditions)
214
- lambda { |env|
215
- env = next_callback.call env
217
+ def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
218
+ callback_sequence.after do |env|
216
219
  target = env.target
217
220
  value = env.value
218
221
  halted = env.halted
@@ -220,117 +223,119 @@ module ActiveSupport
220
223
  if !halted && user_conditions.all? { |c| c.call(target, value) }
221
224
  user_callback.call target, value
222
225
  end
226
+
223
227
  env
224
- }
228
+ end
225
229
  end
226
230
 
227
- def self.halting(next_callback, user_callback)
228
- lambda { |env|
229
- env = next_callback.call env
231
+ def self.halting(callback_sequence, user_callback)
232
+ callback_sequence.after do |env|
230
233
  unless env.halted
231
234
  user_callback.call env.target, env.value
232
235
  end
236
+
233
237
  env
234
- }
238
+ end
235
239
  end
236
240
 
237
- def self.conditional(next_callback, user_callback, user_conditions)
238
- lambda { |env|
239
- env = next_callback.call env
241
+ def self.conditional(callback_sequence, user_callback, user_conditions)
242
+ callback_sequence.after do |env|
240
243
  target = env.target
241
244
  value = env.value
242
245
 
243
246
  if user_conditions.all? { |c| c.call(target, value) }
244
247
  user_callback.call target, value
245
248
  end
249
+
246
250
  env
247
- }
251
+ end
248
252
  end
249
253
 
250
- def self.simple(next_callback, user_callback)
251
- lambda { |env|
252
- env = next_callback.call env
254
+ def self.simple(callback_sequence, user_callback)
255
+ callback_sequence.after do |env|
253
256
  user_callback.call env.target, env.value
257
+
254
258
  env
255
- }
259
+ end
256
260
  end
257
261
  end
258
262
 
259
263
  class Around
260
- def self.build(next_callback, user_callback, user_conditions, chain_config)
264
+ def self.build(callback_sequence, user_callback, user_conditions, chain_config)
261
265
  if chain_config.key?(:terminator) && user_conditions.any?
262
- halting_and_conditional(next_callback, user_callback, user_conditions)
266
+ halting_and_conditional(callback_sequence, user_callback, user_conditions)
263
267
  elsif chain_config.key? :terminator
264
- halting(next_callback, user_callback)
268
+ halting(callback_sequence, user_callback)
265
269
  elsif user_conditions.any?
266
- conditional(next_callback, user_callback, user_conditions)
270
+ conditional(callback_sequence, user_callback, user_conditions)
267
271
  else
268
- simple(next_callback, user_callback)
272
+ simple(callback_sequence, user_callback)
269
273
  end
270
274
  end
271
275
 
272
276
  private
273
277
 
274
- def self.halting_and_conditional(next_callback, user_callback, user_conditions)
275
- lambda { |env|
278
+ def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
279
+ callback_sequence.around do |env, &run|
276
280
  target = env.target
277
281
  value = env.value
278
282
  halted = env.halted
279
283
 
280
284
  if !halted && user_conditions.all? { |c| c.call(target, value) }
281
285
  user_callback.call(target, value) {
282
- env = next_callback.call env
286
+ env = run.call env
283
287
  env.value
284
288
  }
289
+
285
290
  env
286
291
  else
287
- next_callback.call env
292
+ run.call env
288
293
  end
289
- }
294
+ end
290
295
  end
291
296
 
292
- def self.halting(next_callback, user_callback)
293
- lambda { |env|
297
+ def self.halting(callback_sequence, user_callback)
298
+ callback_sequence.around do |env, &run|
294
299
  target = env.target
295
300
  value = env.value
296
301
 
297
- unless env.halted
302
+ if env.halted
303
+ run.call env
304
+ else
298
305
  user_callback.call(target, value) {
299
- env = next_callback.call env
306
+ env = run.call env
300
307
  env.value
301
308
  }
302
309
  env
303
- else
304
- next_callback.call env
305
310
  end
306
- }
311
+ end
307
312
  end
308
313
 
309
- def self.conditional(next_callback, user_callback, user_conditions)
310
- lambda { |env|
314
+ def self.conditional(callback_sequence, user_callback, user_conditions)
315
+ callback_sequence.around do |env, &run|
311
316
  target = env.target
312
317
  value = env.value
313
318
 
314
319
  if user_conditions.all? { |c| c.call(target, value) }
315
320
  user_callback.call(target, value) {
316
- env = next_callback.call env
321
+ env = run.call env
317
322
  env.value
318
323
  }
319
324
  env
320
325
  else
321
- next_callback.call env
326
+ run.call env
322
327
  end
323
- }
328
+ end
324
329
  end
325
330
 
326
- def self.simple(next_callback, user_callback)
327
- lambda { |env|
331
+ def self.simple(callback_sequence, user_callback)
332
+ callback_sequence.around do |env, &run|
328
333
  user_callback.call(env.target, env.value) {
329
- env = next_callback.call env
334
+ env = run.call env
330
335
  env.value
331
336
  }
332
337
  env
333
- }
338
+ end
334
339
  end
335
340
  end
336
341
  end
@@ -382,17 +387,17 @@ module ActiveSupport
382
387
  end
383
388
 
384
389
  # Wraps code with filter
385
- def apply(next_callback)
390
+ def apply(callback_sequence)
386
391
  user_conditions = conditions_lambdas
387
392
  user_callback = make_lambda @filter
388
393
 
389
394
  case kind
390
395
  when :before
391
- Filters::Before.build(next_callback, user_callback, user_conditions, chain_config, @filter)
396
+ Filters::Before.build(callback_sequence, user_callback, user_conditions, chain_config, @filter)
392
397
  when :after
393
- Filters::After.build(next_callback, user_callback, user_conditions, chain_config)
398
+ Filters::After.build(callback_sequence, user_callback, user_conditions, chain_config)
394
399
  when :around
395
- Filters::Around.build(next_callback, user_callback, user_conditions, chain_config)
400
+ Filters::Around.build(callback_sequence, user_callback, user_conditions, chain_config)
396
401
  end
397
402
  end
398
403
 
@@ -464,6 +469,42 @@ module ActiveSupport
464
469
  end
465
470
  end
466
471
 
472
+ # Execute before and after filters in a sequence instead of
473
+ # chaining them with nested lambda calls, see:
474
+ # https://github.com/rails/rails/issues/18011
475
+ class CallbackSequence
476
+ def initialize(&call)
477
+ @call = call
478
+ @before = []
479
+ @after = []
480
+ end
481
+
482
+ def before(&before)
483
+ @before.unshift(before)
484
+ self
485
+ end
486
+
487
+ def after(&after)
488
+ @after.push(after)
489
+ self
490
+ end
491
+
492
+ def around(&around)
493
+ CallbackSequence.new do |*args|
494
+ around.call(*args) {
495
+ self.call(*args)
496
+ }
497
+ end
498
+ end
499
+
500
+ def call(*args)
501
+ @before.each { |b| b.call(*args) }
502
+ value = @call.call(*args)
503
+ @after.each { |a| a.call(*args) }
504
+ value
505
+ end
506
+ end
507
+
467
508
  # An Array with a compile method.
468
509
  class CallbackChain #:nodoc:#
469
510
  include Enumerable
@@ -508,8 +549,9 @@ module ActiveSupport
508
549
 
509
550
  def compile
510
551
  @callbacks || @mutex.synchronize do
511
- @callbacks ||= @chain.reverse.inject(Filters::ENDING) do |chain, callback|
512
- callback.apply chain
552
+ final_sequence = CallbackSequence.new { |env| Filters::ENDING.call(env) }
553
+ @callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
554
+ callback.apply callback_sequence
513
555
  end
514
556
  end
515
557
  end