activesupport 7.2.2 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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