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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +209 -0
- data/lib/active_support/cache/strategy/local_cache.rb +1 -0
- data/lib/active_support/cache.rb +1 -1
- data/lib/active_support/callbacks.rb +118 -76
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -11
- data/lib/active_support/core_ext/hash/keys.rb +38 -16
- data/lib/active_support/core_ext/object/duplicable.rb +10 -0
- data/lib/active_support/core_ext/object/json.rb +3 -3
- data/lib/active_support/core_ext/object/to_param.rb +1 -62
- data/lib/active_support/core_ext/object/to_query.rb +58 -7
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +7 -3
- data/lib/active_support/core_ext/time/zones.rb +1 -0
- data/lib/active_support/dependencies.rb +4 -4
- data/lib/active_support/duration.rb +5 -1
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +5 -1
- data/lib/active_support/inflector/methods.rb +1 -1
- data/lib/active_support/json/encoding.rb +4 -0
- data/lib/active_support/multibyte/unicode.rb +0 -1
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -6
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/subscriber.rb +10 -1
- data/lib/active_support/values/time_zone.rb +5 -2
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/rexml.rb +6 -5
- data/lib/active_support/xml_mini.rb +3 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54422272f221596ea76d050a34d6b83f1f1ae6c9
|
4
|
+
data.tar.gz: a05f3b1deef3c7cd943ec76a3e5a66b0987b5b93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
data/lib/active_support/cache.rb
CHANGED
@@ -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?(@
|
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(
|
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(
|
124
|
+
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
125
125
|
elsif chain_config.key? :terminator
|
126
|
-
halting(
|
126
|
+
halting(callback_sequence, user_callback, halted_lambda, filter)
|
127
127
|
elsif user_conditions.any?
|
128
|
-
conditional(
|
128
|
+
conditional(callback_sequence, user_callback, user_conditions)
|
129
129
|
else
|
130
|
-
simple
|
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(
|
137
|
-
|
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
|
-
|
150
|
-
|
149
|
+
|
150
|
+
env
|
151
|
+
end
|
151
152
|
end
|
152
153
|
|
153
|
-
def self.halting(
|
154
|
-
|
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
|
-
|
167
|
-
|
167
|
+
|
168
|
+
env
|
169
|
+
end
|
168
170
|
end
|
169
171
|
|
170
|
-
def self.conditional(
|
171
|
-
|
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
|
-
|
179
|
-
|
180
|
+
|
181
|
+
env
|
182
|
+
end
|
180
183
|
end
|
181
184
|
|
182
|
-
def self.simple(
|
183
|
-
|
185
|
+
def self.simple(callback_sequence, user_callback)
|
186
|
+
callback_sequence.before do |env|
|
184
187
|
user_callback.call env.target, env.value
|
185
|
-
|
186
|
-
|
188
|
+
|
189
|
+
env
|
190
|
+
end
|
187
191
|
end
|
188
192
|
end
|
189
193
|
|
190
194
|
class After
|
191
|
-
def self.build(
|
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(
|
198
|
+
halting_and_conditional(callback_sequence, user_callback, user_conditions)
|
195
199
|
elsif chain_config.key?(:terminator)
|
196
|
-
halting(
|
200
|
+
halting(callback_sequence, user_callback)
|
197
201
|
elsif user_conditions.any?
|
198
|
-
conditional
|
202
|
+
conditional callback_sequence, user_callback, user_conditions
|
199
203
|
else
|
200
|
-
simple
|
204
|
+
simple callback_sequence, user_callback
|
201
205
|
end
|
202
206
|
else
|
203
207
|
if user_conditions.any?
|
204
|
-
conditional
|
208
|
+
conditional callback_sequence, user_callback, user_conditions
|
205
209
|
else
|
206
|
-
simple
|
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(
|
214
|
-
|
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(
|
228
|
-
|
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(
|
238
|
-
|
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(
|
251
|
-
|
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(
|
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(
|
266
|
+
halting_and_conditional(callback_sequence, user_callback, user_conditions)
|
263
267
|
elsif chain_config.key? :terminator
|
264
|
-
halting(
|
268
|
+
halting(callback_sequence, user_callback)
|
265
269
|
elsif user_conditions.any?
|
266
|
-
conditional(
|
270
|
+
conditional(callback_sequence, user_callback, user_conditions)
|
267
271
|
else
|
268
|
-
simple(
|
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(
|
275
|
-
|
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 =
|
286
|
+
env = run.call env
|
283
287
|
env.value
|
284
288
|
}
|
289
|
+
|
285
290
|
env
|
286
291
|
else
|
287
|
-
|
292
|
+
run.call env
|
288
293
|
end
|
289
|
-
|
294
|
+
end
|
290
295
|
end
|
291
296
|
|
292
|
-
def self.halting(
|
293
|
-
|
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
|
-
|
302
|
+
if env.halted
|
303
|
+
run.call env
|
304
|
+
else
|
298
305
|
user_callback.call(target, value) {
|
299
|
-
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(
|
310
|
-
|
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 =
|
321
|
+
env = run.call env
|
317
322
|
env.value
|
318
323
|
}
|
319
324
|
env
|
320
325
|
else
|
321
|
-
|
326
|
+
run.call env
|
322
327
|
end
|
323
|
-
|
328
|
+
end
|
324
329
|
end
|
325
330
|
|
326
|
-
def self.simple(
|
327
|
-
|
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 =
|
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(
|
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(
|
396
|
+
Filters::Before.build(callback_sequence, user_callback, user_conditions, chain_config, @filter)
|
392
397
|
when :after
|
393
|
-
Filters::After.build(
|
398
|
+
Filters::After.build(callback_sequence, user_callback, user_conditions, chain_config)
|
394
399
|
when :around
|
395
|
-
Filters::Around.build(
|
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
|
-
|
512
|
-
|
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
|