activesupport 4.1.16 → 4.2.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -714
  3. data/README.rdoc +7 -2
  4. data/lib/active_support/backtrace_cleaner.rb +4 -4
  5. data/lib/active_support/cache.rb +18 -20
  6. data/lib/active_support/cache/file_store.rb +5 -0
  7. data/lib/active_support/cache/strategy/local_cache.rb +5 -4
  8. data/lib/active_support/cache/strategy/local_cache_middleware.rb +5 -0
  9. data/lib/active_support/callbacks.rb +92 -140
  10. data/lib/active_support/concern.rb +9 -1
  11. data/lib/active_support/core_ext/array/access.rb +5 -1
  12. data/lib/active_support/core_ext/array/grouping.rb +5 -0
  13. data/lib/active_support/core_ext/class/delegating_attributes.rb +4 -0
  14. data/lib/active_support/core_ext/date_time/calculations.rb +11 -1
  15. data/lib/active_support/core_ext/date_time/conversions.rb +2 -2
  16. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  17. data/lib/active_support/core_ext/hash.rb +1 -0
  18. data/lib/active_support/core_ext/hash/conversions.rb +2 -3
  19. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  20. data/lib/active_support/core_ext/hash/keys.rb +10 -6
  21. data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
  22. data/lib/active_support/core_ext/kernel.rb +3 -2
  23. data/lib/active_support/core_ext/kernel/concern.rb +10 -0
  24. data/lib/active_support/core_ext/kernel/reporting.rb +14 -0
  25. data/lib/active_support/core_ext/load_error.rb +4 -1
  26. data/lib/active_support/core_ext/module/delegation.rb +13 -25
  27. data/lib/active_support/core_ext/numeric/time.rb +1 -19
  28. data/lib/active_support/core_ext/object.rb +1 -0
  29. data/lib/active_support/core_ext/object/duplicable.rb +4 -11
  30. data/lib/active_support/core_ext/object/itself.rb +12 -0
  31. data/lib/active_support/core_ext/object/json.rb +1 -1
  32. data/lib/active_support/core_ext/object/to_query.rb +2 -1
  33. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  34. data/lib/active_support/core_ext/string/access.rb +4 -4
  35. data/lib/active_support/core_ext/string/filters.rb +25 -1
  36. data/lib/active_support/core_ext/string/inflections.rb +3 -1
  37. data/lib/active_support/core_ext/string/output_safety.rb +29 -19
  38. data/lib/active_support/core_ext/thread.rb +7 -0
  39. data/lib/active_support/core_ext/time/conversions.rb +1 -1
  40. data/lib/active_support/core_ext/time/zones.rb +0 -1
  41. data/lib/active_support/dependencies.rb +5 -4
  42. data/lib/active_support/duration.rb +2 -3
  43. data/lib/active_support/gem_version.rb +3 -3
  44. data/lib/active_support/hash_with_indifferent_access.rb +13 -5
  45. data/lib/active_support/i18n_railtie.rb +1 -7
  46. data/lib/active_support/inflector/inflections.rb +1 -1
  47. data/lib/active_support/inflector/methods.rb +39 -15
  48. data/lib/active_support/json/encoding.rb +0 -4
  49. data/lib/active_support/logger.rb +0 -14
  50. data/lib/active_support/logger_silence.rb +3 -24
  51. data/lib/active_support/message_encryptor.rb +2 -1
  52. data/lib/active_support/multibyte/unicode.rb +5 -3
  53. data/lib/active_support/notifications.rb +7 -2
  54. data/lib/active_support/notifications/fanout.rb +11 -6
  55. data/lib/active_support/number_helper.rb +7 -8
  56. data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -2
  57. data/lib/active_support/test_case.rb +3 -13
  58. data/lib/active_support/testing/assertions.rb +1 -1
  59. data/lib/active_support/testing/declarative.rb +1 -25
  60. data/lib/active_support/testing/isolation.rb +16 -6
  61. data/lib/active_support/testing/tagged_logging.rb +1 -1
  62. data/lib/active_support/testing/time_helpers.rb +5 -1
  63. data/lib/active_support/time.rb +0 -2
  64. data/lib/active_support/time_with_zone.rb +14 -3
  65. data/lib/active_support/values/time_zone.rb +76 -75
  66. data/lib/active_support/xml_mini.rb +0 -3
  67. data/lib/active_support/xml_mini/jdom.rb +5 -6
  68. data/lib/active_support/xml_mini/rexml.rb +5 -6
  69. metadata +17 -16
  70. data/lib/active_support/core_ext/object/to_json.rb +0 -5
  71. data/lib/active_support/file_watcher.rb +0 -36
  72. data/lib/active_support/security_utils.rb +0 -27
@@ -14,7 +14,7 @@ The latest version of Active Support can be installed with RubyGems:
14
14
 
15
15
  Source code can be downloaded as part of the Rails project on GitHub:
16
16
 
17
- * https://github.com/rails/rails/tree/4-1-stable/activesupport
17
+ * https://github.com/rails/rails/tree/master/activesupport
18
18
 
19
19
 
20
20
  == License
@@ -30,6 +30,11 @@ API documentation is at:
30
30
 
31
31
  * http://api.rubyonrails.org
32
32
 
33
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
33
+ Bug reports can be filed for the Ruby on Rails project here:
34
34
 
35
35
  * https://github.com/rails/rails/issues
36
+
37
+ Feature requests should be discussed on the rails-core mailing list here:
38
+
39
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
40
+
@@ -13,7 +13,7 @@ module ActiveSupport
13
13
  # can focus on the rest.
14
14
  #
15
15
  # bc = BacktraceCleaner.new
16
- # bc.add_filter { |line| line.gsub(Rails.root, '') } # strip the Rails.root prefix
16
+ # bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
17
17
  # bc.add_silencer { |line| line =~ /mongrel|rubygems/ } # skip any lines from mongrel or rubygems
18
18
  # bc.clean(exception.backtrace) # perform the cleanup
19
19
  #
@@ -65,14 +65,14 @@ module ActiveSupport
65
65
  @silencers << block
66
66
  end
67
67
 
68
- # Will remove all silencers, but leave in the filters. This is useful if
69
- # your context of debugging suddenly expands as you suspect a bug in one of
68
+ # Removes all silencers, but leaves in the filters. Useful if your
69
+ # context of debugging suddenly expands as you suspect a bug in one of
70
70
  # the libraries you use.
71
71
  def remove_silencers!
72
72
  @silencers = []
73
73
  end
74
74
 
75
- # Removes all filters, but leaves in silencers. Useful if you suddenly
75
+ # Removes all filters, but leaves in the silencers. Useful if you suddenly
76
76
  # need to see entire filepaths in the backtrace that you had already
77
77
  # filtered out.
78
78
  def remove_filters!
@@ -8,6 +8,7 @@ require 'active_support/core_ext/numeric/bytes'
8
8
  require 'active_support/core_ext/numeric/time'
9
9
  require 'active_support/core_ext/object/to_param'
10
10
  require 'active_support/core_ext/string/inflections'
11
+ require 'active_support/deprecation'
11
12
 
12
13
  module ActiveSupport
13
14
  # See ActiveSupport::Cache::Store for documentation.
@@ -178,14 +179,16 @@ module ActiveSupport
178
179
  @silence = previous_silence
179
180
  end
180
181
 
181
- # Set to +true+ if cache stores should be instrumented.
182
- # Default is +false+.
182
+ # :deprecated:
183
183
  def self.instrument=(boolean)
184
- Thread.current[:instrument_cache_store] = boolean
184
+ ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument= is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
185
+ true
185
186
  end
186
187
 
188
+ # :deprecated:
187
189
  def self.instrument
188
- Thread.current[:instrument_cache_store] || false
190
+ ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
191
+ true
189
192
  end
190
193
 
191
194
  # Fetches data from the cache, using the given key. If there is data in
@@ -234,7 +237,7 @@ module ActiveSupport
234
237
  # seconds. Because of extended life of the previous cache, other processes
235
238
  # will continue to use slightly stale data for a just a bit longer. In the
236
239
  # meantime that first process will go ahead and will write into cache the
237
- # new value. After that all the processes will start getting new value.
240
+ # new value. After that all the processes will start getting the new value.
238
241
  # The key is to keep <tt>:race_condition_ttl</tt> small.
239
242
  #
240
243
  # If the process regenerating the entry errors out, the entry will be
@@ -357,20 +360,19 @@ module ActiveSupport
357
360
  #
358
361
  # Options are passed to the underlying cache implementation.
359
362
  #
360
- # Returns an array with the data for each of the names. For example:
363
+ # Returns a hash with the data for each of the names. For example:
361
364
  #
362
365
  # cache.write("bim", "bam")
363
- # cache.fetch_multi("bim", "boom") {|key| key * 2 }
364
- # # => ["bam", "boomboom"]
366
+ # cache.fetch_multi("bim", "boom") { |key| key * 2 }
367
+ # # => { "bam" => "bam", "boom" => "boomboom" }
365
368
  #
366
369
  def fetch_multi(*names)
367
370
  options = names.extract_options!
368
371
  options = merged_options(options)
369
-
370
372
  results = read_multi(*names, options)
371
373
 
372
- names.map do |name|
373
- results.fetch(name) do
374
+ names.each_with_object({}) do |name, memo|
375
+ memo[name] = results.fetch(name) do
374
376
  value = yield name
375
377
  write(name, value, options)
376
378
  value
@@ -540,13 +542,9 @@ module ActiveSupport
540
542
  def instrument(operation, key, options = nil)
541
543
  log(operation, key, options)
542
544
 
543
- if self.class.instrument
544
- payload = { :key => key }
545
- payload.merge!(options) if options.is_a?(Hash)
546
- ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
547
- else
548
- yield(nil)
549
- end
545
+ payload = { :key => key }
546
+ payload.merge!(options) if options.is_a?(Hash)
547
+ ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
550
548
  end
551
549
 
552
550
  def log(operation, key, options = nil)
@@ -564,7 +562,7 @@ module ActiveSupport
564
562
  def handle_expired_entry(entry, key, options)
565
563
  if entry && entry.expired?
566
564
  race_ttl = options[:race_condition_ttl].to_i
567
- if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
565
+ if race_ttl && (Time.now.to_f - entry.expires_at <= race_ttl)
568
566
  # When an entry has :race_condition_ttl defined, put the stale entry back into the cache
569
567
  # for a brief period while the entry is begin recalculated.
570
568
  entry.expires_at = Time.now + race_ttl
@@ -624,7 +622,7 @@ module ActiveSupport
624
622
  # Check if the entry is expired. The +expires_in+ parameter can override
625
623
  # the value set when the entry was created.
626
624
  def expired?
627
- convert_version_4beta1_entry! if defined?(@v)
625
+ convert_version_4beta1_entry! if defined?(@value)
628
626
  @expires_in && @created_at + @expires_in <= Time.now.to_f
629
627
  end
630
628
 
@@ -14,6 +14,7 @@ module ActiveSupport
14
14
 
15
15
  DIR_FORMATTER = "%03X"
16
16
  FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
17
+ FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
17
18
  EXCLUDED_DIRS = ['.', '..'].freeze
18
19
 
19
20
  def initialize(cache_path, options = nil)
@@ -117,6 +118,10 @@ module ActiveSupport
117
118
 
118
119
  # Translate a key into a file path.
119
120
  def key_file_path(key)
121
+ if key.size > FILEPATH_MAX_SIZE
122
+ key = Digest::MD5.hexdigest(key)
123
+ end
124
+
120
125
  fname = URI.encode_www_form_component(key)
121
126
  hash = Zlib.adler32(fname)
122
127
  hash, dir_1 = hash.divmod(0x1000)
@@ -86,13 +86,13 @@ module ActiveSupport
86
86
 
87
87
  def increment(name, amount = 1, options = nil) # :nodoc:
88
88
  value = bypass_local_cache{super}
89
- increment_or_decrement(value, name, amount, options)
89
+ set_cache_value(value, name, amount, options)
90
90
  value
91
91
  end
92
92
 
93
93
  def decrement(name, amount = 1, options = nil) # :nodoc:
94
94
  value = bypass_local_cache{super}
95
- increment_or_decrement(value, name, amount, options)
95
+ set_cache_value(value, name, amount, options)
96
96
  value
97
97
  end
98
98
 
@@ -120,8 +120,7 @@ module ActiveSupport
120
120
  super
121
121
  end
122
122
 
123
- private
124
- def increment_or_decrement(value, name, amount, options)
123
+ def set_cache_value(value, name, amount, options)
125
124
  if local_cache
126
125
  local_cache.mute do
127
126
  if value
@@ -133,6 +132,8 @@ module ActiveSupport
133
132
  end
134
133
  end
135
134
 
135
+ private
136
+
136
137
  def local_cache_key
137
138
  @local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, '_').to_sym
138
139
  end
@@ -1,4 +1,6 @@
1
1
  require 'rack/body_proxy'
2
+ require 'rack/utils'
3
+
2
4
  module ActiveSupport
3
5
  module Cache
4
6
  module Strategy
@@ -28,6 +30,9 @@ module ActiveSupport
28
30
  LocalCacheRegistry.set_cache_for(local_cache_key, nil)
29
31
  end
30
32
  response
33
+ rescue Rack::Utils::InvalidParameterError
34
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil)
35
+ [400, {}, []]
31
36
  rescue Exception
32
37
  LocalCacheRegistry.set_cache_for(local_cache_key, nil)
33
38
  raise
@@ -71,7 +71,8 @@ module ActiveSupport
71
71
  # order.
72
72
  #
73
73
  # If the callback chain was halted, returns +false+. Otherwise returns the
74
- # result of the block, or +true+ if no block is given.
74
+ # result of the block, +nil+ if no callbacks have been set, or +true+
75
+ # if callbacks have been set but no block is given.
75
76
  #
76
77
  # run_callbacks :save do
77
78
  # save
@@ -117,24 +118,22 @@ module ActiveSupport
117
118
  ENDING = End.new
118
119
 
119
120
  class Before
120
- def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
121
+ def self.build(next_callback, user_callback, user_conditions, chain_config, filter)
121
122
  halted_lambda = chain_config[:terminator]
122
123
 
123
124
  if chain_config.key?(:terminator) && user_conditions.any?
124
- halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
125
+ halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
125
126
  elsif chain_config.key? :terminator
126
- halting(callback_sequence, user_callback, halted_lambda, filter)
127
+ halting(next_callback, user_callback, halted_lambda, filter)
127
128
  elsif user_conditions.any?
128
- conditional(callback_sequence, user_callback, user_conditions)
129
+ conditional(next_callback, user_callback, user_conditions)
129
130
  else
130
- simple callback_sequence, user_callback
131
+ simple next_callback, user_callback
131
132
  end
132
133
  end
133
134
 
134
- private
135
-
136
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
137
- callback_sequence.before do |env|
135
+ def self.halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
136
+ lambda { |env|
138
137
  target = env.target
139
138
  value = env.value
140
139
  halted = env.halted
@@ -146,13 +145,13 @@ module ActiveSupport
146
145
  target.send :halted_callback_hook, filter
147
146
  end
148
147
  end
149
-
150
- env
151
- end
148
+ next_callback.call env
149
+ }
152
150
  end
151
+ private_class_method :halting_and_conditional
153
152
 
154
- def self.halting(callback_sequence, user_callback, halted_lambda, filter)
155
- callback_sequence.before do |env|
153
+ def self.halting(next_callback, user_callback, halted_lambda, filter)
154
+ lambda { |env|
156
155
  target = env.target
157
156
  value = env.value
158
157
  halted = env.halted
@@ -164,58 +163,57 @@ module ActiveSupport
164
163
  target.send :halted_callback_hook, filter
165
164
  end
166
165
  end
167
-
168
- env
169
- end
166
+ next_callback.call env
167
+ }
170
168
  end
169
+ private_class_method :halting
171
170
 
172
- def self.conditional(callback_sequence, user_callback, user_conditions)
173
- callback_sequence.before do |env|
171
+ def self.conditional(next_callback, user_callback, user_conditions)
172
+ lambda { |env|
174
173
  target = env.target
175
174
  value = env.value
176
175
 
177
176
  if user_conditions.all? { |c| c.call(target, value) }
178
177
  user_callback.call target, value
179
178
  end
180
-
181
- env
182
- end
179
+ next_callback.call env
180
+ }
183
181
  end
182
+ private_class_method :conditional
184
183
 
185
- def self.simple(callback_sequence, user_callback)
186
- callback_sequence.before do |env|
184
+ def self.simple(next_callback, user_callback)
185
+ lambda { |env|
187
186
  user_callback.call env.target, env.value
188
-
189
- env
190
- end
187
+ next_callback.call env
188
+ }
191
189
  end
190
+ private_class_method :simple
192
191
  end
193
192
 
194
193
  class After
195
- def self.build(callback_sequence, user_callback, user_conditions, chain_config)
194
+ def self.build(next_callback, user_callback, user_conditions, chain_config)
196
195
  if chain_config[:skip_after_callbacks_if_terminated]
197
196
  if chain_config.key?(:terminator) && user_conditions.any?
198
- halting_and_conditional(callback_sequence, user_callback, user_conditions)
197
+ halting_and_conditional(next_callback, user_callback, user_conditions)
199
198
  elsif chain_config.key?(:terminator)
200
- halting(callback_sequence, user_callback)
199
+ halting(next_callback, user_callback)
201
200
  elsif user_conditions.any?
202
- conditional callback_sequence, user_callback, user_conditions
201
+ conditional next_callback, user_callback, user_conditions
203
202
  else
204
- simple callback_sequence, user_callback
203
+ simple next_callback, user_callback
205
204
  end
206
205
  else
207
206
  if user_conditions.any?
208
- conditional callback_sequence, user_callback, user_conditions
207
+ conditional next_callback, user_callback, user_conditions
209
208
  else
210
- simple callback_sequence, user_callback
209
+ simple next_callback, user_callback
211
210
  end
212
211
  end
213
212
  end
214
213
 
215
- private
216
-
217
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
218
- callback_sequence.after do |env|
214
+ def self.halting_and_conditional(next_callback, user_callback, user_conditions)
215
+ lambda { |env|
216
+ env = next_callback.call env
219
217
  target = env.target
220
218
  value = env.value
221
219
  halted = env.halted
@@ -223,120 +221,124 @@ module ActiveSupport
223
221
  if !halted && user_conditions.all? { |c| c.call(target, value) }
224
222
  user_callback.call target, value
225
223
  end
226
-
227
224
  env
228
- end
225
+ }
229
226
  end
227
+ private_class_method :halting_and_conditional
230
228
 
231
- def self.halting(callback_sequence, user_callback)
232
- callback_sequence.after do |env|
229
+ def self.halting(next_callback, user_callback)
230
+ lambda { |env|
231
+ env = next_callback.call env
233
232
  unless env.halted
234
233
  user_callback.call env.target, env.value
235
234
  end
236
-
237
235
  env
238
- end
236
+ }
239
237
  end
238
+ private_class_method :halting
240
239
 
241
- def self.conditional(callback_sequence, user_callback, user_conditions)
242
- callback_sequence.after do |env|
240
+ def self.conditional(next_callback, user_callback, user_conditions)
241
+ lambda { |env|
242
+ env = next_callback.call env
243
243
  target = env.target
244
244
  value = env.value
245
245
 
246
246
  if user_conditions.all? { |c| c.call(target, value) }
247
247
  user_callback.call target, value
248
248
  end
249
-
250
249
  env
251
- end
250
+ }
252
251
  end
252
+ private_class_method :conditional
253
253
 
254
- def self.simple(callback_sequence, user_callback)
255
- callback_sequence.after do |env|
254
+ def self.simple(next_callback, user_callback)
255
+ lambda { |env|
256
+ env = next_callback.call env
256
257
  user_callback.call env.target, env.value
257
-
258
258
  env
259
- end
259
+ }
260
260
  end
261
+ private_class_method :simple
261
262
  end
262
263
 
263
264
  class Around
264
- def self.build(callback_sequence, user_callback, user_conditions, chain_config)
265
+ def self.build(next_callback, user_callback, user_conditions, chain_config)
265
266
  if chain_config.key?(:terminator) && user_conditions.any?
266
- halting_and_conditional(callback_sequence, user_callback, user_conditions)
267
+ halting_and_conditional(next_callback, user_callback, user_conditions)
267
268
  elsif chain_config.key? :terminator
268
- halting(callback_sequence, user_callback)
269
+ halting(next_callback, user_callback)
269
270
  elsif user_conditions.any?
270
- conditional(callback_sequence, user_callback, user_conditions)
271
+ conditional(next_callback, user_callback, user_conditions)
271
272
  else
272
- simple(callback_sequence, user_callback)
273
+ simple(next_callback, user_callback)
273
274
  end
274
275
  end
275
276
 
276
- private
277
-
278
- def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
279
- callback_sequence.around do |env, &run|
277
+ def self.halting_and_conditional(next_callback, user_callback, user_conditions)
278
+ lambda { |env|
280
279
  target = env.target
281
280
  value = env.value
282
281
  halted = env.halted
283
282
 
284
283
  if !halted && user_conditions.all? { |c| c.call(target, value) }
285
284
  user_callback.call(target, value) {
286
- env = run.call env
285
+ env = next_callback.call env
287
286
  env.value
288
287
  }
289
-
290
288
  env
291
289
  else
292
- run.call env
290
+ next_callback.call env
293
291
  end
294
- end
292
+ }
295
293
  end
294
+ private_class_method :halting_and_conditional
296
295
 
297
- def self.halting(callback_sequence, user_callback)
298
- callback_sequence.around do |env, &run|
296
+ def self.halting(next_callback, user_callback)
297
+ lambda { |env|
299
298
  target = env.target
300
299
  value = env.value
301
300
 
302
301
  if env.halted
303
- run.call env
302
+ next_callback.call env
304
303
  else
305
304
  user_callback.call(target, value) {
306
- env = run.call env
305
+ env = next_callback.call env
307
306
  env.value
308
307
  }
309
308
  env
310
309
  end
311
- end
310
+ }
312
311
  end
312
+ private_class_method :halting
313
313
 
314
- def self.conditional(callback_sequence, user_callback, user_conditions)
315
- callback_sequence.around do |env, &run|
314
+ def self.conditional(next_callback, user_callback, user_conditions)
315
+ lambda { |env|
316
316
  target = env.target
317
317
  value = env.value
318
318
 
319
319
  if user_conditions.all? { |c| c.call(target, value) }
320
320
  user_callback.call(target, value) {
321
- env = run.call env
321
+ env = next_callback.call env
322
322
  env.value
323
323
  }
324
324
  env
325
325
  else
326
- run.call env
326
+ next_callback.call env
327
327
  end
328
- end
328
+ }
329
329
  end
330
+ private_class_method :conditional
330
331
 
331
- def self.simple(callback_sequence, user_callback)
332
- callback_sequence.around do |env, &run|
332
+ def self.simple(next_callback, user_callback)
333
+ lambda { |env|
333
334
  user_callback.call(env.target, env.value) {
334
- env = run.call env
335
+ env = next_callback.call env
335
336
  env.value
336
337
  }
337
338
  env
338
- end
339
+ }
339
340
  end
341
+ private_class_method :simple
340
342
  end
341
343
  end
342
344
 
@@ -387,17 +389,17 @@ module ActiveSupport
387
389
  end
388
390
 
389
391
  # Wraps code with filter
390
- def apply(callback_sequence)
392
+ def apply(next_callback)
391
393
  user_conditions = conditions_lambdas
392
394
  user_callback = make_lambda @filter
393
395
 
394
396
  case kind
395
397
  when :before
396
- Filters::Before.build(callback_sequence, user_callback, user_conditions, chain_config, @filter)
398
+ Filters::Before.build(next_callback, user_callback, user_conditions, chain_config, @filter)
397
399
  when :after
398
- Filters::After.build(callback_sequence, user_callback, user_conditions, chain_config)
400
+ Filters::After.build(next_callback, user_callback, user_conditions, chain_config)
399
401
  when :around
400
- Filters::Around.build(callback_sequence, user_callback, user_conditions, chain_config)
402
+ Filters::Around.build(next_callback, user_callback, user_conditions, chain_config)
401
403
  end
402
404
  end
403
405
 
@@ -414,15 +416,8 @@ module ActiveSupport
414
416
  # Procs:: A proc to call with the object.
415
417
  # Objects:: An object with a <tt>before_foo</tt> method on it to call.
416
418
  #
417
- # All of these objects are compiled into methods and handled
418
- # the same after this point:
419
- #
420
- # Symbols:: Already methods.
421
- # Strings:: class_eval'd into methods.
422
- # Procs:: using define_method compiled into methods.
423
- # Objects::
424
- # a method is created that calls the before_foo method
425
- # on the object.
419
+ # All of these objects are converted into a lambda and handled
420
+ # the same after this point.
426
421
  def make_lambda(filter)
427
422
  case filter
428
423
  when Symbol
@@ -469,42 +464,6 @@ module ActiveSupport
469
464
  end
470
465
  end
471
466
 
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
-
508
467
  # An Array with a compile method.
509
468
  class CallbackChain #:nodoc:#
510
469
  include Enumerable
@@ -549,9 +508,8 @@ module ActiveSupport
549
508
 
550
509
  def compile
551
510
  @callbacks || @mutex.synchronize do
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
511
+ @callbacks ||= @chain.reverse.inject(Filters::ENDING) do |chain, callback|
512
+ callback.apply chain
555
513
  end
556
514
  end
557
515
  end
@@ -608,7 +566,7 @@ module ActiveSupport
608
566
  #
609
567
  # set_callback :save, :before, :before_meth
610
568
  # set_callback :save, :after, :after_meth, if: :condition
611
- # set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff }
569
+ # set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
612
570
  #
613
571
  # The second arguments indicates whether the callback is to be run +:before+,
614
572
  # +:after+, or +:around+ the event. If omitted, +:before+ is assumed. This
@@ -760,15 +718,9 @@ module ActiveSupport
760
718
  # would call <tt>Audit#save</tt>.
761
719
  def define_callbacks(*names)
762
720
  options = names.extract_options!
763
- if options.key?(:terminator) && String === options[:terminator]
764
- ActiveSupport::Deprecation.warn "String based terminators are deprecated, please use a lambda"
765
- value = options[:terminator]
766
- line = class_eval "lambda { |result| #{value} }", __FILE__, __LINE__
767
- options[:terminator] = lambda { |target, result| target.instance_exec(result, &line) }
768
- end
769
721
 
770
722
  names.each do |name|
771
- class_attribute "_#{name}_callbacks", instance_writer: false
723
+ class_attribute "_#{name}_callbacks"
772
724
  set_callbacks name, CallbackChain.new(name, options)
773
725
  end
774
726
  end