activesupport 7.2.2 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -198
  3. data/lib/active_support/backtrace_cleaner.rb +1 -1
  4. data/lib/active_support/benchmark.rb +21 -0
  5. data/lib/active_support/benchmarkable.rb +3 -2
  6. data/lib/active_support/cache/file_store.rb +12 -2
  7. data/lib/active_support/cache/memory_store.rb +6 -2
  8. data/lib/active_support/cache/redis_cache_store.rb +5 -2
  9. data/lib/active_support/cache.rb +16 -11
  10. data/lib/active_support/callbacks.rb +5 -3
  11. data/lib/active_support/class_attribute.rb +33 -0
  12. data/lib/active_support/code_generator.rb +9 -0
  13. data/lib/active_support/concurrency/share_lock.rb +0 -1
  14. data/lib/active_support/configuration_file.rb +15 -6
  15. data/lib/active_support/core_ext/array/conversions.rb +3 -3
  16. data/lib/active_support/core_ext/benchmark.rb +6 -9
  17. data/lib/active_support/core_ext/class/attribute.rb +24 -20
  18. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  19. data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
  20. data/lib/active_support/core_ext/enumerable.rb +8 -3
  21. data/lib/active_support/core_ext/erb/util.rb +2 -2
  22. data/lib/active_support/core_ext/hash/except.rb +0 -12
  23. data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
  24. data/lib/active_support/core_ext/object/json.rb +15 -9
  25. data/lib/active_support/core_ext/securerandom.rb +24 -8
  26. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  27. data/lib/active_support/core_ext/time/calculations.rb +14 -2
  28. data/lib/active_support/core_ext/time/compatibility.rb +9 -1
  29. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  30. data/lib/active_support/delegation.rb +0 -2
  31. data/lib/active_support/dependencies.rb +0 -1
  32. data/lib/active_support/deprecation/reporting.rb +0 -19
  33. data/lib/active_support/deprecation.rb +1 -1
  34. data/lib/active_support/duration.rb +14 -10
  35. data/lib/active_support/encrypted_configuration.rb +20 -2
  36. data/lib/active_support/error_reporter.rb +25 -1
  37. data/lib/active_support/evented_file_update_checker.rb +0 -1
  38. data/lib/active_support/gem_version.rb +3 -3
  39. data/lib/active_support/hash_with_indifferent_access.rb +16 -16
  40. data/lib/active_support/i18n_railtie.rb +19 -11
  41. data/lib/active_support/isolated_execution_state.rb +0 -2
  42. data/lib/active_support/json/encoding.rb +2 -2
  43. data/lib/active_support/notifications/fanout.rb +0 -1
  44. data/lib/active_support/number_helper.rb +22 -0
  45. data/lib/active_support/railtie.rb +4 -0
  46. data/lib/active_support/tagged_logging.rb +5 -0
  47. data/lib/active_support/testing/assertions.rb +79 -21
  48. data/lib/active_support/testing/isolation.rb +0 -2
  49. data/lib/active_support/testing/strict_warnings.rb +1 -1
  50. data/lib/active_support/testing/time_helpers.rb +2 -1
  51. data/lib/active_support/time_with_zone.rb +22 -13
  52. data/lib/active_support/values/time_zone.rb +11 -9
  53. data/lib/active_support.rb +10 -3
  54. metadata +23 -8
  55. data/lib/active_support/proxy_object.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a3996eac7e9551da7dd4bfc64cd93c049f3cb044fba118c088fc7ae18098565
4
- data.tar.gz: fc6777f0b3cc247cfb3d3bbedabec020937ef4bf226318d6f775bef99b43b162
3
+ metadata.gz: e4fc487978c855f357de44a7915c8d6d21161a4731bfe676294c1a39f91083d8
4
+ data.tar.gz: e0c7577dabe5346cdcaddef70cb94d58d636df12bef5f7b96df8c062f1831d08
5
5
  SHA512:
6
- metadata.gz: 1c2e709540796368a539085facf517fd7bd02fb30438a87dd4508fff29e15fe58632b8d62351238998b95e775ec12491591efbd8ac0edb89f513c7a3dad1ff47
7
- data.tar.gz: 1be932867f259f0ee991d3b74a8f8e186f75b7bf7a279bde9235ac6e59cc4bae7f2c61feff5a19c5582afcca0bd4bd4468f25cf55b07693d24586a5f05723f90
6
+ metadata.gz: 2fc772fb80613c40405114a4cf7a806fe77766ee128c7c308de18eedd73fa6581f95dd072cdf38b13947d91d9df560620b8126b199577b293f2095c4c6d0481e
7
+ data.tar.gz: 8aa7beb41005f500c9d4d1287f2f11724f7178aaa9953c089d4afb5523060136da33771f3ac0ee5edf8dc91afcb9bd31272eaeef650c9238c670c6f0c82b18cb
data/CHANGELOG.md CHANGED
@@ -1,279 +1,157 @@
1
- ## Rails 7.2.2 (October 30, 2024) ##
1
+ ## Rails 8.0.1 (December 13, 2024) ##
2
2
 
3
- * Include options when instrumenting `ActiveSupport::Cache::Store#delete` and `ActiveSupport::Cache::Store#delete_multi`.
4
-
5
- *Adam Renberg Tamm*
3
+ * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceeded by multibyte characters.
6
4
 
7
- * Print test names when running `rails test -v` for parallel tests.
5
+ *Martin Emde*
8
6
 
9
- *John Hawthorn*, *Abeid Ahmed*
7
+ * Restore the ability to decorate methods generated by `class_attribute`.
10
8
 
9
+ It always has been complicated to use Module#prepend or an alias method chain
10
+ to decorate methods defined by `class_attribute`, but became even harder in 8.0.
11
11
 
12
- ## Rails 7.2.1.2 (October 23, 2024) ##
12
+ This capability is now supported for both reader and writer methods.
13
13
 
14
- * No changes.
14
+ *Jean Boussier*
15
15
 
16
16
 
17
- ## Rails 7.2.1.1 (October 15, 2024) ##
17
+ ## Rails 8.0.0.1 (December 10, 2024) ##
18
18
 
19
19
  * No changes.
20
20
 
21
21
 
22
- ## Rails 7.2.1 (August 22, 2024) ##
22
+ ## Rails 8.0.0 (November 07, 2024) ##
23
23
 
24
24
  * No changes.
25
25
 
26
26
 
27
- ## Rails 7.2.0 (August 09, 2024) ##
28
-
29
- * Fix `delegate_missing_to allow_nil: true` when called with implict self
30
-
31
- ```ruby
32
- class Person
33
- delegate_missing_to :address, allow_nil: true
34
-
35
- def address
36
- nil
37
- end
38
-
39
- def berliner?
40
- city == "Berlin"
41
- end
42
- end
43
-
44
- Person.new.city # => nil
45
- Person.new.berliner? # undefined local variable or method `city' for an instance of Person (NameError)
46
- ```
47
-
48
- *Jean Boussier*
49
-
50
- * Add `logger` as a dependency since it is a bundled gem candidate for Ruby 3.5
51
-
52
- *Earlopain*
53
-
54
- * Define `Digest::UUID.nil_uuid`, which returns the so-called nil UUID.
55
-
56
- *Xavier Noria*
57
-
58
- * Support `duration` type in `ActiveSupport::XmlMini`.
59
-
60
- *heka1024*
61
-
62
- * Remove deprecated `ActiveSupport::Notifications::Event#children` and `ActiveSupport::Notifications::Event#parent_of?`.
63
-
64
- *Rafael Mendonça França*
65
-
66
- * Remove deprecated support to call the following methods without passing a deprecator:
67
-
68
- - `deprecate`
69
- - `deprecate_constant`
70
- - `ActiveSupport::Deprecation::DeprecatedObjectProxy.new`
71
- - `ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new`
72
- - `ActiveSupport::Deprecation::DeprecatedConstantProxy.new`
73
- - `assert_deprecated`
74
- - `assert_not_deprecated`
75
- - `collect_deprecations`
76
-
77
- *Rafael Mendonça França*
78
-
79
- * Remove deprecated `ActiveSupport::Deprecation` delegation to instance.
80
-
81
- *Rafael Mendonça França*
82
-
83
- * Remove deprecated `SafeBuffer#clone_empty`.
84
-
85
- *Rafael Mendonça França*
86
-
87
- * Remove deprecated `#to_default_s` from `Array`, `Date`, `DateTime` and `Time`.
88
-
89
- *Rafael Mendonça França*
90
-
91
- * Remove deprecated support to passing `Dalli::Client` instances to `MemCacheStore`.
92
-
93
- *Rafael Mendonça França*
94
-
95
- * Remove deprecated `config.active_support.use_rfc4122_namespaced_uuids`.
27
+ ## Rails 8.0.0.rc2 (October 30, 2024) ##
96
28
 
97
- *Rafael Mendonça França*
98
-
99
- * Remove deprecated `config.active_support.remove_deprecated_time_with_zone_name`.
100
-
101
- *Rafael Mendonça França*
102
-
103
- * Remove deprecated `config.active_support.disable_to_s_conversion`.
104
-
105
- *Rafael Mendonça França*
29
+ * No changes.
106
30
 
107
- * Remove deprecated support to bolding log text with positional boolean in `ActiveSupport::LogSubscriber#color`.
108
31
 
109
- *Rafael Mendonça França*
32
+ ## Rails 8.0.0.rc1 (October 19, 2024) ##
110
33
 
111
- * Remove deprecated constants `ActiveSupport::LogSubscriber::CLEAR` and `ActiveSupport::LogSubscriber::BOLD`.
34
+ * Remove deprecated support to passing an array of strings to `ActiveSupport::Deprecation#warn`.
112
35
 
113
36
  *Rafael Mendonça França*
114
37
 
115
- * Remove deprecated support for `config.active_support.cache_format_version = 6.1`.
38
+ * Remove deprecated support to setting `attr_internal_naming_format` with a `@` prefix.
116
39
 
117
40
  *Rafael Mendonça França*
118
41
 
119
- * Remove deprecated `:pool_size` and `:pool_timeout` options for the cache storage.
42
+ * Remove deprecated `ActiveSupport::ProxyObject`.
120
43
 
121
44
  *Rafael Mendonça França*
122
45
 
123
- * Warn on tests without assertions.
46
+ * Don't execute i18n watcher on boot. It shouldn't catch any file changes initially,
47
+ and unnecessarily slows down boot of applications with lots of translations.
124
48
 
125
- `ActiveSupport::TestCase` now warns when tests do not run any assertions.
126
- This is helpful in detecting broken tests that do not perform intended assertions.
49
+ *Gannon McGibbon*, *David Stosik*
127
50
 
128
- *fatkodima*
51
+ * Fix `ActiveSupport::HashWithIndifferentAccess#stringify_keys` to stringify all keys not just symbols.
129
52
 
130
- * Support `hexBinary` type in `ActiveSupport::XmlMini`.
53
+ Previously:
131
54
 
132
- *heka1024*
133
-
134
- * Deprecate `ActiveSupport::ProxyObject` in favor of Ruby's built-in `BasicObject`.
135
-
136
- *Earlopain*
137
-
138
- * `stub_const` now accepts a `exists: false` parameter to allow stubbing missing constants.
139
-
140
- *Jean Boussier*
141
-
142
- * Make `ActiveSupport::BacktraceCleaner` copy filters and silencers on dup and clone.
143
-
144
- Previously the copy would still share the internal silencers and filters array,
145
- causing state to leak.
146
-
147
- *Jean Boussier*
148
-
149
- * Updating Astana with Western Kazakhstan TZInfo identifier.
150
-
151
- *Damian Nelson*
55
+ ```ruby
56
+ { 1 => 2 }.with_indifferent_access.stringify_keys[1] # => 2
57
+ ```
152
58
 
153
- * Add filename support for `ActiveSupport::Logger.logger_outputs_to?`.
59
+ After this change:
154
60
 
155
61
  ```ruby
156
- logger = Logger.new('/var/log/rails.log')
157
- ActiveSupport::Logger.logger_outputs_to?(logger, '/var/log/rails.log')
62
+ { 1 => 2 }.with_indifferent_access.stringify_keys["1"] # => 2
158
63
  ```
159
64
 
160
- *Christian Schmidt*
65
+ This change can be seen as a bug fix, but since it behaved like this for a very long time, we're deciding
66
+ to not backport the fix and to make the change in a major release.
161
67
 
162
- * Include `IPAddr#prefix` when serializing an `IPAddr` using the
163
- `ActiveSupport::MessagePack` serializer.
68
+ *Jean Boussier*
164
69
 
165
- This change is backward and forward compatible — old payloads can
166
- still be read, and new payloads will be readable by older versions of Rails.
70
+ ## Rails 8.0.0.beta1 (September 26, 2024) ##
167
71
 
168
- *Taiki Komaba*
72
+ * Include options when instrumenting `ActiveSupport::Cache::Store#delete` and `ActiveSupport::Cache::Store#delete_multi`.
169
73
 
170
- * Add `default:` support for `ActiveSupport::CurrentAttributes.attribute`.
74
+ *Adam Renberg Tamm*
171
75
 
172
- ```ruby
173
- class Current < ActiveSupport::CurrentAttributes
174
- attribute :counter, default: 0
175
- end
176
- ```
76
+ * Print test names when running `rails test -v` for parallel tests.
177
77
 
178
- *Sean Doyle*
78
+ *John Hawthorn*, *Abeid Ahmed*
179
79
 
180
- * Yield instance to `Object#with` block.
80
+ * Deprecate `Benchmark.ms` core extension.
181
81
 
182
- ```ruby
183
- client.with(timeout: 5_000) do |c|
184
- c.get("/commits")
185
- end
186
- ```
82
+ The `benchmark` gem will become bundled in Ruby 3.5
187
83
 
188
- *Sean Doyle*
84
+ *Earlopain*
189
85
 
190
- * Use logical core count instead of physical core count to determine the
191
- default number of workers when parallelizing tests.
86
+ * `ActiveSupport::TimeWithZone#inspect` now uses ISO 8601 style time like `Time#inspect`
192
87
 
193
- *Jonathan Hefner*
88
+ *John Hawthorn*
194
89
 
195
- * Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
90
+ * `ActiveSupport::ErrorReporter#report` now assigns a backtrace to unraised exceptions.
196
91
 
197
- There is a bug in the current implementation of #travel_to:
198
- it remembers a timezone of its argument, and all stubbed methods start
199
- returning results in that remembered timezone. However, the expected
200
- behavior is to return results in a system timezone.
92
+ Previously reporting an un-raised exception would result in an error report without
93
+ a backtrace. Now it automatically generates one.
201
94
 
202
- *Aleksei Chernenkov*
95
+ *Jean Boussier*
203
96
 
204
- * Add `ErrorReported#unexpected` to report precondition violations.
97
+ * Add `escape_html_entities` option to `ActiveSupport::JSON.encode`.
205
98
 
206
- For example:
99
+ This allows for overriding the global configuration found at
100
+ `ActiveSupport.escape_html_entities_in_json` for specific calls to `to_json`.
207
101
 
102
+ This should be usable from controllers in the following manner:
208
103
  ```ruby
209
- def edit
210
- if published?
211
- Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
212
- return false
104
+ class MyController < ApplicationController
105
+ def index
106
+ render json: { hello: "world" }, escape_html_entities: false
213
107
  end
214
- # ...
215
108
  end
216
109
  ```
217
110
 
218
- The above will raise an error in development and test, but only report the error in production.
219
-
220
- *Jean Boussier*
221
-
222
- * Make the order of read_multi and write_multi notifications for `Cache::Store#fetch_multi` operations match the order they are executed in.
111
+ *Nigel Baillie*
223
112
 
224
- *Adam Renberg Tamm*
113
+ * Raise when using key which can't respond to `#to_sym` in `EncryptedConfiguration`.
225
114
 
226
- * Make return values of `Cache::Store#write` consistent.
115
+ As is the case when trying to use an Integer or Float as a key, which is unsupported.
227
116
 
228
- The return value was not specified before. Now it returns `true` on a successful write,
229
- `nil` if there was an error talking to the cache backend, and `false` if the write failed
230
- for another reason (e.g. the key already exists and `unless_exist: true` was passed).
117
+ *zzak*
231
118
 
232
- *Sander Verdonschot*
119
+ * Deprecate addition and since between two `Time` and `ActiveSupport::TimeWithZone`.
233
120
 
234
- * Fix logged cache keys not always matching actual key used by cache action.
121
+ Previously adding time instances together such as `10.days.ago + 10.days.ago` or `10.days.ago.since(10.days.ago)` produced a nonsensical future date. This behavior is deprecated and will be removed in Rails 8.1.
235
122
 
236
- *Hartley McGuire*
123
+ *Nick Schwaderer*
237
124
 
238
- * Improve error messages of `assert_changes` and `assert_no_changes`.
239
-
240
- `assert_changes` error messages now display objects with `.inspect` to make it easier
241
- to differentiate nil from empty strings, strings from symbols, etc.
242
- `assert_no_changes` error messages now surface the actual value.
243
-
244
- *pcreux*
245
-
246
- * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
247
-
248
- *Earlopain*
125
+ * Support rfc2822 format for Time#to_fs & Date#to_fs.
249
126
 
250
- * Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
127
+ *Akshay Birajdar*
251
128
 
252
- *Andrew Novoselac*
129
+ * Optimize load time for `Railtie#initialize_i18n`. Filter `I18n.load_path`s passed to the file watcher to only those
130
+ under `Rails.root`. Previously the watcher would grab all available locales, including those in gems
131
+ which do not require a watcher because they won't change.
253
132
 
254
- * Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
133
+ *Nick Schwaderer*
255
134
 
256
- *Andrew Novoselac*
135
+ * Add a `filter` option to `in_order_of` to prioritize certain values in the sorting without filtering the results
136
+ by these values.
257
137
 
258
- * Fix compatibility with the `semantic_logger` gem.
138
+ *Igor Depolli*
259
139
 
260
- The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
261
- `SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
140
+ * Improve error message when using `assert_difference` or `assert_changes` with a
141
+ proc by printing the proc's source code (MRI only).
262
142
 
263
- This caused the various `LogSubscriber` classes in Rails to break when assigned a
264
- `SemanticLogger` instance.
143
+ *Richard Böhme*, *Jean Boussier*
265
144
 
266
- *Jean Boussier*, *ojab*
145
+ * Add a new configuration value `:zone` for `ActiveSupport.to_time_preserves_timezone` and rename the previous `true` value to `:offset`. The new default value is `:zone`.
267
146
 
268
- * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
147
+ *Jason Kim*, *John Hawthorn*
269
148
 
270
- *Pierre Jambet*
149
+ * Align instrumentation `payload[:key]` in ActiveSupport::Cache to follow the same pattern, with namespaced and normalized keys.
271
150
 
272
- * Implement `HashWithIndifferentAccess#to_proc`.
151
+ *Frederik Erbs Spang Thomsen*
273
152
 
274
- Previously, calling `#to_proc` on `HashWithIndifferentAccess` object used inherited `#to_proc`
275
- method from the `Hash` class, which was not able to access values using indifferent keys.
153
+ * Fix `travel_to` to set usec 0 when `with_usec` is `false` and the given argument String or DateTime.
276
154
 
277
- *fatkodima*
155
+ *mopp*
278
156
 
279
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activesupport/CHANGELOG.md) for previous changes.
157
+ Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activesupport/CHANGELOG.md) for previous changes.
@@ -18,7 +18,7 @@ module ActiveSupport
18
18
  #
19
19
  # bc = ActiveSupport::BacktraceCleaner.new
20
20
  # root = "#{Rails.root}/"
21
- # bc.add_filter { |line| line.start_with?(root) ? line.from(root.size) : line } # strip the Rails.root prefix
21
+ # bc.add_filter { |line| line.delete_prefix(root) } # strip the Rails.root prefix
22
22
  # bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
23
23
  # bc.clean(exception.backtrace) # perform the cleanup
24
24
  #
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Benchmark # :nodoc:
5
+ # Benchmark realtime in the specified time unit. By default,
6
+ # the returned unit is in seconds.
7
+ #
8
+ # ActiveSupport::Benchmark.realtime { sleep 0.1 }
9
+ # # => 0.10007
10
+ #
11
+ # ActiveSupport::Benchmark.realtime(:float_millisecond) { sleep 0.1 }
12
+ # # => 100.07
13
+ #
14
+ # `unit` can be any of the values accepted by Ruby's `Process.clock_gettime`.
15
+ def self.realtime(unit = :float_second, &block)
16
+ time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
17
+ yield
18
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, unit) - time_start
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/benchmark"
4
3
  require "active_support/core_ext/hash/keys"
5
4
 
6
5
  module ActiveSupport
@@ -41,7 +40,9 @@ module ActiveSupport
41
40
  options[:level] ||= :info
42
41
 
43
42
  result = nil
44
- ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
43
+ ms = ActiveSupport::Benchmark.realtime(:float_millisecond) do
44
+ result = options[:silence] ? logger.silence(&block) : yield
45
+ end
45
46
  logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
46
47
  result
47
48
  else
@@ -58,7 +58,12 @@ module ActiveSupport
58
58
  # cache.increment("baz") # => 6
59
59
  #
60
60
  def increment(name, amount = 1, options = nil)
61
- modify_value(name, amount, options)
61
+ options = merged_options(options)
62
+ key = normalize_key(name, options)
63
+
64
+ instrument(:increment, key, amount: amount) do
65
+ modify_value(name, amount, options)
66
+ end
62
67
  end
63
68
 
64
69
  # Decrement a cached integer value. Returns the updated value.
@@ -73,7 +78,12 @@ module ActiveSupport
73
78
  # cache.decrement("baz") # => 4
74
79
  #
75
80
  def decrement(name, amount = 1, options = nil)
76
- modify_value(name, -amount, options)
81
+ options = merged_options(options)
82
+ key = normalize_key(name, options)
83
+
84
+ instrument(:decrement, key, amount: amount) do
85
+ modify_value(name, -amount, options)
86
+ end
77
87
  end
78
88
 
79
89
  def delete_matched(matcher, options = nil)
@@ -147,7 +147,9 @@ module ActiveSupport
147
147
  # cache.increment("baz") # => 6
148
148
  #
149
149
  def increment(name, amount = 1, options = nil)
150
- modify_value(name, amount, options)
150
+ instrument(:increment, name, amount: amount) do
151
+ modify_value(name, amount, options)
152
+ end
151
153
  end
152
154
 
153
155
  # Decrement a cached integer value. Returns the updated value.
@@ -162,7 +164,9 @@ module ActiveSupport
162
164
  # cache.decrement("baz") # => 4
163
165
  #
164
166
  def decrement(name, amount = 1, options = nil)
165
- modify_value(name, -amount, options)
167
+ instrument(:decrement, name, amount: amount) do
168
+ modify_value(name, -amount, options)
169
+ end
166
170
  end
167
171
 
168
172
  # Deletes cache entries if the cache key matches a given pattern.
@@ -173,9 +173,12 @@ module ActiveSupport
173
173
  return {} if names.empty?
174
174
 
175
175
  options = names.extract_options!
176
- instrument_multi(:read_multi, names, options) do |payload|
176
+ options = merged_options(options)
177
+ keys = names.map { |name| normalize_key(name, options) }
178
+
179
+ instrument_multi(:read_multi, keys, options) do |payload|
177
180
  read_multi_entries(names, **options).tap do |results|
178
- payload[:hits] = results.keys
181
+ payload[:hits] = results.keys.map { |name| normalize_key(name, options) }
179
182
  end
180
183
  end
181
184
  end
@@ -286,7 +286,7 @@ module ActiveSupport
286
286
  # <tt>coder: nil</tt> to avoid the overhead of safeguarding against
287
287
  # mutation.
288
288
  #
289
- # The +:coder+ option is mutally exclusive with the +:serializer+ and
289
+ # The +:coder+ option is mutually exclusive with the +:serializer+ and
290
290
  # +:compressor+ options. Specifying them together will raise an
291
291
  # +ArgumentError+.
292
292
  #
@@ -419,7 +419,7 @@ module ActiveSupport
419
419
  # t1.join
420
420
  #
421
421
  # p val_1 # => "new value 1"
422
- # p val_2 # => "oritinal value"
422
+ # p val_2 # => "original value"
423
423
  # p cache.fetch("foo") # => "new value 1"
424
424
  #
425
425
  # # The entry requires 3 seconds to expire (expires_in + race_condition_ttl)
@@ -538,10 +538,11 @@ module ActiveSupport
538
538
 
539
539
  options = names.extract_options!
540
540
  options = merged_options(options)
541
+ keys = names.map { |name| normalize_key(name, options) }
541
542
 
542
- instrument_multi :read_multi, names, options do |payload|
543
+ instrument_multi :read_multi, keys, options do |payload|
543
544
  read_multi_entries(names, **options, event: payload).tap do |results|
544
- payload[:hits] = results.keys
545
+ payload[:hits] = results.keys.map { |name| normalize_key(name, options) }
545
546
  end
546
547
  end
547
548
  end
@@ -551,8 +552,9 @@ module ActiveSupport
551
552
  return hash if hash.empty?
552
553
 
553
554
  options = merged_options(options)
555
+ normalized_hash = hash.transform_keys { |key| normalize_key(key, options) }
554
556
 
555
- instrument_multi :write_multi, hash, options do |payload|
557
+ instrument_multi :write_multi, normalized_hash, options do |payload|
556
558
  entries = hash.each_with_object({}) do |(name, value), memo|
557
559
  memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
558
560
  end
@@ -596,9 +598,9 @@ module ActiveSupport
596
598
 
597
599
  options = names.extract_options!
598
600
  options = merged_options(options)
599
-
601
+ keys = names.map { |name| normalize_key(name, options) }
600
602
  writes = {}
601
- ordered = instrument_multi :read_multi, names, options do |payload|
603
+ ordered = instrument_multi :read_multi, keys, options do |payload|
602
604
  if options[:force]
603
605
  reads = {}
604
606
  else
@@ -610,7 +612,7 @@ module ActiveSupport
610
612
  end
611
613
  writes.compact! if options[:skip_nil]
612
614
 
613
- payload[:hits] = reads.keys
615
+ payload[:hits] = reads.keys.map { |name| normalize_key(name, options) }
614
616
  payload[:super_operation] = :fetch_multi
615
617
 
616
618
  ordered
@@ -943,9 +945,12 @@ module ActiveSupport
943
945
  #
944
946
  # namespace_key 'foo', namespace: -> { 'cache' }
945
947
  # # => 'cache:foo'
946
- def namespace_key(key, options = nil)
947
- options = merged_options(options)
948
- namespace = options[:namespace]
948
+ def namespace_key(key, call_options = nil)
949
+ namespace = if call_options&.key?(:namespace)
950
+ call_options[:namespace]
951
+ else
952
+ options[:namespace]
953
+ end
949
954
 
950
955
  if namespace.respond_to?(:call)
951
956
  namespace = namespace.call
@@ -6,7 +6,6 @@ require "active_support/core_ext/array/extract_options"
6
6
  require "active_support/core_ext/class/attribute"
7
7
  require "active_support/core_ext/string/filters"
8
8
  require "active_support/core_ext/object/blank"
9
- require "thread"
10
9
 
11
10
  module ActiveSupport
12
11
  # = Active Support \Callbacks
@@ -67,7 +66,7 @@ module ActiveSupport
67
66
 
68
67
  included do
69
68
  extend ActiveSupport::DescendantsTracker
70
- class_attribute :__callbacks, instance_writer: false, default: {}
69
+ class_attribute :__callbacks, instance_writer: false, instance_predicate: false, default: {}
71
70
  end
72
71
 
73
72
  CALLBACK_FILTER_TYPES = [:before, :after, :around].freeze
@@ -934,7 +933,10 @@ module ActiveSupport
934
933
  end
935
934
 
936
935
  def set_callbacks(name, callbacks) # :nodoc:
937
- unless singleton_class.method_defined?(:__callbacks, false)
936
+ # HACK: We're making assumption on how `class_attribute` is implemented
937
+ # to save constantly duping the callback hash. If this desync with class_attribute
938
+ # we'll lose the optimization, but won't cause an actual behavior bug.
939
+ unless singleton_class.private_method_defined?(:__class_attr__callbacks, false)
938
940
  self.__callbacks = __callbacks.dup
939
941
  end
940
942
  self.__callbacks[name.to_sym] = callbacks
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module ClassAttribute # :nodoc:
5
+ class << self
6
+ def redefine(owner, name, namespaced_name, value)
7
+ if owner.singleton_class?
8
+ if owner.attached_object.is_a?(Module)
9
+ redefine_method(owner, namespaced_name, private: true) { value }
10
+ else
11
+ redefine_method(owner, name) { value }
12
+ end
13
+ end
14
+
15
+ redefine_method(owner.singleton_class, namespaced_name, private: true) { value }
16
+
17
+ redefine_method(owner.singleton_class, "#{namespaced_name}=", private: true) do |new_value|
18
+ if owner.equal?(self)
19
+ value = new_value
20
+ else
21
+ ::ActiveSupport::ClassAttribute.redefine(self, name, namespaced_name, new_value)
22
+ end
23
+ end
24
+ end
25
+
26
+ def redefine_method(owner, name, private: false, &block)
27
+ owner.silence_redefinition_of_method(name)
28
+ owner.define_method(name, &block)
29
+ owner.send(:private, name) if private
30
+ end
31
+ end
32
+ end
33
+ end
@@ -55,6 +55,11 @@ module ActiveSupport
55
55
  @path = path
56
56
  @line = line
57
57
  @namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
58
+ @sources = []
59
+ end
60
+
61
+ def class_eval
62
+ yield @sources
58
63
  end
59
64
 
60
65
  def define_cached_method(canonical_name, namespace:, as: nil, &block)
@@ -65,6 +70,10 @@ module ActiveSupport
65
70
  @namespaces.each_value do |method_set|
66
71
  method_set.apply(@owner, @path, @line - 1)
67
72
  end
73
+
74
+ unless @sources.empty?
75
+ @owner.class_eval("# frozen_string_literal: true\n" + @sources.join(";"), @path, @line - 1)
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thread"
4
3
  require "monitor"
5
4
 
6
5
  module ActiveSupport