activesupport 7.1.0.beta1 → 7.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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: