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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +140 -714
- data/README.rdoc +7 -2
- data/lib/active_support/backtrace_cleaner.rb +4 -4
- data/lib/active_support/cache.rb +18 -20
- data/lib/active_support/cache/file_store.rb +5 -0
- data/lib/active_support/cache/strategy/local_cache.rb +5 -4
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +5 -0
- data/lib/active_support/callbacks.rb +92 -140
- data/lib/active_support/concern.rb +9 -1
- data/lib/active_support/core_ext/array/access.rb +5 -1
- data/lib/active_support/core_ext/array/grouping.rb +5 -0
- data/lib/active_support/core_ext/class/delegating_attributes.rb +4 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +11 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -2
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/hash/conversions.rb +2 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +10 -6
- data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
- data/lib/active_support/core_ext/kernel.rb +3 -2
- data/lib/active_support/core_ext/kernel/concern.rb +10 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +14 -0
- data/lib/active_support/core_ext/load_error.rb +4 -1
- data/lib/active_support/core_ext/module/delegation.rb +13 -25
- data/lib/active_support/core_ext/numeric/time.rb +1 -19
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/object/duplicable.rb +4 -11
- data/lib/active_support/core_ext/object/itself.rb +12 -0
- data/lib/active_support/core_ext/object/json.rb +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +2 -1
- data/lib/active_support/core_ext/object/with_options.rb +15 -2
- data/lib/active_support/core_ext/string/access.rb +4 -4
- data/lib/active_support/core_ext/string/filters.rb +25 -1
- data/lib/active_support/core_ext/string/inflections.rb +3 -1
- data/lib/active_support/core_ext/string/output_safety.rb +29 -19
- data/lib/active_support/core_ext/thread.rb +7 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -1
- data/lib/active_support/core_ext/time/zones.rb +0 -1
- data/lib/active_support/dependencies.rb +5 -4
- data/lib/active_support/duration.rb +2 -3
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +13 -5
- data/lib/active_support/i18n_railtie.rb +1 -7
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/inflector/methods.rb +39 -15
- data/lib/active_support/json/encoding.rb +0 -4
- data/lib/active_support/logger.rb +0 -14
- data/lib/active_support/logger_silence.rb +3 -24
- data/lib/active_support/message_encryptor.rb +2 -1
- data/lib/active_support/multibyte/unicode.rb +5 -3
- data/lib/active_support/notifications.rb +7 -2
- data/lib/active_support/notifications/fanout.rb +11 -6
- data/lib/active_support/number_helper.rb +7 -8
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -2
- data/lib/active_support/test_case.rb +3 -13
- data/lib/active_support/testing/assertions.rb +1 -1
- data/lib/active_support/testing/declarative.rb +1 -25
- data/lib/active_support/testing/isolation.rb +16 -6
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +5 -1
- data/lib/active_support/time.rb +0 -2
- data/lib/active_support/time_with_zone.rb +14 -3
- data/lib/active_support/values/time_zone.rb +76 -75
- data/lib/active_support/xml_mini.rb +0 -3
- data/lib/active_support/xml_mini/jdom.rb +5 -6
- data/lib/active_support/xml_mini/rexml.rb +5 -6
- metadata +17 -16
- data/lib/active_support/core_ext/object/to_json.rb +0 -5
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/security_utils.rb +0 -27
data/README.rdoc
CHANGED
@@ -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/
|
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
|
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
|
-
#
|
69
|
-
#
|
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!
|
data/lib/active_support/cache.rb
CHANGED
@@ -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
|
-
#
|
182
|
-
# Default is +false+.
|
182
|
+
# :deprecated:
|
183
183
|
def self.instrument=(boolean)
|
184
|
-
|
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
|
-
|
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
|
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
|
-
# # =>
|
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.
|
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
|
-
|
544
|
-
|
545
|
-
|
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
|
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?(@
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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(
|
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(
|
125
|
+
halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
|
125
126
|
elsif chain_config.key? :terminator
|
126
|
-
halting(
|
127
|
+
halting(next_callback, user_callback, halted_lambda, filter)
|
127
128
|
elsif user_conditions.any?
|
128
|
-
conditional(
|
129
|
+
conditional(next_callback, user_callback, user_conditions)
|
129
130
|
else
|
130
|
-
simple
|
131
|
+
simple next_callback, user_callback
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
|
-
|
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
|
-
|
151
|
-
end
|
148
|
+
next_callback.call env
|
149
|
+
}
|
152
150
|
end
|
151
|
+
private_class_method :halting_and_conditional
|
153
152
|
|
154
|
-
def self.halting(
|
155
|
-
|
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
|
-
|
169
|
-
end
|
166
|
+
next_callback.call env
|
167
|
+
}
|
170
168
|
end
|
169
|
+
private_class_method :halting
|
171
170
|
|
172
|
-
def self.conditional(
|
173
|
-
|
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
|
-
|
182
|
-
end
|
179
|
+
next_callback.call env
|
180
|
+
}
|
183
181
|
end
|
182
|
+
private_class_method :conditional
|
184
183
|
|
185
|
-
def self.simple(
|
186
|
-
|
184
|
+
def self.simple(next_callback, user_callback)
|
185
|
+
lambda { |env|
|
187
186
|
user_callback.call env.target, env.value
|
188
|
-
|
189
|
-
|
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(
|
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(
|
197
|
+
halting_and_conditional(next_callback, user_callback, user_conditions)
|
199
198
|
elsif chain_config.key?(:terminator)
|
200
|
-
halting(
|
199
|
+
halting(next_callback, user_callback)
|
201
200
|
elsif user_conditions.any?
|
202
|
-
conditional
|
201
|
+
conditional next_callback, user_callback, user_conditions
|
203
202
|
else
|
204
|
-
simple
|
203
|
+
simple next_callback, user_callback
|
205
204
|
end
|
206
205
|
else
|
207
206
|
if user_conditions.any?
|
208
|
-
conditional
|
207
|
+
conditional next_callback, user_callback, user_conditions
|
209
208
|
else
|
210
|
-
simple
|
209
|
+
simple next_callback, user_callback
|
211
210
|
end
|
212
211
|
end
|
213
212
|
end
|
214
213
|
|
215
|
-
|
216
|
-
|
217
|
-
|
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
|
-
|
225
|
+
}
|
229
226
|
end
|
227
|
+
private_class_method :halting_and_conditional
|
230
228
|
|
231
|
-
def self.halting(
|
232
|
-
|
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
|
-
|
236
|
+
}
|
239
237
|
end
|
238
|
+
private_class_method :halting
|
240
239
|
|
241
|
-
def self.conditional(
|
242
|
-
|
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
|
-
|
250
|
+
}
|
252
251
|
end
|
252
|
+
private_class_method :conditional
|
253
253
|
|
254
|
-
def self.simple(
|
255
|
-
|
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
|
-
|
259
|
+
}
|
260
260
|
end
|
261
|
+
private_class_method :simple
|
261
262
|
end
|
262
263
|
|
263
264
|
class Around
|
264
|
-
def self.build(
|
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(
|
267
|
+
halting_and_conditional(next_callback, user_callback, user_conditions)
|
267
268
|
elsif chain_config.key? :terminator
|
268
|
-
halting(
|
269
|
+
halting(next_callback, user_callback)
|
269
270
|
elsif user_conditions.any?
|
270
|
-
conditional(
|
271
|
+
conditional(next_callback, user_callback, user_conditions)
|
271
272
|
else
|
272
|
-
simple(
|
273
|
+
simple(next_callback, user_callback)
|
273
274
|
end
|
274
275
|
end
|
275
276
|
|
276
|
-
|
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 =
|
285
|
+
env = next_callback.call env
|
287
286
|
env.value
|
288
287
|
}
|
289
|
-
|
290
288
|
env
|
291
289
|
else
|
292
|
-
|
290
|
+
next_callback.call env
|
293
291
|
end
|
294
|
-
|
292
|
+
}
|
295
293
|
end
|
294
|
+
private_class_method :halting_and_conditional
|
296
295
|
|
297
|
-
def self.halting(
|
298
|
-
|
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
|
-
|
302
|
+
next_callback.call env
|
304
303
|
else
|
305
304
|
user_callback.call(target, value) {
|
306
|
-
env =
|
305
|
+
env = next_callback.call env
|
307
306
|
env.value
|
308
307
|
}
|
309
308
|
env
|
310
309
|
end
|
311
|
-
|
310
|
+
}
|
312
311
|
end
|
312
|
+
private_class_method :halting
|
313
313
|
|
314
|
-
def self.conditional(
|
315
|
-
|
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 =
|
321
|
+
env = next_callback.call env
|
322
322
|
env.value
|
323
323
|
}
|
324
324
|
env
|
325
325
|
else
|
326
|
-
|
326
|
+
next_callback.call env
|
327
327
|
end
|
328
|
-
|
328
|
+
}
|
329
329
|
end
|
330
|
+
private_class_method :conditional
|
330
331
|
|
331
|
-
def self.simple(
|
332
|
-
|
332
|
+
def self.simple(next_callback, user_callback)
|
333
|
+
lambda { |env|
|
333
334
|
user_callback.call(env.target, env.value) {
|
334
|
-
env =
|
335
|
+
env = next_callback.call env
|
335
336
|
env.value
|
336
337
|
}
|
337
338
|
env
|
338
|
-
|
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(
|
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(
|
398
|
+
Filters::Before.build(next_callback, user_callback, user_conditions, chain_config, @filter)
|
397
399
|
when :after
|
398
|
-
Filters::After.build(
|
400
|
+
Filters::After.build(next_callback, user_callback, user_conditions, chain_config)
|
399
401
|
when :around
|
400
|
-
Filters::Around.build(
|
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
|
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
|
-
|
553
|
-
|
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,
|
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"
|
723
|
+
class_attribute "_#{name}_callbacks"
|
772
724
|
set_callbacks name, CallbackChain.new(name, options)
|
773
725
|
end
|
774
726
|
end
|