activesupport 7.1.2 → 7.1.3.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6db71966858e675d32617069b0df8dc17b1c5dfe8123c87ae96a28fdb6e2f5e6
4
- data.tar.gz: 81ffe410567130147cd0c6f74943d40404a4031b2cf30f12bfaa2ee698cd5a57
3
+ metadata.gz: 63e4b9598ffeea57d9aa5ab27deb5249cc21324883d53ad536bb02fd5d8e4526
4
+ data.tar.gz: 82041b4d7a4b287404280f004cc9a255ad55ec975682ceb4829be789bce352bb
5
5
  SHA512:
6
- metadata.gz: 99a9131ff9f97e739719621df9ba0a33d3b2fad9b1315397382235f29d33ee130f701d0c0ed767eacf01ccb31607eb26d7f5bb95f37ad86ac57f18817cd9b253
7
- data.tar.gz: ffa6a0ffe90b88c87f65d85ddb32390d20f8c34ab2517f797c34d325839cbf434a0202650cdd54f118bee9a299cf478f83af4222c313f2746e267bbd19003914
6
+ metadata.gz: b0e517fefe56838a7851ec1832ea1cb9fbc10aa392da9f3840ee7d71b0768d29825e03176b5358a5e098ed42686d0602bd13ebb08a750e6294992fb3ac845555
7
+ data.tar.gz: d58c4664ef7962fab547b4d5dc91e7cca0ac647b0b4e080c49129c06ca9d0604dc7d4ee2f9e0347a1100d435789923aafb94adfa49c6cb7f031e18b1e44d798f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,60 @@
1
+ ## Rails 7.1.3.4 (June 04, 2024) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.1.3.3 (May 16, 2024) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 7.1.3.2 (February 21, 2024) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 7.1.3.1 (February 21, 2024) ##
17
+
18
+ * No changes.
19
+
20
+
21
+ ## Rails 7.1.3 (January 16, 2024) ##
22
+
23
+ * Handle nil `backtrace_locations` in `ActiveSupport::SyntaxErrorProxy`.
24
+
25
+ *Eugene Kenny*
26
+
27
+ * Fix `ActiveSupport::JSON.encode` to prevent duplicate keys.
28
+
29
+ If the same key exist in both String and Symbol form it could
30
+ lead to the same key being emitted twice.
31
+
32
+ *Manish Sharma*
33
+
34
+ * Fix `ActiveSupport::Cache::Store#read_multi` when using a cache namespace
35
+ and local cache strategy.
36
+
37
+ *Mark Oleson*
38
+
39
+ * Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
40
+
41
+ There is a bug in the current implementation of #travel_to:
42
+ it remembers a timezone of its argument, and all stubbed methods start
43
+ returning results in that remembered timezone. However, the expected
44
+ behaviour is to return results in a system timezone.
45
+
46
+ *Aleksei Chernenkov*
47
+
48
+ * Fix `:unless_exist` option for `MemoryStore#write` (et al) when using a
49
+ cache namespace.
50
+
51
+ *S. Brent Faulkner*
52
+
53
+ * Fix ActiveSupport::Deprecation to handle blaming generated code.
54
+
55
+ *Jean Boussier*, *fatkodima*
56
+
57
+
1
58
  ## Rails 7.1.2 (November 10, 2023) ##
2
59
 
3
60
  * Fix `:expires_in` option for `RedisCacheStore#write_multi`.
@@ -24,11 +24,11 @@ module ActiveSupport
24
24
  #
25
25
  # Special features:
26
26
  # - Clustering and load balancing. One can specify multiple memcached servers,
27
- # and MemCacheStore will load balance between all available servers. If a
28
- # server goes down, then MemCacheStore will ignore it until it comes back up.
27
+ # and +MemCacheStore+ will load balance between all available servers. If a
28
+ # server goes down, then +MemCacheStore+ will ignore it until it comes back up.
29
29
  #
30
- # MemCacheStore implements the Strategy::LocalCache strategy which implements
31
- # an in-memory cache inside of a block.
30
+ # +MemCacheStore+ implements the Strategy::LocalCache strategy which
31
+ # implements an in-memory cache inside of a block.
32
32
  class MemCacheStore < Store
33
33
  # These options represent behavior overridden by this implementation and should
34
34
  # not be allowed to get down to the Dalli client
@@ -106,14 +106,14 @@ module ActiveSupport
106
106
  end
107
107
  end
108
108
 
109
- # Creates a new MemCacheStore object, with the given memcached server
109
+ # Creates a new +MemCacheStore+ object, with the given memcached server
110
110
  # addresses. Each address is either a host name, or a host-with-port string
111
111
  # in the form of "host_name:port". For example:
112
112
  #
113
113
  # ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
114
114
  #
115
115
  # If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
116
- # MemCacheStore will connect to localhost:11211 (the default memcached port).
116
+ # +MemCacheStore+ will connect to localhost:11211 (the default memcached port).
117
117
  # Passing a +Dalli::Client+ instance is deprecated and will be removed. Please pass an address instead.
118
118
  def initialize(*addresses)
119
119
  addresses = addresses.flatten
@@ -18,13 +18,13 @@ module ActiveSupport
18
18
  # a cleanup will occur which tries to prune the cache down to three quarters
19
19
  # of the maximum size by removing the least recently used entries.
20
20
  #
21
- # Unlike other Cache store implementations, MemoryStore does not compress
22
- # values by default. MemoryStore does not benefit from compression as much
21
+ # Unlike other Cache store implementations, +MemoryStore+ does not compress
22
+ # values by default. +MemoryStore+ does not benefit from compression as much
23
23
  # as other Store implementations, as it does not send data over a network.
24
24
  # However, when compression is enabled, it still pays the full cost of
25
25
  # compression in terms of cpu use.
26
26
  #
27
- # MemoryStore is thread-safe.
27
+ # +MemoryStore+ is thread-safe.
28
28
  class MemoryStore < Store
29
29
  module DupCoder # :nodoc:
30
30
  extend self
@@ -209,7 +209,7 @@ module ActiveSupport
209
209
  def write_entry(key, entry, **options)
210
210
  payload = serialize_entry(entry, **options)
211
211
  synchronize do
212
- return false if options[:unless_exist] && exist?(key)
212
+ return false if options[:unless_exist] && exist?(key, namespace: nil)
213
213
 
214
214
  old_payload = @data[key]
215
215
  if old_payload
@@ -19,22 +19,23 @@ module ActiveSupport
19
19
  module Cache
20
20
  # = Redis \Cache \Store
21
21
  #
22
- # Deployment note: Take care to use a *dedicated Redis cache* rather
23
- # than pointing this at your existing Redis server. It won't cope well
24
- # with mixed usage patterns and it won't expire cache entries by default.
22
+ # Deployment note: Take care to use a <b>dedicated Redis cache</b> rather
23
+ # than pointing this at a persistent Redis server (for example, one used as
24
+ # an Active Job queue). Redis won't cope well with mixed usage patterns and it
25
+ # won't expire cache entries by default.
25
26
  #
26
27
  # Redis cache server setup guide: https://redis.io/topics/lru-cache
27
28
  #
28
- # * Supports vanilla Redis, hiredis, and Redis::Distributed.
29
- # * Supports Memcached-like sharding across Redises with Redis::Distributed.
29
+ # * Supports vanilla Redis, hiredis, and +Redis::Distributed+.
30
+ # * Supports Memcached-like sharding across Redises with +Redis::Distributed+.
30
31
  # * Fault tolerant. If the Redis server is unavailable, no exceptions are
31
32
  # raised. Cache fetches are all misses and writes are dropped.
32
33
  # * Local cache. Hot in-memory primary cache within block/middleware scope.
33
- # * +read_multi+ and +write_multi+ support for Redis mget/mset. Use Redis::Distributed
34
- # 4.0.1+ for distributed mget support.
34
+ # * +read_multi+ and +write_multi+ support for Redis mget/mset. Use
35
+ # +Redis::Distributed+ 4.0.1+ for distributed mget support.
35
36
  # * +delete_matched+ support for Redis KEYS globs.
36
37
  class RedisCacheStore < Store
37
- # Keys are truncated with the ActiveSupport digest if they exceed 1kB
38
+ # Keys are truncated with the Active Support digest if they exceed 1kB
38
39
  MAX_KEY_BYTESIZE = 1024
39
40
 
40
41
  DEFAULT_REDIS_OPTIONS = {
@@ -110,8 +111,11 @@ module ActiveSupport
110
111
 
111
112
  # Creates a new Redis cache store.
112
113
  #
113
- # Handles four options: :redis block, :redis instance, single :url
114
- # string, and multiple :url strings.
114
+ # There are four ways to provide the Redis client used by the cache: the
115
+ # +:redis+ param can be a Redis instance or a block that returns a Redis
116
+ # instance, or the +:url+ param can be a string or an array of strings
117
+ # which will be used to create a Redis instance or a +Redis::Distributed+
118
+ # instance.
115
119
  #
116
120
  # Option Class Result
117
121
  # :redis Proc -> options[:redis].call
@@ -134,7 +138,7 @@ module ActiveSupport
134
138
  #
135
139
  # Race condition TTL is not set by default. This can be used to avoid
136
140
  # "thundering herd" cache writes when hot cache entries are expired.
137
- # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
141
+ # See ActiveSupport::Cache::Store#fetch for more.
138
142
  #
139
143
  # Setting <tt>skip_nil: true</tt> will not cache nil results:
140
144
  #
@@ -242,7 +246,7 @@ module ActiveSupport
242
246
  # Decrement a cached integer value using the Redis decrby atomic operator.
243
247
  # Returns the updated value.
244
248
  #
245
- # If the key is unset or has expired, it will be set to -amount:
249
+ # If the key is unset or has expired, it will be set to +-amount+:
246
250
  #
247
251
  # cache.decrement("foo") # => -1
248
252
  #
@@ -131,17 +131,20 @@ module ActiveSupport
131
131
  end
132
132
  end
133
133
 
134
- def read_multi_entries(keys, **options)
134
+ def read_multi_entries(names, **options)
135
135
  return super unless local_cache
136
136
 
137
- local_entries = local_cache.read_multi_entries(keys)
137
+ keys_to_names = names.index_by { |name| normalize_key(name, options) }
138
+
139
+ local_entries = local_cache.read_multi_entries(keys_to_names.keys)
140
+ local_entries.transform_keys! { |key| keys_to_names[key] }
138
141
  local_entries.transform_values! do |payload|
139
- deserialize_entry(payload)&.value
142
+ deserialize_entry(payload, **options)&.value
140
143
  end
141
- missed_keys = keys - local_entries.keys
144
+ missed_names = names - local_entries.keys
142
145
 
143
- if missed_keys.any?
144
- local_entries.merge!(super(missed_keys, **options))
146
+ if missed_names.any?
147
+ local_entries.merge!(super(missed_names, **options))
145
148
  else
146
149
  local_entries
147
150
  end
@@ -160,8 +160,8 @@ module ActiveSupport
160
160
  # Some implementations may not support all methods beyond the basic cache
161
161
  # methods of #fetch, #write, #read, #exist?, and #delete.
162
162
  #
163
- # ActiveSupport::Cache::Store can store any Ruby object that is supported by
164
- # its +coder+'s +dump+ and +load+ methods.
163
+ # +ActiveSupport::Cache::Store+ can store any Ruby object that is supported
164
+ # by its +coder+'s +dump+ and +load+ methods.
165
165
  #
166
166
  # cache = ActiveSupport::Cache::MemoryStore.new
167
167
  #
@@ -370,8 +370,8 @@ module ActiveSupport
370
370
  #
371
371
  # ==== Options
372
372
  #
373
- # Internally, +fetch+ calls #read_entry, and calls #write_entry on a cache
374
- # miss. Thus, +fetch+ supports the same options as #read and #write.
373
+ # Internally, +fetch+ calls +read_entry+, and calls +write_entry+ on a
374
+ # cache miss. Thus, +fetch+ supports the same options as #read and #write.
375
375
  # Additionally, +fetch+ supports the following options:
376
376
  #
377
377
  # * <tt>force: true</tt> - Forces a cache "miss," meaning we treat the
@@ -818,7 +818,7 @@ module ActiveSupport
818
818
  end
819
819
  end
820
820
 
821
- def deserialize_entry(payload)
821
+ def deserialize_entry(payload, **)
822
822
  payload.nil? ? nil : @coder.load(payload)
823
823
  rescue DeserializationError
824
824
  nil
@@ -1064,6 +1064,10 @@ module ActiveSupport
1064
1064
  end
1065
1065
  end
1066
1066
 
1067
+ # Enables the dynamic configuration of Cache entry options while ensuring
1068
+ # that conflicting options are not both set. When a block is given to
1069
+ # ActiveSupport::Cache::Store#fetch, the second argument will be an
1070
+ # instance of +WriteOptions+.
1067
1071
  class WriteOptions
1068
1072
  def initialize(options) # :nodoc:
1069
1073
  @options = options
@@ -1081,6 +1085,9 @@ module ActiveSupport
1081
1085
  @options[:expires_in]
1082
1086
  end
1083
1087
 
1088
+ # Sets the Cache entry's +expires_in+ value. If an +expires_at+ option was
1089
+ # previously set, this will unset it since +expires_in+ and +expires_at+
1090
+ # cannot both be set.
1084
1091
  def expires_in=(expires_in)
1085
1092
  @options.delete(:expires_at)
1086
1093
  @options[:expires_in] = expires_in
@@ -1090,6 +1097,9 @@ module ActiveSupport
1090
1097
  @options[:expires_at]
1091
1098
  end
1092
1099
 
1100
+ # Sets the Cache entry's +expires_at+ value. If an +expires_in+ option was
1101
+ # previously set, this will unset it since +expires_at+ and +expires_in+
1102
+ # cannot both be set.
1093
1103
  def expires_at=(expires_at)
1094
1104
  @options.delete(:expires_in)
1095
1105
  @options[:expires_at] = expires_at
@@ -68,7 +68,7 @@ class Object
68
68
  # You can access these methods using the class name instead:
69
69
  #
70
70
  # class Phone < ActiveRecord::Base
71
- # enum phone_number_type: { home: 0, office: 1, mobile: 2 }
71
+ # enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
72
72
  #
73
73
  # with_options presence: true do
74
74
  # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
@@ -24,7 +24,7 @@ class String
24
24
  #
25
25
  # The second argument, +indent_string+, specifies which indent string to
26
26
  # use. The default is +nil+, which tells the method to make a guess by
27
- # peeking at the first indented line, and fallback to a space if there is
27
+ # peeking at the first indented line, and fall back to a space if there is
28
28
  # none.
29
29
  #
30
30
  # " foo".indent(2) # => " foo"
@@ -57,15 +57,15 @@ module ActiveSupport
57
57
  # You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
58
58
  # constant. Available behaviors are:
59
59
  #
60
- # [+raise+] Raise ActiveSupport::DeprecationException.
61
- # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
62
- # [+log+] Log all deprecation warnings to +Rails.logger+.
63
- # [+notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
64
- # [+report+] Use ActiveSupport::ErrorReporter to report deprecations.
65
- # [+silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
60
+ # [+:raise+] Raise ActiveSupport::DeprecationException.
61
+ # [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
62
+ # [+:log+] Log all deprecation warnings to +Rails.logger+.
63
+ # [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
64
+ # [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
65
+ # [+:silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
66
66
  #
67
67
  # Setting behaviors only affects deprecations that happen after boot time.
68
- # For more information you can read the documentation of the +behavior=+ method.
68
+ # For more information you can read the documentation of the #behavior= method.
69
69
  module Behavior
70
70
  # Whether to print a backtrace along with the warning.
71
71
  attr_accessor :debug
@@ -85,12 +85,12 @@ module ActiveSupport
85
85
  #
86
86
  # Available behaviors:
87
87
  #
88
- # [+raise+] Raise ActiveSupport::DeprecationException.
89
- # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
90
- # [+log+] Log all deprecation warnings to +Rails.logger+.
91
- # [+notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
92
- # [+report+] Use ActiveSupport::ErrorReporter to report deprecations.
93
- # [+silence+] Do nothing.
88
+ # [+:raise+] Raise ActiveSupport::DeprecationException.
89
+ # [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
90
+ # [+:log+] Log all deprecation warnings to +Rails.logger+.
91
+ # [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
92
+ # [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
93
+ # [+:silence+] Do nothing.
94
94
  #
95
95
  # Setting behaviors only affects deprecations that happen after boot time.
96
96
  # Deprecation warnings raised by gems are not affected by this setting
@@ -104,15 +104,17 @@ module ActiveSupport
104
104
  # # custom stuff
105
105
  # }
106
106
  #
107
- # If you are using \Rails, you can set <tt>config.active_support.report_deprecations = false</tt> to disable
108
- # all deprecation behaviors. This is similar to the +silence+ option but more performant.
107
+ # If you are using \Rails, you can set
108
+ # <tt>config.active_support.report_deprecations = false</tt> to disable
109
+ # all deprecation behaviors. This is similar to the +:silence+ option but
110
+ # more performant.
109
111
  def behavior=(behavior)
110
112
  @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
111
113
  end
112
114
 
113
115
  # Sets the behavior for disallowed deprecations (those configured by
114
116
  # ActiveSupport::Deprecation#disallowed_warnings=) to the specified
115
- # value. As with +behavior=+, this can be a single value, array, or an
117
+ # value. As with #behavior=, this can be a single value, array, or an
116
118
  # object that responds to +call+.
117
119
  def disallowed_behavior=(behavior)
118
120
  @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
@@ -142,7 +142,9 @@ module ActiveSupport
142
142
  return _extract_callstack(callstack) if callstack.first.is_a? String
143
143
 
144
144
  offending_line = callstack.find { |frame|
145
- frame.absolute_path && !ignored_callstack(frame.absolute_path)
145
+ # Code generated with `eval` doesn't have an `absolute_path`, e.g. templates.
146
+ path = frame.absolute_path || frame.path
147
+ path && !ignored_callstack?(path)
146
148
  } || callstack.first
147
149
 
148
150
  [offending_line.path, offending_line.lineno, offending_line.label]
@@ -150,7 +152,7 @@ module ActiveSupport
150
152
 
151
153
  def _extract_callstack(callstack)
152
154
  warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
153
- offending_line = callstack.find { |line| !ignored_callstack(line) } || callstack.first
155
+ offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
154
156
 
155
157
  if offending_line
156
158
  if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
@@ -162,9 +164,10 @@ module ActiveSupport
162
164
  end
163
165
 
164
166
  RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/"
167
+ LIB_DIR = RbConfig::CONFIG["libdir"]
165
168
 
166
- def ignored_callstack(path)
167
- path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
169
+ def ignored_callstack?(path)
170
+ path.start_with?(RAILS_GEM_ROOT, LIB_DIR)
168
171
  end
169
172
  end
170
173
  end
@@ -9,8 +9,8 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 2
13
- PRE = nil
12
+ TINY = 3
13
+ PRE = "4"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -7,8 +7,18 @@ module ActiveSupport
7
7
  def translate(key, **options)
8
8
  if html_safe_translation_key?(key)
9
9
  html_safe_options = html_escape_translation_options(options)
10
- translation = I18n.translate(key, **html_safe_options)
11
- html_safe_translation(translation)
10
+
11
+ exception = false
12
+ exception_handler = ->(*args) do
13
+ exception = true
14
+ I18n.exception_handler.call(*args)
15
+ end
16
+ translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
17
+ if exception
18
+ translation
19
+ else
20
+ html_safe_translation(translation)
21
+ end
12
22
  else
13
23
  I18n.translate(key, **options)
14
24
  end
@@ -76,7 +76,7 @@ module ActiveSupport
76
76
  when Hash
77
77
  result = {}
78
78
  value.each do |k, v|
79
- k = k.to_s unless Symbol === k || String === k
79
+ k = k.to_s unless String === k
80
80
  result[k] = jsonify(v)
81
81
  end
82
82
  result