activesupport 4.2.11.3 → 5.0.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 +5 -5
- data/CHANGELOG.md +309 -485
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/active_support.rb +8 -15
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/cache.rb +59 -72
- data/lib/active_support/cache/file_store.rb +27 -19
- data/lib/active_support/cache/mem_cache_store.rb +71 -60
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/callbacks.rb +107 -111
- data/lib/active_support/concern.rb +1 -1
- data/lib/active_support/concurrency/latch.rb +7 -15
- data/lib/active_support/concurrency/share_lock.rb +142 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +13 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +5 -2
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +3 -3
- data/lib/active_support/core_ext/date_and_time/calculations.rb +93 -27
- data/lib/active_support/core_ext/date_and_time/zones.rb +1 -2
- data/lib/active_support/core_ext/date_time.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +7 -23
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/enumerable.rb +27 -17
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/compact.rb +15 -19
- data/lib/active_support/core_ext/hash/conversions.rb +21 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +22 -18
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +13 -7
- data/lib/active_support/core_ext/integer/time.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +0 -84
- data/lib/active_support/core_ext/load_error.rb +4 -2
- data/lib/active_support/core_ext/marshal.rb +8 -13
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -7
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +7 -14
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +12 -23
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +20 -0
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +11 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +39 -70
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +9 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +67 -21
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +1 -1
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -2
- data/lib/active_support/core_ext/string/inflections.rb +23 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +8 -9
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time.rb +0 -2
- data/lib/active_support/core_ext/time/calculations.rb +18 -16
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +19 -3
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/dependencies.rb +79 -44
- data/lib/active_support/dependencies/interlock.rb +47 -0
- data/lib/active_support/deprecation/behaviors.rb +12 -0
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +13 -2
- data/lib/active_support/duration.rb +5 -8
- data/lib/active_support/evented_file_update_checker.rb +150 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/hash_with_indifferent_access.rb +15 -17
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +87 -89
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +2 -8
- data/lib/active_support/json/encoding.rb +0 -50
- data/lib/active_support/key_generator.rb +4 -4
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/logger.rb +4 -52
- data/lib/active_support/logger_silence.rb +3 -5
- data/lib/active_support/message_encryptor.rb +4 -11
- data/lib/active_support/message_verifier.rb +64 -8
- data/lib/active_support/multibyte/chars.rb +12 -3
- data/lib/active_support/multibyte/unicode.rb +6 -8
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +5 -5
- data/lib/active_support/notifications/instrumenter.rb +19 -2
- data/lib/active_support/number_helper.rb +21 -15
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -4
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +7 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +28 -25
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +3 -0
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/rescuable.rb +4 -4
- data/lib/active_support/security_utils.rb +0 -7
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +3 -1
- data/lib/active_support/test_case.rb +13 -25
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/autorun.rb +8 -1
- data/lib/active_support/testing/composite_filter.rb +54 -0
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +6 -6
- data/lib/active_support/time_with_zone.rb +135 -53
- data/lib/active_support/values/time_zone.rb +80 -46
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini.rb +15 -30
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -3
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -3
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
- data/lib/active_support/xml_mini/rexml.rb +3 -1
- metadata +57 -21
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -15
- data/lib/active_support/core_ext/date_time/compatibility.rb +0 -16
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/compatibility.rb +0 -14
- data/lib/active_support/logger_thread_safe_level.rb +0 -32
@@ -24,9 +24,41 @@ module ActiveSupport
|
|
24
24
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
25
25
|
# an in-memory cache inside of a block.
|
26
26
|
class MemCacheStore < Store
|
27
|
+
# Provide support for raw values in the local cache strategy.
|
28
|
+
module LocalCacheWithRaw # :nodoc:
|
29
|
+
protected
|
30
|
+
def read_entry(key, options)
|
31
|
+
entry = super
|
32
|
+
if options[:raw] && local_cache && entry
|
33
|
+
entry = deserialize_entry(entry.value)
|
34
|
+
end
|
35
|
+
entry
|
36
|
+
end
|
37
|
+
|
38
|
+
def write_entry(key, entry, options) # :nodoc:
|
39
|
+
if options[:raw] && local_cache
|
40
|
+
raw_entry = Entry.new(entry.value.to_s)
|
41
|
+
raw_entry.expires_at = entry.expires_at
|
42
|
+
super(key, raw_entry, options)
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
prepend Strategy::LocalCache
|
50
|
+
prepend LocalCacheWithRaw
|
51
|
+
|
27
52
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
28
53
|
|
29
|
-
|
54
|
+
# Creates a new Dalli::Client instance with specified addresses and options.
|
55
|
+
# By default address is equal localhost:11211.
|
56
|
+
#
|
57
|
+
# ActiveSupport::Cache::MemCacheStore.build_mem_cache
|
58
|
+
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["localhost:11211"], @options={}, @ring=nil>
|
59
|
+
# ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
|
60
|
+
# # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
|
61
|
+
def self.build_mem_cache(*addresses) # :nodoc:
|
30
62
|
addresses = addresses.flatten
|
31
63
|
options = addresses.extract_options!
|
32
64
|
addresses = ["localhost:11211"] if addresses.empty?
|
@@ -56,9 +88,6 @@ module ActiveSupport
|
|
56
88
|
UNIVERSAL_OPTIONS.each{|name| mem_cache_options.delete(name)}
|
57
89
|
@data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
|
58
90
|
end
|
59
|
-
|
60
|
-
extend Strategy::LocalCache
|
61
|
-
extend LocalCacheWithRaw
|
62
91
|
end
|
63
92
|
|
64
93
|
# Reads multiple values from the cache using a single call to the
|
@@ -66,14 +95,17 @@ module ActiveSupport
|
|
66
95
|
def read_multi(*names)
|
67
96
|
options = names.extract_options!
|
68
97
|
options = merged_options(options)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
98
|
+
|
99
|
+
instrument_multi(:read, names, options) do
|
100
|
+
keys_to_names = Hash[names.map{|name| [normalize_key(name, options), name]}]
|
101
|
+
raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
|
102
|
+
values = {}
|
103
|
+
raw_values.each do |key, value|
|
104
|
+
entry = deserialize_entry(value)
|
105
|
+
values[keys_to_names[key]] = entry.value unless entry.expired?
|
106
|
+
end
|
107
|
+
values
|
75
108
|
end
|
76
|
-
values
|
77
109
|
end
|
78
110
|
|
79
111
|
# Increment a cached value. This method uses the memcached incr atomic
|
@@ -83,11 +115,10 @@ module ActiveSupport
|
|
83
115
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
84
116
|
options = merged_options(options)
|
85
117
|
instrument(:increment, name, :amount => amount) do
|
86
|
-
|
118
|
+
rescue_error_with nil do
|
119
|
+
@data.incr(normalize_key(name, options), amount)
|
120
|
+
end
|
87
121
|
end
|
88
|
-
rescue Dalli::DalliError => e
|
89
|
-
logger.error("DalliError (#{e}): #{e.message}") if logger
|
90
|
-
nil
|
91
122
|
end
|
92
123
|
|
93
124
|
# Decrement a cached value. This method uses the memcached decr atomic
|
@@ -97,20 +128,16 @@ module ActiveSupport
|
|
97
128
|
def decrement(name, amount = 1, options = nil) # :nodoc:
|
98
129
|
options = merged_options(options)
|
99
130
|
instrument(:decrement, name, :amount => amount) do
|
100
|
-
|
131
|
+
rescue_error_with nil do
|
132
|
+
@data.decr(normalize_key(name, options), amount)
|
133
|
+
end
|
101
134
|
end
|
102
|
-
rescue Dalli::DalliError => e
|
103
|
-
logger.error("DalliError (#{e}): #{e.message}") if logger
|
104
|
-
nil
|
105
135
|
end
|
106
136
|
|
107
137
|
# Clear the entire cache on all memcached servers. This method should
|
108
138
|
# be used with care when shared cache is being used.
|
109
139
|
def clear(options = nil)
|
110
|
-
@data.flush_all
|
111
|
-
rescue Dalli::DalliError => e
|
112
|
-
logger.error("DalliError (#{e}): #{e.message}") if logger
|
113
|
-
nil
|
140
|
+
rescue_error_with(nil) { @data.flush_all }
|
114
141
|
end
|
115
142
|
|
116
143
|
# Get the statistics from the memcached servers.
|
@@ -121,10 +148,7 @@ module ActiveSupport
|
|
121
148
|
protected
|
122
149
|
# Read an entry from the cache.
|
123
150
|
def read_entry(key, options) # :nodoc:
|
124
|
-
deserialize_entry(@data.get(
|
125
|
-
rescue Dalli::DalliError => e
|
126
|
-
logger.error("DalliError (#{e}): #{e.message}") if logger
|
127
|
-
nil
|
151
|
+
rescue_error_with(nil) { deserialize_entry(@data.get(key, options)) }
|
128
152
|
end
|
129
153
|
|
130
154
|
# Write an entry to the cache.
|
@@ -136,18 +160,14 @@ module ActiveSupport
|
|
136
160
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
137
161
|
expires_in += 5.minutes
|
138
162
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
false
|
163
|
+
rescue_error_with false do
|
164
|
+
@data.send(method, key, value, expires_in, options)
|
165
|
+
end
|
143
166
|
end
|
144
167
|
|
145
168
|
# Delete an entry from the cache.
|
146
169
|
def delete_entry(key, options) # :nodoc:
|
147
|
-
@data.delete(
|
148
|
-
rescue Dalli::DalliError => e
|
149
|
-
logger.error("DalliError (#{e}): #{e.message}") if logger
|
150
|
-
false
|
170
|
+
rescue_error_with(false) { @data.delete(key) }
|
151
171
|
end
|
152
172
|
|
153
173
|
private
|
@@ -155,44 +175,35 @@ module ActiveSupport
|
|
155
175
|
# Memcache keys are binaries. So we need to force their encoding to binary
|
156
176
|
# before applying the regular expression to ensure we are escaping all
|
157
177
|
# characters properly.
|
158
|
-
def
|
159
|
-
key =
|
178
|
+
def normalize_key(key, options)
|
179
|
+
key = super.dup
|
160
180
|
key = key.force_encoding(Encoding::ASCII_8BIT)
|
161
181
|
key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
162
182
|
key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
|
163
183
|
key
|
164
184
|
end
|
165
185
|
|
186
|
+
def escape_key(key)
|
187
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
188
|
+
`escape_key` is deprecated and will be removed from Rails 5.1.
|
189
|
+
Please use `normalize_key` which will return a fully resolved key or nothing.
|
190
|
+
MESSAGE
|
191
|
+
key
|
192
|
+
end
|
193
|
+
|
166
194
|
def deserialize_entry(raw_value)
|
167
195
|
if raw_value
|
168
196
|
entry = Marshal.load(raw_value) rescue raw_value
|
169
197
|
entry.is_a?(Entry) ? entry : Entry.new(entry)
|
170
|
-
else
|
171
|
-
nil
|
172
198
|
end
|
173
199
|
end
|
174
200
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
entry = deserialize_entry(entry.value)
|
182
|
-
end
|
183
|
-
entry
|
184
|
-
end
|
185
|
-
|
186
|
-
def write_entry(key, entry, options) # :nodoc:
|
187
|
-
retval = super
|
188
|
-
if options[:raw] && local_cache && retval
|
189
|
-
raw_entry = Entry.new(entry.value.to_s)
|
190
|
-
raw_entry.expires_at = entry.expires_at
|
191
|
-
local_cache.write_entry(key, raw_entry, options)
|
192
|
-
end
|
193
|
-
retval
|
194
|
-
end
|
195
|
-
end
|
201
|
+
def rescue_error_with(fallback)
|
202
|
+
yield
|
203
|
+
rescue Dalli::DalliError => e
|
204
|
+
logger.error("DalliError (#{e}): #{e.message}") if logger
|
205
|
+
fallback
|
206
|
+
end
|
196
207
|
end
|
197
208
|
end
|
198
209
|
end
|
@@ -75,30 +75,12 @@ module ActiveSupport
|
|
75
75
|
|
76
76
|
# Increment an integer value in the cache.
|
77
77
|
def increment(name, amount = 1, options = nil)
|
78
|
-
|
79
|
-
options = merged_options(options)
|
80
|
-
if num = read(name, options)
|
81
|
-
num = num.to_i + amount
|
82
|
-
write(name, num, options)
|
83
|
-
num
|
84
|
-
else
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
end
|
78
|
+
modify_value(name, amount, options)
|
88
79
|
end
|
89
80
|
|
90
81
|
# Decrement an integer value in the cache.
|
91
82
|
def decrement(name, amount = 1, options = nil)
|
92
|
-
|
93
|
-
options = merged_options(options)
|
94
|
-
if num = read(name, options)
|
95
|
-
num = num.to_i - amount
|
96
|
-
write(name, num, options)
|
97
|
-
num
|
98
|
-
else
|
99
|
-
nil
|
100
|
-
end
|
101
|
-
end
|
83
|
+
modify_value(name, -amount, options)
|
102
84
|
end
|
103
85
|
|
104
86
|
def delete_matched(matcher, options = nil)
|
@@ -126,7 +108,7 @@ module ActiveSupport
|
|
126
108
|
|
127
109
|
PER_ENTRY_OVERHEAD = 240
|
128
110
|
|
129
|
-
def cached_size(key, entry)
|
111
|
+
def cached_size(key, entry) # :nodoc:
|
130
112
|
key.to_s.bytesize + entry.size + PER_ENTRY_OVERHEAD
|
131
113
|
end
|
132
114
|
|
@@ -167,6 +149,19 @@ module ActiveSupport
|
|
167
149
|
!!entry
|
168
150
|
end
|
169
151
|
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def modify_value(name, amount, options)
|
156
|
+
synchronize do
|
157
|
+
options = merged_options(options)
|
158
|
+
if num = read(name, options)
|
159
|
+
num = num.to_i + amount
|
160
|
+
write(name, num, options)
|
161
|
+
num
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
170
165
|
end
|
171
166
|
end
|
172
167
|
end
|
@@ -8,10 +8,7 @@ module ActiveSupport
|
|
8
8
|
# be cached inside blocks that utilize this strategy. See
|
9
9
|
# ActiveSupport::Cache::Strategy::LocalCache for more details.
|
10
10
|
class NullStore < Store
|
11
|
-
|
12
|
-
super(options)
|
13
|
-
extend Strategy::LocalCache
|
14
|
-
end
|
11
|
+
prepend Strategy::LocalCache
|
15
12
|
|
16
13
|
def clear(options = nil)
|
17
14
|
end
|
@@ -39,7 +39,7 @@ module ActiveSupport
|
|
39
39
|
@data = {}
|
40
40
|
end
|
41
41
|
|
42
|
-
# Don't allow synchronizing since it isn't thread safe
|
42
|
+
# Don't allow synchronizing since it isn't thread safe.
|
43
43
|
def synchronize # :nodoc:
|
44
44
|
yield
|
45
45
|
end
|
@@ -60,6 +60,10 @@ module ActiveSupport
|
|
60
60
|
def delete_entry(key, options)
|
61
61
|
!!@data.delete(key)
|
62
62
|
end
|
63
|
+
|
64
|
+
def fetch_entry(key, options = nil) # :nodoc:
|
65
|
+
@data.fetch(key) { @data[key] = yield }
|
66
|
+
end
|
63
67
|
end
|
64
68
|
|
65
69
|
# Use a local cache for the duration of block.
|
@@ -75,36 +79,35 @@ module ActiveSupport
|
|
75
79
|
end
|
76
80
|
|
77
81
|
def clear(options = nil) # :nodoc:
|
78
|
-
|
82
|
+
return super unless cache = local_cache
|
83
|
+
cache.clear(options)
|
79
84
|
super
|
80
85
|
end
|
81
86
|
|
82
87
|
def cleanup(options = nil) # :nodoc:
|
83
|
-
|
88
|
+
return super unless cache = local_cache
|
89
|
+
cache.clear(options)
|
84
90
|
super
|
85
91
|
end
|
86
92
|
|
87
93
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
94
|
+
return super unless local_cache
|
88
95
|
value = bypass_local_cache{super}
|
89
|
-
|
96
|
+
write_cache_value(name, value, options)
|
90
97
|
value
|
91
98
|
end
|
92
99
|
|
93
100
|
def decrement(name, amount = 1, options = nil) # :nodoc:
|
101
|
+
return super unless local_cache
|
94
102
|
value = bypass_local_cache{super}
|
95
|
-
|
103
|
+
write_cache_value(name, value, options)
|
96
104
|
value
|
97
105
|
end
|
98
106
|
|
99
107
|
protected
|
100
108
|
def read_entry(key, options) # :nodoc:
|
101
|
-
if local_cache
|
102
|
-
|
103
|
-
unless entry
|
104
|
-
entry = super
|
105
|
-
local_cache.write_entry(key, entry, options)
|
106
|
-
end
|
107
|
-
entry
|
109
|
+
if cache = local_cache
|
110
|
+
cache.fetch_entry(key) { super }
|
108
111
|
else
|
109
112
|
super
|
110
113
|
end
|
@@ -120,14 +123,22 @@ module ActiveSupport
|
|
120
123
|
super
|
121
124
|
end
|
122
125
|
|
123
|
-
def set_cache_value(value, name, amount, options)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
126
|
+
def set_cache_value(value, name, amount, options) # :nodoc:
|
127
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
128
|
+
`set_cache_value` is deprecated and will be removed from Rails 5.1.
|
129
|
+
Please use `write_cache_value`
|
130
|
+
MESSAGE
|
131
|
+
write_cache_value name, value, options
|
132
|
+
end
|
133
|
+
|
134
|
+
def write_cache_value(name, value, options) # :nodoc:
|
135
|
+
name = normalize_key(name, options)
|
136
|
+
cache = local_cache
|
137
|
+
cache.mute do
|
138
|
+
if value
|
139
|
+
cache.write(name, value, options)
|
140
|
+
else
|
141
|
+
cache.delete(name, options)
|
131
142
|
end
|
132
143
|
end
|
133
144
|
end
|
@@ -4,6 +4,9 @@ require 'active_support/core_ext/array/extract_options'
|
|
4
4
|
require 'active_support/core_ext/class/attribute'
|
5
5
|
require 'active_support/core_ext/kernel/reporting'
|
6
6
|
require 'active_support/core_ext/kernel/singleton_class'
|
7
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
8
|
+
require 'active_support/core_ext/string/filters'
|
9
|
+
require 'active_support/deprecation'
|
7
10
|
require 'thread'
|
8
11
|
|
9
12
|
module ActiveSupport
|
@@ -64,6 +67,12 @@ module ActiveSupport
|
|
64
67
|
|
65
68
|
CALLBACK_FILTER_TYPES = [:before, :after, :around]
|
66
69
|
|
70
|
+
# If true, Active Record and Active Model callbacks returning +false+ will
|
71
|
+
# halt the entire callback chain and display a deprecation message.
|
72
|
+
# If false, callback chains will only be halted by calling +throw :abort+.
|
73
|
+
# Defaults to +true+.
|
74
|
+
mattr_accessor(:halt_and_display_warning_on_return_false) { true }
|
75
|
+
|
67
76
|
# Runs the callbacks for the given event.
|
68
77
|
#
|
69
78
|
# Calls the before and around callbacks in the order they were set, yields
|
@@ -124,14 +133,10 @@ module ActiveSupport
|
|
124
133
|
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
|
125
134
|
halted_lambda = chain_config[:terminator]
|
126
135
|
|
127
|
-
if
|
136
|
+
if user_conditions.any?
|
128
137
|
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
129
|
-
elsif chain_config.key? :terminator
|
130
|
-
halting(callback_sequence, user_callback, halted_lambda, filter)
|
131
|
-
elsif user_conditions.any?
|
132
|
-
conditional(callback_sequence, user_callback, user_conditions)
|
133
138
|
else
|
134
|
-
|
139
|
+
halting(callback_sequence, user_callback, halted_lambda, filter)
|
135
140
|
end
|
136
141
|
end
|
137
142
|
|
@@ -142,8 +147,8 @@ module ActiveSupport
|
|
142
147
|
halted = env.halted
|
143
148
|
|
144
149
|
if !halted && user_conditions.all? { |c| c.call(target, value) }
|
145
|
-
|
146
|
-
env.halted = halted_lambda.call(target,
|
150
|
+
result_lambda = -> { user_callback.call target, value }
|
151
|
+
env.halted = halted_lambda.call(target, result_lambda)
|
147
152
|
if env.halted
|
148
153
|
target.send :halted_callback_hook, filter
|
149
154
|
end
|
@@ -161,8 +166,9 @@ module ActiveSupport
|
|
161
166
|
halted = env.halted
|
162
167
|
|
163
168
|
unless halted
|
164
|
-
|
165
|
-
env.halted = halted_lambda.call(target,
|
169
|
+
result_lambda = -> { user_callback.call target, value }
|
170
|
+
env.halted = halted_lambda.call(target, result_lambda)
|
171
|
+
|
166
172
|
if env.halted
|
167
173
|
target.send :halted_callback_hook, filter
|
168
174
|
end
|
@@ -172,42 +178,15 @@ module ActiveSupport
|
|
172
178
|
end
|
173
179
|
end
|
174
180
|
private_class_method :halting
|
175
|
-
|
176
|
-
def self.conditional(callback_sequence, user_callback, user_conditions)
|
177
|
-
callback_sequence.before do |env|
|
178
|
-
target = env.target
|
179
|
-
value = env.value
|
180
|
-
|
181
|
-
if user_conditions.all? { |c| c.call(target, value) }
|
182
|
-
user_callback.call target, value
|
183
|
-
end
|
184
|
-
|
185
|
-
env
|
186
|
-
end
|
187
|
-
end
|
188
|
-
private_class_method :conditional
|
189
|
-
|
190
|
-
def self.simple(callback_sequence, user_callback)
|
191
|
-
callback_sequence.before do |env|
|
192
|
-
user_callback.call env.target, env.value
|
193
|
-
|
194
|
-
env
|
195
|
-
end
|
196
|
-
end
|
197
|
-
private_class_method :simple
|
198
181
|
end
|
199
182
|
|
200
183
|
class After
|
201
184
|
def self.build(callback_sequence, user_callback, user_conditions, chain_config)
|
202
185
|
if chain_config[:skip_after_callbacks_if_terminated]
|
203
|
-
if
|
186
|
+
if user_conditions.any?
|
204
187
|
halting_and_conditional(callback_sequence, user_callback, user_conditions)
|
205
|
-
elsif chain_config.key?(:terminator)
|
206
|
-
halting(callback_sequence, user_callback)
|
207
|
-
elsif user_conditions.any?
|
208
|
-
conditional callback_sequence, user_callback, user_conditions
|
209
188
|
else
|
210
|
-
|
189
|
+
halting(callback_sequence, user_callback)
|
211
190
|
end
|
212
191
|
else
|
213
192
|
if user_conditions.any?
|
@@ -270,14 +249,10 @@ module ActiveSupport
|
|
270
249
|
|
271
250
|
class Around
|
272
251
|
def self.build(callback_sequence, user_callback, user_conditions, chain_config)
|
273
|
-
if
|
252
|
+
if user_conditions.any?
|
274
253
|
halting_and_conditional(callback_sequence, user_callback, user_conditions)
|
275
|
-
elsif chain_config.key? :terminator
|
276
|
-
halting(callback_sequence, user_callback)
|
277
|
-
elsif user_conditions.any?
|
278
|
-
conditional(callback_sequence, user_callback, user_conditions)
|
279
254
|
else
|
280
|
-
|
255
|
+
halting(callback_sequence, user_callback)
|
281
256
|
end
|
282
257
|
end
|
283
258
|
|
@@ -289,13 +264,11 @@ module ActiveSupport
|
|
289
264
|
|
290
265
|
if !halted && user_conditions.all? { |c| c.call(target, value) }
|
291
266
|
user_callback.call(target, value) {
|
292
|
-
|
293
|
-
env.value
|
267
|
+
run.call.value
|
294
268
|
}
|
295
|
-
|
296
269
|
env
|
297
270
|
else
|
298
|
-
run.call
|
271
|
+
run.call
|
299
272
|
end
|
300
273
|
end
|
301
274
|
end
|
@@ -307,51 +280,28 @@ module ActiveSupport
|
|
307
280
|
value = env.value
|
308
281
|
|
309
282
|
if env.halted
|
310
|
-
run.call
|
283
|
+
run.call
|
311
284
|
else
|
312
285
|
user_callback.call(target, value) {
|
313
|
-
|
314
|
-
env.value
|
286
|
+
run.call.value
|
315
287
|
}
|
316
288
|
env
|
317
289
|
end
|
318
290
|
end
|
319
291
|
end
|
320
292
|
private_class_method :halting
|
321
|
-
|
322
|
-
def self.conditional(callback_sequence, user_callback, user_conditions)
|
323
|
-
callback_sequence.around do |env, &run|
|
324
|
-
target = env.target
|
325
|
-
value = env.value
|
326
|
-
|
327
|
-
if user_conditions.all? { |c| c.call(target, value) }
|
328
|
-
user_callback.call(target, value) {
|
329
|
-
env = run.call env
|
330
|
-
env.value
|
331
|
-
}
|
332
|
-
env
|
333
|
-
else
|
334
|
-
run.call env
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
private_class_method :conditional
|
339
|
-
|
340
|
-
def self.simple(callback_sequence, user_callback)
|
341
|
-
callback_sequence.around do |env, &run|
|
342
|
-
user_callback.call(env.target, env.value) {
|
343
|
-
env = run.call env
|
344
|
-
env.value
|
345
|
-
}
|
346
|
-
env
|
347
|
-
end
|
348
|
-
end
|
349
|
-
private_class_method :simple
|
350
293
|
end
|
351
294
|
end
|
352
295
|
|
353
296
|
class Callback #:nodoc:#
|
354
297
|
def self.build(chain, filter, kind, options)
|
298
|
+
if filter.is_a?(String)
|
299
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
300
|
+
Passing string to define callback is deprecated and will be removed
|
301
|
+
in Rails 5.1 without replacement.
|
302
|
+
MSG
|
303
|
+
end
|
304
|
+
|
355
305
|
new chain.name, filter, kind, options, chain.config
|
356
306
|
end
|
357
307
|
|
@@ -371,14 +321,14 @@ module ActiveSupport
|
|
371
321
|
def filter; @key; end
|
372
322
|
def raw_filter; @filter; end
|
373
323
|
|
374
|
-
def
|
324
|
+
def merge_conditional_options(chain, if_option:, unless_option:)
|
375
325
|
options = {
|
376
326
|
:if => @if.dup,
|
377
327
|
:unless => @unless.dup
|
378
328
|
}
|
379
329
|
|
380
|
-
options[:if].concat Array(
|
381
|
-
options[:unless].concat Array(
|
330
|
+
options[:if].concat Array(unless_option)
|
331
|
+
options[:unless].concat Array(if_option)
|
382
332
|
|
383
333
|
self.class.build chain, @filter, @kind, options
|
384
334
|
end
|
@@ -493,17 +443,17 @@ module ActiveSupport
|
|
493
443
|
end
|
494
444
|
|
495
445
|
def around(&around)
|
496
|
-
CallbackSequence.new do
|
497
|
-
around.call(
|
498
|
-
self.call(
|
446
|
+
CallbackSequence.new do |arg|
|
447
|
+
around.call(arg) {
|
448
|
+
self.call(arg)
|
499
449
|
}
|
500
450
|
end
|
501
451
|
end
|
502
452
|
|
503
|
-
def call(
|
504
|
-
@before.each { |b| b.call(
|
505
|
-
value = @call.call(
|
506
|
-
@after.each { |a| a.call(
|
453
|
+
def call(arg)
|
454
|
+
@before.each { |b| b.call(arg) }
|
455
|
+
value = @call.call(arg)
|
456
|
+
@after.each { |a| a.call(arg) }
|
507
457
|
value
|
508
458
|
end
|
509
459
|
end
|
@@ -517,7 +467,8 @@ module ActiveSupport
|
|
517
467
|
def initialize(name, config)
|
518
468
|
@name = name
|
519
469
|
@config = {
|
520
|
-
:
|
470
|
+
scope: [:kind],
|
471
|
+
terminator: default_terminator
|
521
472
|
}.merge!(config)
|
522
473
|
@chain = []
|
523
474
|
@callbacks = nil
|
@@ -588,6 +539,17 @@ module ActiveSupport
|
|
588
539
|
@callbacks = nil
|
589
540
|
@chain.delete_if { |c| callback.duplicates?(c) }
|
590
541
|
end
|
542
|
+
|
543
|
+
def default_terminator
|
544
|
+
Proc.new do |target, result_lambda|
|
545
|
+
terminate = true
|
546
|
+
catch(:abort) do
|
547
|
+
result_lambda.call if result_lambda.is_a?(Proc)
|
548
|
+
terminate = false
|
549
|
+
end
|
550
|
+
terminate
|
551
|
+
end
|
552
|
+
end
|
591
553
|
end
|
592
554
|
|
593
555
|
module ClassMethods
|
@@ -613,14 +575,14 @@ module ActiveSupport
|
|
613
575
|
# set_callback :save, :after, :after_meth, if: :condition
|
614
576
|
# set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
|
615
577
|
#
|
616
|
-
# The second
|
578
|
+
# The second argument indicates whether the callback is to be run +:before+,
|
617
579
|
# +:after+, or +:around+ the event. If omitted, +:before+ is assumed. This
|
618
580
|
# means the first example above can also be written as:
|
619
581
|
#
|
620
582
|
# set_callback :save, :before_meth
|
621
583
|
#
|
622
584
|
# The callback can be specified as a symbol naming an instance method; as a
|
623
|
-
# proc, lambda, or block; as a string to be instance evaluated; or as an
|
585
|
+
# proc, lambda, or block; as a string to be instance evaluated(deprecated); or as an
|
624
586
|
# object that responds to a certain method determined by the <tt>:scope</tt>
|
625
587
|
# argument to +define_callbacks+.
|
626
588
|
#
|
@@ -664,19 +626,27 @@ module ActiveSupport
|
|
664
626
|
# class Writer < Person
|
665
627
|
# skip_callback :validate, :before, :check_membership, if: -> { self.age > 18 }
|
666
628
|
# end
|
629
|
+
#
|
630
|
+
# An <tt>ArgumentError</tt> will be raised if the callback has not
|
631
|
+
# already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
|
667
632
|
def skip_callback(name, *filter_list, &block)
|
668
633
|
type, filters, options = normalize_callback_params(filter_list, block)
|
634
|
+
options[:raise] = true unless options.key?(:raise)
|
669
635
|
|
670
636
|
__update_callbacks(name) do |target, chain|
|
671
637
|
filters.each do |filter|
|
672
|
-
|
638
|
+
callback = chain.find {|c| c.matches?(type, filter) }
|
639
|
+
|
640
|
+
if !callback && options[:raise]
|
641
|
+
raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined"
|
642
|
+
end
|
673
643
|
|
674
|
-
if
|
675
|
-
|
676
|
-
chain.insert(chain.index(
|
644
|
+
if callback && (options.key?(:if) || options.key?(:unless))
|
645
|
+
new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
|
646
|
+
chain.insert(chain.index(callback), new_callback)
|
677
647
|
end
|
678
648
|
|
679
|
-
chain.delete(
|
649
|
+
chain.delete(callback)
|
680
650
|
end
|
681
651
|
target.set_callbacks name, chain
|
682
652
|
end
|
@@ -703,21 +673,23 @@ module ActiveSupport
|
|
703
673
|
# ===== Options
|
704
674
|
#
|
705
675
|
# * <tt>:terminator</tt> - Determines when a before filter will halt the
|
706
|
-
# callback chain, preventing following
|
707
|
-
# the event from being triggered.
|
708
|
-
#
|
709
|
-
#
|
676
|
+
# callback chain, preventing following before and around callbacks from
|
677
|
+
# being called and the event from being triggered.
|
678
|
+
# This should be a lambda to be executed.
|
679
|
+
# The current object and the result lambda of the callback will be provided
|
680
|
+
# to the terminator lambda.
|
710
681
|
#
|
711
|
-
# define_callbacks :validate, terminator: ->(target,
|
682
|
+
# define_callbacks :validate, terminator: ->(target, result_lambda) { result_lambda.call == false }
|
712
683
|
#
|
713
684
|
# In this example, if any before validate callbacks returns +false+,
|
714
|
-
#
|
715
|
-
#
|
685
|
+
# any successive before and around callback is not executed.
|
686
|
+
#
|
687
|
+
# The default terminator halts the chain when a callback throws +:abort+.
|
716
688
|
#
|
717
689
|
# * <tt>:skip_after_callbacks_if_terminated</tt> - Determines if after
|
718
690
|
# callbacks should be terminated by the <tt>:terminator</tt> option. By
|
719
|
-
# default after callbacks executed no matter if callback chain was
|
720
|
-
# terminated or not.
|
691
|
+
# default after callbacks are executed no matter if callback chain was
|
692
|
+
# terminated or not. This option makes sense only when <tt>:terminator</tt>
|
721
693
|
# option is specified.
|
722
694
|
#
|
723
695
|
# * <tt>:scope</tt> - Indicates which methods should be executed when an
|
@@ -770,7 +742,7 @@ module ActiveSupport
|
|
770
742
|
options = names.extract_options!
|
771
743
|
|
772
744
|
names.each do |name|
|
773
|
-
class_attribute "_#{name}_callbacks"
|
745
|
+
class_attribute "_#{name}_callbacks"
|
774
746
|
set_callbacks name, CallbackChain.new(name, options)
|
775
747
|
|
776
748
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -783,13 +755,37 @@ module ActiveSupport
|
|
783
755
|
|
784
756
|
protected
|
785
757
|
|
786
|
-
def get_callbacks(name)
|
758
|
+
def get_callbacks(name) # :nodoc:
|
787
759
|
send "_#{name}_callbacks"
|
788
760
|
end
|
789
761
|
|
790
|
-
def set_callbacks(name, callbacks)
|
762
|
+
def set_callbacks(name, callbacks) # :nodoc:
|
791
763
|
send "_#{name}_callbacks=", callbacks
|
792
764
|
end
|
765
|
+
|
766
|
+
def deprecated_false_terminator # :nodoc:
|
767
|
+
Proc.new do |target, result_lambda|
|
768
|
+
terminate = true
|
769
|
+
catch(:abort) do
|
770
|
+
result = result_lambda.call if result_lambda.is_a?(Proc)
|
771
|
+
if Callbacks.halt_and_display_warning_on_return_false && result == false
|
772
|
+
display_deprecation_warning_for_false_terminator
|
773
|
+
else
|
774
|
+
terminate = false
|
775
|
+
end
|
776
|
+
end
|
777
|
+
terminate
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
private
|
782
|
+
|
783
|
+
def display_deprecation_warning_for_false_terminator
|
784
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
785
|
+
Returning `false` in Active Record and Active Model callbacks will not implicitly halt a callback chain in the next release of Rails.
|
786
|
+
To explicitly halt the callback chain, please use `throw :abort` instead.
|
787
|
+
MSG
|
788
|
+
end
|
793
789
|
end
|
794
790
|
end
|
795
791
|
end
|