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 +4 -4
- data/CHANGELOG.md +56 -2
- data/lib/active_support/broadcast_logger.rb +206 -0
- data/lib/active_support/callbacks.rb +6 -3
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/range/overlap.rb +30 -2
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/logger.rb +0 -58
- data/lib/active_support/logger_thread_safe_level.rb +1 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/testing/error_reporter_assertions.rb +48 -49
- data/lib/active_support.rb +1 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 680e4677ad9c5c80f0e8ca9b8fe7e4df0706ff259937be2547ba2e73fefc2c59
|
4
|
+
data.tar.gz: 80dbd580c5d1ff3f342599ca0162c20845a7b0ea6a8fa0c88abea51643569ae3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
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
|
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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
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
|
-
|
8
|
-
|
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
|
@@ -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
|
@@ -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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
data/lib/active_support.rb
CHANGED
@@ -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.
|
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-
|
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.
|
448
|
-
documentation_uri: https://api.rubyonrails.org/v7.1.0.
|
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.
|
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:
|