activesupport 7.1.0.beta1 → 7.1.0.rc1

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: b700c44e30a586bad9303faa7189ffbab6e529983cd8813251a698390ca0739d
4
- data.tar.gz: 44ecf71d5e2b51d0461e81e3e72b9dbf6611c25ef6eb4fe24dbf054c8488cd92
3
+ metadata.gz: 680e4677ad9c5c80f0e8ca9b8fe7e4df0706ff259937be2547ba2e73fefc2c59
4
+ data.tar.gz: 80dbd580c5d1ff3f342599ca0162c20845a7b0ea6a8fa0c88abea51643569ae3
5
5
  SHA512:
6
- metadata.gz: e31bf27329b619e70a79be7eab163b0cc6f4da5e833c75ee009bc33d7f2573cbc53dcda7f7e950177eb6304d9d2bf7ff997d4d5a2deaec750abadd04a9d95f10
7
- data.tar.gz: d5a11fec498e5a0163e4f0d25994ec42c53b05db43cef312078057a200b3c84579bf31931d750d7502c497d6fa73d0d845af0c3c16748721c303459e45a86ace
6
+ metadata.gz: a3dca2799c3af8ac3a5298a5a67061cf4225bdc388972908f072c877d0c5108b714576db0b550b967c54526c785dd9f601fbc6a4b3720d90bd016ed200088227
7
+ data.tar.gz: 53b99d38845de0067923c74518c21f2a370f8595e0eb6ad37a0beb5d3c8f2685e774a4aabb361e63aff7b699922fed4615db9e94c36db08f9e7acebff10ab26d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
+ ## Rails 7.1.0.rc1 (September 27, 2023) ##
2
+
3
+ * Add a new public API for broadcasting logs
4
+
5
+ This feature existed for a while but was until now a private API.
6
+ Broadcasting log allows to send log message to difference sinks (STDOUT, a file ...) and
7
+ is used by default in the development environment to write logs both on STDOUT and in the
8
+ "development.log" file.
9
+
10
+ Basic usage:
11
+
12
+ ```ruby
13
+ stdout_logger = Logger.new(STDOUT)
14
+ file_logger = Logger.new("development.log")
15
+ broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)
16
+
17
+ broadcast.info("Hello!") # The "Hello!" message is written on STDOUT and in the log file.
18
+ ```
19
+
20
+ Adding other sink(s) to the broadcast:
21
+
22
+ ```ruby
23
+ broadcast = ActiveSupport::BroadcastLogger.new
24
+ broadcast.broadcast_to(Logger.new(STDERR))
25
+ ```
26
+
27
+ Remove a sink from the broadcast:
28
+
29
+ ```ruby
30
+ stdout_logger = Logger.new(STDOUT)
31
+ broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger)
32
+
33
+ broadcast.stop_broadcasting_to(stdout_logger)
34
+ ```
35
+
36
+ *Edouard Chin*
37
+
38
+ * Fix Range#overlap? not taking empty ranges into account on Ruby < 3.3
39
+
40
+ *Nobuyoshi Nakada*, *Shouichi Kamiya*, *Hartley McGuire*
41
+
42
+ * Use Ruby 3.3 Range#overlap? if available
43
+
44
+ *Yasuo Honda*
45
+
46
+
1
47
  ## Rails 7.1.0.beta1 (September 13, 2023) ##
2
48
 
49
+ * Add `bigdecimal` as Active Support dependency that is a bundled gem candidate for Ruby 3.4.
50
+
51
+ `bigdecimal` 3.1.4 or higher version will be installed.
52
+ Ruby 2.7 and 3.0 users who want `bigdecimal` version 2.0.0 or 3.0.0 behavior as a default gem,
53
+ pin the `bigdecimal` version in your application Gemfile.
54
+
55
+ *Koichi ITO*
56
+
3
57
  * Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
4
58
 
5
59
  *Yasuo Honda*
@@ -366,7 +420,7 @@
366
420
  ```ruby
367
421
  travel_to Time.new(2004, 11, 24) do
368
422
  # Inside the `travel_to` block `Time.new` is stubbed
369
- assert_equal Time.new.year, 2004
423
+ assert_equal 2004, Time.new.year
370
424
  end
371
425
  ```
372
426
 
@@ -434,7 +488,7 @@
434
488
  string.slice!(0, 1).html_safe? # => true
435
489
  # maintain html_safe? after the slice!
436
490
  string.html_safe? # => true
437
- string.chr # => true
491
+ string.chr.html_safe? # => true
438
492
  ```
439
493
 
440
494
  *Michael Go*
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # = Active Support Broadcast Logger
5
+ #
6
+ # The Broadcast logger is a logger used to write messages to multiple IO. It is commonly used
7
+ # in development to display messages on STDOUT and also write them to a file (development.log).
8
+ # With the Broadcast logger, you can broadcast your logs to a unlimited number of sinks.
9
+ #
10
+ # The BroadcastLogger acts as a standard logger and all methods you are used to are available.
11
+ # However, all the methods on this logger will propagate and be delegated to the other loggers
12
+ # that are part of the broadcast.
13
+ #
14
+ # Broadcasting your logs.
15
+ #
16
+ # stdout_logger = Logger.new(STDOUT)
17
+ # file_logger = Logger.new("development.log")
18
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
19
+ #
20
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
21
+ #
22
+ # Add a logger to the broadcast.
23
+ #
24
+ # stdout_logger = Logger.new(STDOUT)
25
+ # broadcast = BroadcastLogger.new(stdout_logger)
26
+ # file_logger = Logger.new("development.log")
27
+ # broadcast.broadcast_to(file_logger)
28
+ #
29
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
30
+ #
31
+ # Modifying the log level for all broadcasted loggers.
32
+ #
33
+ # stdout_logger = Logger.new(STDOUT)
34
+ # file_logger = Logger.new("development.log")
35
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
36
+ #
37
+ # broadcast.level = Logger::FATAL # Modify the log level for the whole broadcast.
38
+ #
39
+ # Stop broadcasting log to a sink.
40
+ #
41
+ # stdout_logger = Logger.new(STDOUT)
42
+ # file_logger = Logger.new("development.log")
43
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
44
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
45
+ #
46
+ # broadcast.stop_broadcasting_to(file_logger)
47
+ # broadcast.info("Hello world!") # Writes the log *only* to STDOUT.
48
+ #
49
+ # At least one sink has to be part of the broadcast. Otherwise, your logs will not
50
+ # be written anywhere. For instance:
51
+ #
52
+ # broadcast = BroadcastLogger.new
53
+ # broadcast.info("Hello world") # The log message will appear nowhere.
54
+ class BroadcastLogger
55
+ include ActiveSupport::LoggerSilence
56
+
57
+ # Returns all the logger that are part of this broadcast.
58
+ attr_reader :broadcasts
59
+ attr_reader :formatter
60
+ attr_accessor :progname
61
+
62
+ def initialize(*loggers)
63
+ @broadcasts = []
64
+ @progname = "Broadcast"
65
+
66
+ broadcast_to(*loggers)
67
+ end
68
+
69
+ # Add logger(s) to the broadcast.
70
+ #
71
+ # broadcast_logger = ActiveSupport::BroadcastLogger.new
72
+ # broadcast_logger.broadcast_to(Logger.new(STDOUT), Logger.new(STDERR))
73
+ def broadcast_to(*loggers)
74
+ @broadcasts.concat(loggers)
75
+ end
76
+
77
+ # Remove a logger from the broadcast. When a logger is removed, messages sent to
78
+ # the broadcast will no longer be written to its sink.
79
+ #
80
+ # sink = Logger.new(STDOUT)
81
+ # broadcast_logger = ActiveSupport::BroadcastLogger.new
82
+ #
83
+ # broadcast_logger.stop_broadcasting_to(sink)
84
+ def stop_broadcasting_to(logger)
85
+ @broadcasts.delete(logger)
86
+ end
87
+
88
+ def level
89
+ @broadcasts.map(&:level).min
90
+ end
91
+
92
+ def <<(message)
93
+ dispatch { |logger| logger.<<(message) }
94
+ end
95
+
96
+ def add(*args, &block)
97
+ dispatch { |logger| logger.add(*args, &block) }
98
+ end
99
+ alias_method :log, :add
100
+
101
+ def debug(*args, &block)
102
+ dispatch { |logger| logger.debug(*args, &block) }
103
+ end
104
+
105
+ def info(*args, &block)
106
+ dispatch { |logger| logger.info(*args, &block) }
107
+ end
108
+
109
+ def warn(*args, &block)
110
+ dispatch { |logger| logger.warn(*args, &block) }
111
+ end
112
+
113
+ def error(*args, &block)
114
+ dispatch { |logger| logger.error(*args, &block) }
115
+ end
116
+
117
+ def fatal(*args, &block)
118
+ dispatch { |logger| logger.fatal(*args, &block) }
119
+ end
120
+
121
+ def unknown(*args, &block)
122
+ dispatch { |logger| logger.unknown(*args, &block) }
123
+ end
124
+
125
+ def formatter=(formatter)
126
+ dispatch { |logger| logger.formatter = formatter }
127
+
128
+ @formatter = formatter
129
+ end
130
+
131
+ def level=(level)
132
+ dispatch { |logger| logger.level = level }
133
+ end
134
+ alias_method :sev_threshold=, :level=
135
+
136
+ def local_level=(level)
137
+ dispatch do |logger|
138
+ logger.local_level = level if logger.respond_to?(:local_level=)
139
+ end
140
+ end
141
+
142
+ def close
143
+ dispatch { |logger| logger.close }
144
+ end
145
+
146
+ # +True+ if the log level allows entries with severity Logger::DEBUG to be written
147
+ # to at least one broadcast. +False+ otherwise.
148
+ def debug?
149
+ @broadcasts.any? { |logger| logger.debug? }
150
+ end
151
+
152
+ # Sets the log level to Logger::DEBUG for the whole broadcast.
153
+ def debug!
154
+ dispatch { |logger| logger.debug! }
155
+ end
156
+
157
+ # +True+ if the log level allows entries with severity Logger::INFO to be written
158
+ # to at least one broadcast. +False+ otherwise.
159
+ def info?
160
+ @broadcasts.any? { |logger| logger.info? }
161
+ end
162
+
163
+ # Sets the log level to Logger::INFO for the whole broadcast.
164
+ def info!
165
+ dispatch { |logger| logger.info! }
166
+ end
167
+
168
+ # +True+ if the log level allows entries with severity Logger::WARN to be written
169
+ # to at least one broadcast. +False+ otherwise.
170
+ def warn?
171
+ @broadcasts.any? { |logger| logger.warn? }
172
+ end
173
+
174
+ # Sets the log level to Logger::WARN for the whole broadcast.
175
+ def warn!
176
+ dispatch { |logger| logger.warn! }
177
+ end
178
+
179
+ # +True+ if the log level allows entries with severity Logger::ERROR to be written
180
+ # to at least one broadcast. +False+ otherwise.
181
+ def error?
182
+ @broadcasts.any? { |logger| logger.error? }
183
+ end
184
+
185
+ # Sets the log level to Logger::ERROR for the whole broadcast.
186
+ def error!
187
+ dispatch { |logger| logger.error! }
188
+ end
189
+
190
+ # +True+ if the log level allows entries with severity Logger::FATAL to be written
191
+ # to at least one broadcast. +False+ otherwise.
192
+ def fatal?
193
+ @broadcasts.any? { |logger| logger.fatal? }
194
+ end
195
+
196
+ # Sets the log level to Logger::FATAL for the whole broadcast.
197
+ def fatal!
198
+ dispatch { |logger| logger.fatal! }
199
+ end
200
+
201
+ private
202
+ def dispatch(&block)
203
+ @broadcasts.each { |logger| block.call(logger) }
204
+ end
205
+ end
206
+ end
@@ -743,7 +743,7 @@ module ActiveSupport
743
743
  #
744
744
  # The callback can be specified as a symbol naming an instance method; as a
745
745
  # proc, lambda, or block; or as an object that responds to a certain method
746
- # determined by the <tt>:scope</tt> argument to +define_callbacks+.
746
+ # determined by the <tt>:scope</tt> argument to #define_callbacks.
747
747
  #
748
748
  # If a proc, lambda, or block is given, its body is evaluated in the context
749
749
  # of the current object. It can also optionally accept the current object as
@@ -787,10 +787,13 @@ module ActiveSupport
787
787
  end
788
788
  end
789
789
 
790
- # Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
790
+ # Skip a previously set callback. Like #set_callback, <tt>:if</tt> or
791
791
  # <tt>:unless</tt> options may be passed in order to control when the
792
792
  # callback is skipped.
793
793
  #
794
+ # Note: this example uses +PersonRecord+ and +#saving_message+, which you
795
+ # can see defined here[rdoc-ref:ActiveSupport::Callbacks]
796
+ #
794
797
  # class Writer < PersonRecord
795
798
  # attr_accessor :age
796
799
  # skip_callback :save, :before, :saving_message, if: -> { age > 18 }
@@ -933,7 +936,7 @@ module ActiveSupport
933
936
  # <tt>!</tt>, <tt>?</tt> or <tt>=</tt>.
934
937
  #
935
938
  # Calling +define_callbacks+ multiple times with the same +names+ will
936
- # overwrite previous callbacks registered with +set_callback+.
939
+ # overwrite previous callbacks registered with #set_callback.
937
940
  def define_callbacks(*names)
938
941
  options = names.extract_options!
939
942
 
@@ -1,6 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deep_mergeable"
4
+
3
5
  class Hash
6
+ include ActiveSupport::DeepMergeable
7
+
8
+ ##
9
+ # :method: deep_merge
10
+ # :call-seq: deep_merge(other_hash, &block)
11
+ #
4
12
  # Returns a new hash with +self+ and +other_hash+ merged recursively.
5
13
  #
6
14
  # h1 = { a: true, b: { c: [1, 2, 3] } }
@@ -15,20 +23,20 @@ class Hash
15
23
  # h2 = { b: 250, c: { c1: 200 } }
16
24
  # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
17
25
  # # => { a: 100, b: 450, c: { c1: 300 } }
18
- def deep_merge(other_hash, &block)
19
- dup.deep_merge!(other_hash, &block)
20
- end
26
+ #
27
+ #--
28
+ # Implemented by ActiveSupport::DeepMergeable#deep_merge.
29
+
30
+ ##
31
+ # :method: deep_merge!
32
+ # :call-seq: deep_merge!(other_hash, &block)
33
+ #
34
+ # Same as #deep_merge, but modifies +self+.
35
+ #
36
+ #--
37
+ # Implemented by ActiveSupport::DeepMergeable#deep_merge!.
21
38
 
22
- # Same as +deep_merge+, but modifies +self+.
23
- def deep_merge!(other_hash, &block)
24
- merge!(other_hash) do |key, this_val, other_val|
25
- if this_val.is_a?(Hash) && other_val.is_a?(Hash)
26
- this_val.deep_merge(other_val, &block)
27
- elsif block_given?
28
- block.call(key, this_val, other_val)
29
- else
30
- other_val
31
- end
32
- end
39
+ def deep_merge?(other) # :nodoc:
40
+ other.is_a?(Hash)
33
41
  end
34
42
  end
@@ -4,8 +4,36 @@ class Range
4
4
  # Compare two ranges and see if they overlap each other
5
5
  # (1..5).overlap?(4..6) # => true
6
6
  # (1..5).overlap?(7..9) # => false
7
- def overlap?(other)
8
- other.begin == self.begin || cover?(other.begin) || other.cover?(self.begin)
7
+ unless Range.method_defined?(:overlap?)
8
+ def overlap?(other)
9
+ raise TypeError unless other.is_a? Range
10
+
11
+ self_begin = self.begin
12
+ other_end = other.end
13
+ other_excl = other.exclude_end?
14
+
15
+ return false if _empty_range?(self_begin, other_end, other_excl)
16
+
17
+ other_begin = other.begin
18
+ self_end = self.end
19
+ self_excl = self.exclude_end?
20
+
21
+ return false if _empty_range?(other_begin, self_end, self_excl)
22
+ return true if self_begin == other_begin
23
+
24
+ return false if _empty_range?(self_begin, self_end, self_excl)
25
+ return false if _empty_range?(other_begin, other_end, other_excl)
26
+
27
+ true
28
+ end
29
+
30
+ private
31
+ def _empty_range?(b, e, excl)
32
+ return false if b.nil? || e.nil?
33
+
34
+ comp = b <=> e
35
+ comp.nil? || comp > 0 || (comp == 0 && excl)
36
+ end
9
37
  end
10
38
 
11
39
  alias :overlaps? :overlap?
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Provides +deep_merge+ and +deep_merge!+ methods. Expects the including class
5
+ # to provide a <tt>merge!(other, &block)</tt> method.
6
+ module DeepMergeable # :nodoc:
7
+ # Returns a new instance with the values from +other+ merged recursively.
8
+ #
9
+ # class Hash
10
+ # include ActiveSupport::DeepMergeable
11
+ # end
12
+ #
13
+ # hash_1 = { a: true, b: { c: [1, 2, 3] } }
14
+ # hash_2 = { a: false, b: { x: [3, 4, 5] } }
15
+ #
16
+ # hash_1.deep_merge(hash_2)
17
+ # # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
18
+ #
19
+ # A block can be provided to merge non-<tt>DeepMergeable</tt> values:
20
+ #
21
+ # hash_1 = { a: 100, b: 200, c: { c1: 100 } }
22
+ # hash_2 = { b: 250, c: { c1: 200 } }
23
+ #
24
+ # hash_1.deep_merge(hash_2) do |key, this_val, other_val|
25
+ # this_val + other_val
26
+ # end
27
+ # # => { a: 100, b: 450, c: { c1: 300 } }
28
+ #
29
+ def deep_merge(other, &block)
30
+ dup.deep_merge!(other, &block)
31
+ end
32
+
33
+ # Same as #deep_merge, but modifies +self+.
34
+ def deep_merge!(other, &block)
35
+ merge!(other) do |key, this_val, other_val|
36
+ if this_val.is_a?(DeepMergeable) && this_val.deep_merge?(other_val)
37
+ this_val.deep_merge(other_val, &block)
38
+ elsif block_given?
39
+ block.call(key, this_val, other_val)
40
+ else
41
+ other_val
42
+ end
43
+ end
44
+ end
45
+
46
+ # Returns true if +other+ can be deep merged into +self+. Classes may
47
+ # override this method to restrict or expand the domain of deep mergeable
48
+ # values. Defaults to checking that +other+ is of type +self.class+.
49
+ def deep_merge?(other)
50
+ other.is_a?(self.class)
51
+ end
52
+ end
53
+ end
@@ -10,7 +10,7 @@ module ActiveSupport
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
12
  TINY = 0
13
- PRE = "beta1"
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -19,64 +19,6 @@ module ActiveSupport
19
19
  sources.any? { |source| source == logger_source }
20
20
  end
21
21
 
22
- # Broadcasts logs to multiple loggers.
23
- def self.broadcast(logger) # :nodoc:
24
- Module.new do
25
- define_method(:add) do |*args, &block|
26
- logger.add(*args, &block)
27
- super(*args, &block)
28
- end
29
-
30
- define_method(:<<) do |x|
31
- logger << x
32
- super(x)
33
- end
34
-
35
- define_method(:close) do
36
- logger.close
37
- super()
38
- end
39
-
40
- define_method(:progname=) do |name|
41
- logger.progname = name
42
- super(name)
43
- end
44
-
45
- define_method(:formatter=) do |formatter|
46
- logger.formatter = formatter
47
- super(formatter)
48
- end
49
-
50
- define_method(:level=) do |level|
51
- logger.level = level
52
- super(level)
53
- end
54
-
55
- define_method(:local_level=) do |level|
56
- logger.local_level = level if logger.respond_to?(:local_level=)
57
- super(level) if respond_to?(:local_level=)
58
- end
59
-
60
- define_method(:silence) do |level = Logger::ERROR, &block|
61
- if logger.respond_to?(:silence)
62
- logger.silence(level) do
63
- if defined?(super)
64
- super(level, &block)
65
- else
66
- block.call(self)
67
- end
68
- end
69
- else
70
- if defined?(super)
71
- super(level, &block)
72
- else
73
- block.call(self)
74
- end
75
- end
76
- end
77
- end
78
- end
79
-
80
22
  def initialize(*args, **kwargs)
81
23
  super
82
24
  @formatter ||= SimpleFormatter.new
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/concern"
4
- require "active_support/core_ext/module/attribute_accessors"
5
- require "concurrent"
6
- require "fiber"
4
+ require "logger"
7
5
 
8
6
  module ActiveSupport
9
7
  module LoggerThreadSafeLevel # :nodoc:
@@ -88,7 +88,7 @@ module ActiveSupport
88
88
  initializer "active_support.initialize_time_zone" do |app|
89
89
  begin
90
90
  TZInfo::DataSource.get
91
- rescue TZInfo::DataSourceNotFound => e
91
+ rescue TZInfo::DataSourceNotFound, TZInfo::ZoneinfoDirectoryNotFound => e
92
92
  raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
93
93
  end
94
94
  require "active_support/core_ext/time/zones"
@@ -3,7 +3,7 @@
3
3
  module ActiveSupport
4
4
  module Testing
5
5
  module ErrorReporterAssertions
6
- module ErrorCollector
6
+ module ErrorCollector # :nodoc:
7
7
  @subscribed = false
8
8
  @mutex = Mutex.new
9
9
 
@@ -51,58 +51,57 @@ module ActiveSupport
51
51
  end
52
52
  end
53
53
 
54
- private
55
- # Assertion that the block should not cause an exception to be reported
56
- # to +Rails.error+.
57
- #
58
- # Passes if evaluated code in the yielded block reports no exception.
59
- #
60
- # assert_no_error_reported do
61
- # perform_service(param: 'no_exception')
62
- # end
63
- def assert_no_error_reported(&block)
64
- reports = ErrorCollector.record do
65
- _assert_nothing_raised_or_warn("assert_no_error_reported", &block)
66
- end
67
- assert_predicate(reports, :empty?)
54
+ # Assertion that the block should not cause an exception to be reported
55
+ # to +Rails.error+.
56
+ #
57
+ # Passes if evaluated code in the yielded block reports no exception.
58
+ #
59
+ # assert_no_error_reported do
60
+ # perform_service(param: 'no_exception')
61
+ # end
62
+ def assert_no_error_reported(&block)
63
+ reports = ErrorCollector.record do
64
+ _assert_nothing_raised_or_warn("assert_no_error_reported", &block)
68
65
  end
66
+ assert_predicate(reports, :empty?)
67
+ end
69
68
 
70
- # Assertion that the block should cause at least one exception to be reported
71
- # to +Rails.error+.
72
- #
73
- # Passes if the evaluated code in the yielded block reports a matching exception.
74
- #
75
- # assert_error_reported(IOError) do
76
- # Rails.error.report(IOError.new("Oops"))
77
- # end
78
- #
79
- # To test further details about the reported exception, you can use the return
80
- # value.
81
- #
82
- # report = assert_error_reported(IOError) do
83
- # # ...
84
- # end
85
- # assert_equal "Oops", report.error.message
86
- # assert_equal "admin", report.context[:section]
87
- # assert_equal :warning, report.severity
88
- # assert_predicate report, :handled?
89
- def assert_error_reported(error_class = StandardError, &block)
90
- reports = ErrorCollector.record do
91
- _assert_nothing_raised_or_warn("assert_error_reported", &block)
92
- end
69
+ # Assertion that the block should cause at least one exception to be reported
70
+ # to +Rails.error+.
71
+ #
72
+ # Passes if the evaluated code in the yielded block reports a matching exception.
73
+ #
74
+ # assert_error_reported(IOError) do
75
+ # Rails.error.report(IOError.new("Oops"))
76
+ # end
77
+ #
78
+ # To test further details about the reported exception, you can use the return
79
+ # value.
80
+ #
81
+ # report = assert_error_reported(IOError) do
82
+ # # ...
83
+ # end
84
+ # assert_equal "Oops", report.error.message
85
+ # assert_equal "admin", report.context[:section]
86
+ # assert_equal :warning, report.severity
87
+ # assert_predicate report, :handled?
88
+ def assert_error_reported(error_class = StandardError, &block)
89
+ reports = ErrorCollector.record do
90
+ _assert_nothing_raised_or_warn("assert_error_reported", &block)
91
+ end
93
92
 
94
- if reports.empty?
95
- assert(false, "Expected a #{error_class.name} to be reported, but there were no errors reported.")
96
- elsif (report = reports.find { |r| error_class === r.error })
97
- self.assertions += 1
98
- report
99
- else
100
- message = "Expected a #{error_class.name} to be reported, but none of the " \
101
- "#{reports.size} reported errors matched: \n" \
102
- "#{reports.map { |r| r.error.class.name }.join("\n ")}"
103
- assert(false, message)
104
- end
93
+ if reports.empty?
94
+ assert(false, "Expected a #{error_class.name} to be reported, but there were no errors reported.")
95
+ elsif (report = reports.find { |r| error_class === r.error })
96
+ self.assertions += 1
97
+ report
98
+ else
99
+ message = "Expected a #{error_class.name} to be reported, but none of the " \
100
+ "#{reports.size} reported errors matched: \n" \
101
+ "#{reports.map { |r| r.error.class.name }.join("\n ")}"
102
+ assert(false, message)
105
103
  end
104
+ end
106
105
  end
107
106
  end
108
107
  end
@@ -28,6 +28,7 @@ require "active_support/dependencies/autoload"
28
28
  require "active_support/version"
29
29
  require "active_support/deprecator"
30
30
  require "active_support/logger"
31
+ require "active_support/broadcast_logger"
31
32
  require "active_support/lazy_load_hooks"
32
33
  require "active_support/core_ext/date_and_time/compatibility"
33
34
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0.beta1
4
+ version: 7.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -165,6 +165,7 @@ files:
165
165
  - lib/active_support/array_inquirer.rb
166
166
  - lib/active_support/backtrace_cleaner.rb
167
167
  - lib/active_support/benchmarkable.rb
168
+ - lib/active_support/broadcast_logger.rb
168
169
  - lib/active_support/builder.rb
169
170
  - lib/active_support/cache.rb
170
171
  - lib/active_support/cache/coder.rb
@@ -306,6 +307,7 @@ files:
306
307
  - lib/active_support/core_ext/time/zones.rb
307
308
  - lib/active_support/current_attributes.rb
308
309
  - lib/active_support/current_attributes/test_helper.rb
310
+ - lib/active_support/deep_mergeable.rb
309
311
  - lib/active_support/dependencies.rb
310
312
  - lib/active_support/dependencies/autoload.rb
311
313
  - lib/active_support/dependencies/interlock.rb
@@ -444,10 +446,10 @@ licenses:
444
446
  - MIT
445
447
  metadata:
446
448
  bug_tracker_uri: https://github.com/rails/rails/issues
447
- changelog_uri: https://github.com/rails/rails/blob/v7.1.0.beta1/activesupport/CHANGELOG.md
448
- documentation_uri: https://api.rubyonrails.org/v7.1.0.beta1/
449
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.0.rc1/activesupport/CHANGELOG.md
450
+ documentation_uri: https://api.rubyonrails.org/v7.1.0.rc1/
449
451
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
450
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0.beta1/activesupport
452
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.0.rc1/activesupport
451
453
  rubygems_mfa_required: 'true'
452
454
  post_install_message:
453
455
  rdoc_options: