activesupport 6.0.6.1 → 7.1.3.2
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 +865 -438
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +30 -10
- data/lib/active_support/benchmarkable.rb +4 -3
- data/lib/active_support/broadcast_logger.rb +250 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +53 -20
- data/lib/active_support/cache/mem_cache_store.rb +208 -63
- data/lib/active_support/cache/memory_store.rb +120 -38
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +201 -208
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -66
- data/lib/active_support/cache.rb +539 -261
- data/lib/active_support/callbacks.rb +273 -142
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +53 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +19 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +19 -29
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +18 -16
- data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +146 -72
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +3 -4
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +5 -5
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
- data/lib/active_support/core_ext/module/concerning.rb +14 -8
- data/lib/active_support/core_ext/module/delegation.rb +75 -42
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +1 -26
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +15 -4
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +52 -28
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +51 -10
- data/lib/active_support/core_ext/string/inquiry.rb +2 -1
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +85 -194
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +46 -8
- data/lib/active_support/core_ext/time/conversions.rb +16 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +54 -22
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -769
- data/lib/active_support/deprecation/behaviors.rb +77 -38
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/instance_delegator.rb +31 -5
- data/lib/active_support/deprecation/method_wrappers.rb +12 -28
- data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
- data/lib/active_support/deprecation/reporting.rb +76 -16
- data/lib/active_support/deprecation.rb +36 -4
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -68
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -12
- data/lib/active_support/duration.rb +136 -56
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +46 -13
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +86 -137
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +31 -12
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +79 -0
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +86 -42
- data/lib/active_support/html_safe_translation.rb +53 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +29 -27
- data/lib/active_support/inflector/inflections.rb +26 -9
- data/lib/active_support/inflector/methods.rb +54 -64
- data/lib/active_support/inflector/transliterate.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +6 -5
- data/lib/active_support/json/encoding.rb +31 -45
- data/lib/active_support/key_generator.rb +32 -7
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +101 -32
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +24 -25
- data/lib/active_support/message_encryptor.rb +205 -58
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +237 -86
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +35 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +15 -52
- data/lib/active_support/multibyte/unicode.rb +8 -122
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +310 -105
- data/lib/active_support/notifications/instrumenter.rb +113 -48
- data/lib/active_support/notifications.rb +56 -29
- data/lib/active_support/number_helper/number_converter.rb +15 -8
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +379 -304
- data/lib/active_support/option_merger.rb +11 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +23 -3
- data/lib/active_support/parameter_filter.rb +104 -75
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +90 -6
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +18 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +5 -3
- data/lib/active_support/subscriber.rb +23 -47
- data/lib/active_support/syntax_error_proxy.rb +70 -0
- data/lib/active_support/tagged_logging.rb +84 -23
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +73 -20
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +89 -19
- data/lib/active_support/time_with_zone.rb +105 -70
- data/lib/active_support/values/time_zone.rb +59 -26
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +40 -1
- metadata +127 -40
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -25
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Hack to load
|
3
|
+
# Hack to load JSON gem first so we can override its to_json.
|
4
4
|
require "json"
|
5
5
|
require "bigdecimal"
|
6
|
+
require "ipaddr"
|
6
7
|
require "uri/generic"
|
7
8
|
require "pathname"
|
8
9
|
require "active_support/core_ext/big_decimal/conversions" # for #to_s
|
@@ -18,8 +19,7 @@ require "active_support/core_ext/date/conversions"
|
|
18
19
|
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
19
20
|
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
20
21
|
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
21
|
-
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
22
|
-
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
22
|
+
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance.
|
23
23
|
#
|
24
24
|
# On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
|
25
25
|
# JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
|
@@ -29,7 +29,7 @@ require "active_support/core_ext/date/conversions"
|
|
29
29
|
# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
|
30
30
|
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
|
31
31
|
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
|
32
|
-
# should give exactly the same results with or without
|
32
|
+
# should give exactly the same results with or without Active Support.
|
33
33
|
|
34
34
|
module ActiveSupport
|
35
35
|
module ToJsonWithActiveSupportEncoder # :nodoc:
|
@@ -49,8 +49,14 @@ end
|
|
49
49
|
klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
|
50
50
|
end
|
51
51
|
|
52
|
+
class Module
|
53
|
+
def as_json(options = nil) # :nodoc:
|
54
|
+
name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
52
58
|
class Object
|
53
|
-
def as_json(options = nil)
|
59
|
+
def as_json(options = nil) # :nodoc:
|
54
60
|
if respond_to?(:to_hash)
|
55
61
|
to_hash.as_json(options)
|
56
62
|
else
|
@@ -59,44 +65,52 @@ class Object
|
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
|
68
|
+
if RUBY_VERSION >= "3.2"
|
69
|
+
class Data # :nodoc:
|
70
|
+
def as_json(options = nil)
|
71
|
+
to_h.as_json(options)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Struct # :nodoc:
|
63
77
|
def as_json(options = nil)
|
64
|
-
|
78
|
+
to_h.as_json(options)
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
68
82
|
class TrueClass
|
69
|
-
def as_json(options = nil)
|
83
|
+
def as_json(options = nil) # :nodoc:
|
70
84
|
self
|
71
85
|
end
|
72
86
|
end
|
73
87
|
|
74
88
|
class FalseClass
|
75
|
-
def as_json(options = nil)
|
89
|
+
def as_json(options = nil) # :nodoc:
|
76
90
|
self
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
80
94
|
class NilClass
|
81
|
-
def as_json(options = nil)
|
95
|
+
def as_json(options = nil) # :nodoc:
|
82
96
|
self
|
83
97
|
end
|
84
98
|
end
|
85
99
|
|
86
100
|
class String
|
87
|
-
def as_json(options = nil)
|
101
|
+
def as_json(options = nil) # :nodoc:
|
88
102
|
self
|
89
103
|
end
|
90
104
|
end
|
91
105
|
|
92
106
|
class Symbol
|
93
|
-
def as_json(options = nil)
|
107
|
+
def as_json(options = nil) # :nodoc:
|
94
108
|
to_s
|
95
109
|
end
|
96
110
|
end
|
97
111
|
|
98
112
|
class Numeric
|
99
|
-
def as_json(options = nil)
|
113
|
+
def as_json(options = nil) # :nodoc:
|
100
114
|
self
|
101
115
|
end
|
102
116
|
end
|
@@ -104,7 +118,7 @@ end
|
|
104
118
|
class Float
|
105
119
|
# Encoding Infinity or NaN to JSON should return "null". The default returns
|
106
120
|
# "Infinity" or "NaN" which are not valid JSON.
|
107
|
-
def as_json(options = nil)
|
121
|
+
def as_json(options = nil) # :nodoc:
|
108
122
|
finite? ? self : nil
|
109
123
|
end
|
110
124
|
end
|
@@ -119,43 +133,43 @@ class BigDecimal
|
|
119
133
|
# if the other end knows by contract that the data is supposed to be a
|
120
134
|
# BigDecimal, it still has the chance to post-process the string and get the
|
121
135
|
# real value.
|
122
|
-
def as_json(options = nil)
|
136
|
+
def as_json(options = nil) # :nodoc:
|
123
137
|
finite? ? to_s : nil
|
124
138
|
end
|
125
139
|
end
|
126
140
|
|
127
141
|
class Regexp
|
128
|
-
def as_json(options = nil)
|
142
|
+
def as_json(options = nil) # :nodoc:
|
129
143
|
to_s
|
130
144
|
end
|
131
145
|
end
|
132
146
|
|
133
147
|
module Enumerable
|
134
|
-
def as_json(options = nil)
|
148
|
+
def as_json(options = nil) # :nodoc:
|
135
149
|
to_a.as_json(options)
|
136
150
|
end
|
137
151
|
end
|
138
152
|
|
139
153
|
class IO
|
140
|
-
def as_json(options = nil)
|
154
|
+
def as_json(options = nil) # :nodoc:
|
141
155
|
to_s
|
142
156
|
end
|
143
157
|
end
|
144
158
|
|
145
159
|
class Range
|
146
|
-
def as_json(options = nil)
|
160
|
+
def as_json(options = nil) # :nodoc:
|
147
161
|
to_s
|
148
162
|
end
|
149
163
|
end
|
150
164
|
|
151
165
|
class Array
|
152
|
-
def as_json(options = nil)
|
166
|
+
def as_json(options = nil) # :nodoc:
|
153
167
|
map { |v| options ? v.as_json(options.dup) : v.as_json }
|
154
168
|
end
|
155
169
|
end
|
156
170
|
|
157
171
|
class Hash
|
158
|
-
def as_json(options = nil)
|
172
|
+
def as_json(options = nil) # :nodoc:
|
159
173
|
# create a subset of the hash by applying :only or :except
|
160
174
|
subset = if options
|
161
175
|
if attrs = options[:only]
|
@@ -169,12 +183,16 @@ class Hash
|
|
169
183
|
self
|
170
184
|
end
|
171
185
|
|
172
|
-
|
186
|
+
result = {}
|
187
|
+
subset.each do |k, v|
|
188
|
+
result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
|
189
|
+
end
|
190
|
+
result
|
173
191
|
end
|
174
192
|
end
|
175
193
|
|
176
194
|
class Time
|
177
|
-
def as_json(options = nil)
|
195
|
+
def as_json(options = nil) # :nodoc:
|
178
196
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
179
197
|
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
180
198
|
else
|
@@ -184,7 +202,7 @@ class Time
|
|
184
202
|
end
|
185
203
|
|
186
204
|
class Date
|
187
|
-
def as_json(options = nil)
|
205
|
+
def as_json(options = nil) # :nodoc:
|
188
206
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
189
207
|
strftime("%Y-%m-%d")
|
190
208
|
else
|
@@ -194,7 +212,7 @@ class Date
|
|
194
212
|
end
|
195
213
|
|
196
214
|
class DateTime
|
197
|
-
def as_json(options = nil)
|
215
|
+
def as_json(options = nil) # :nodoc:
|
198
216
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
199
217
|
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
200
218
|
else
|
@@ -203,19 +221,25 @@ class DateTime
|
|
203
221
|
end
|
204
222
|
end
|
205
223
|
|
206
|
-
class URI::Generic
|
224
|
+
class URI::Generic # :nodoc:
|
225
|
+
def as_json(options = nil)
|
226
|
+
to_s
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
class Pathname # :nodoc:
|
207
231
|
def as_json(options = nil)
|
208
232
|
to_s
|
209
233
|
end
|
210
234
|
end
|
211
235
|
|
212
|
-
class
|
236
|
+
class IPAddr # :nodoc:
|
213
237
|
def as_json(options = nil)
|
214
238
|
to_s
|
215
239
|
end
|
216
240
|
end
|
217
241
|
|
218
|
-
class Process::Status
|
242
|
+
class Process::Status # :nodoc:
|
219
243
|
def as_json(options = nil)
|
220
244
|
{ exitstatus: exitstatus, pid: pid }
|
221
245
|
end
|
@@ -72,14 +72,12 @@ class Hash
|
|
72
72
|
#
|
73
73
|
# The string pairs "key=value" that conform the query string
|
74
74
|
# are sorted lexicographically in ascending order.
|
75
|
-
#
|
76
|
-
# This method is also aliased as +to_param+.
|
77
75
|
def to_query(namespace = nil)
|
78
|
-
query =
|
76
|
+
query = filter_map do |key, value|
|
79
77
|
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
80
78
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
81
79
|
end
|
82
|
-
end
|
80
|
+
end
|
83
81
|
|
84
82
|
query.sort! unless namespace.to_s.include?("[]")
|
85
83
|
query.join("&")
|
@@ -3,32 +3,32 @@
|
|
3
3
|
require "delegate"
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
|
-
module Tryable
|
7
|
-
def try(
|
8
|
-
if
|
9
|
-
if
|
10
|
-
instance_eval(&
|
6
|
+
module Tryable # :nodoc:
|
7
|
+
def try(*args, &block)
|
8
|
+
if args.empty? && block_given?
|
9
|
+
if block.arity == 0
|
10
|
+
instance_eval(&block)
|
11
11
|
else
|
12
12
|
yield self
|
13
13
|
end
|
14
|
-
elsif respond_to?(
|
15
|
-
public_send(
|
14
|
+
elsif respond_to?(args.first)
|
15
|
+
public_send(*args, &block)
|
16
16
|
end
|
17
17
|
end
|
18
|
-
ruby2_keywords(:try)
|
18
|
+
ruby2_keywords(:try)
|
19
19
|
|
20
|
-
def try!(
|
21
|
-
if
|
22
|
-
if
|
23
|
-
instance_eval(&
|
20
|
+
def try!(*args, &block)
|
21
|
+
if args.empty? && block_given?
|
22
|
+
if block.arity == 0
|
23
|
+
instance_eval(&block)
|
24
24
|
else
|
25
25
|
yield self
|
26
26
|
end
|
27
27
|
else
|
28
|
-
public_send(
|
28
|
+
public_send(*args, &block)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
ruby2_keywords(:try!)
|
31
|
+
ruby2_keywords(:try!)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -39,7 +39,7 @@ class Object
|
|
39
39
|
# :method: try
|
40
40
|
#
|
41
41
|
# :call-seq:
|
42
|
-
# try(*
|
42
|
+
# try(*args, &block)
|
43
43
|
#
|
44
44
|
# Invokes the public method whose name goes as first argument just like
|
45
45
|
# +public_send+ does, except that if the receiver does not respond to it the
|
@@ -104,7 +104,7 @@ class Object
|
|
104
104
|
# :method: try!
|
105
105
|
#
|
106
106
|
# :call-seq:
|
107
|
-
# try!(*
|
107
|
+
# try!(*args, &block)
|
108
108
|
#
|
109
109
|
# Same as #try, but raises a +NoMethodError+ exception if the receiver is
|
110
110
|
# not +nil+ and does not implement the tried method.
|
@@ -121,7 +121,7 @@ class Delegator
|
|
121
121
|
# :method: try
|
122
122
|
#
|
123
123
|
# :call-seq:
|
124
|
-
# try(
|
124
|
+
# try(*args, &block)
|
125
125
|
#
|
126
126
|
# See Object#try
|
127
127
|
|
@@ -129,7 +129,7 @@ class Delegator
|
|
129
129
|
# :method: try!
|
130
130
|
#
|
131
131
|
# :call-seq:
|
132
|
-
# try!(
|
132
|
+
# try!(*args, &block)
|
133
133
|
#
|
134
134
|
# See Object#try!
|
135
135
|
end
|
@@ -145,14 +145,14 @@ class NilClass
|
|
145
145
|
#
|
146
146
|
# With +try+
|
147
147
|
# @person.try(:children).try(:first).try(:name)
|
148
|
-
def try(
|
148
|
+
def try(*)
|
149
149
|
nil
|
150
150
|
end
|
151
151
|
|
152
152
|
# Calling +try!+ on +nil+ always returns +nil+.
|
153
153
|
#
|
154
154
|
# nil.try!(:name) # => nil
|
155
|
-
def try!(
|
155
|
+
def try!(*)
|
156
156
|
nil
|
157
157
|
end
|
158
158
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Set and restore public attributes around a block.
|
5
|
+
#
|
6
|
+
# client.timeout # => 5
|
7
|
+
# client.with(timeout: 1) do
|
8
|
+
# client.timeout # => 1
|
9
|
+
# end
|
10
|
+
# client.timeout # => 5
|
11
|
+
#
|
12
|
+
# This method is a shorthand for the common begin/ensure pattern:
|
13
|
+
#
|
14
|
+
# old_value = object.attribute
|
15
|
+
# begin
|
16
|
+
# object.attribute = new_value
|
17
|
+
# # do things
|
18
|
+
# ensure
|
19
|
+
# object.attribute = old_value
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# It can be used on any object as long as both the reader and writer methods
|
23
|
+
# are public.
|
24
|
+
def with(**attributes)
|
25
|
+
old_values = {}
|
26
|
+
begin
|
27
|
+
attributes.each do |key, value|
|
28
|
+
old_values[key] = public_send(key)
|
29
|
+
public_send("#{key}=", value)
|
30
|
+
end
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
old_values.each do |key, old_value|
|
34
|
+
public_send("#{key}=", old_value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# #with isn't usable on immediates, so we might as well undefine the
|
41
|
+
# method in common immediate classes to avoid potential confusion.
|
42
|
+
[NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass|
|
43
|
+
klass.undef_method(:with)
|
44
|
+
end
|
@@ -5,9 +5,9 @@ require "active_support/option_merger"
|
|
5
5
|
class Object
|
6
6
|
# An elegant way to factor duplication out of options passed to a series of
|
7
7
|
# method calls. Each method called in the block, with the block variable as
|
8
|
-
# the receiver, will have its options merged with the default +options+
|
9
|
-
# provided. Each method called on
|
10
|
-
# hash as its final argument.
|
8
|
+
# the receiver, will have its options merged with the default +options+
|
9
|
+
# <tt>Hash</tt> or <tt>Hash</tt>-like object provided. Each method called on
|
10
|
+
# the block variable must take an options hash as its final argument.
|
11
11
|
#
|
12
12
|
# Without <tt>with_options</tt>, this code contains duplication:
|
13
13
|
#
|
@@ -64,19 +64,38 @@ class Object
|
|
64
64
|
#
|
65
65
|
# Hence the inherited default for +if+ key is ignored.
|
66
66
|
#
|
67
|
-
# NOTE: You cannot call class methods implicitly inside of with_options
|
67
|
+
# NOTE: You cannot call class methods implicitly inside of +with_options+.
|
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
|
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 }
|
75
75
|
# end
|
76
76
|
# end
|
77
77
|
#
|
78
|
+
# When the block argument is omitted, the decorated Object instance is returned:
|
79
|
+
#
|
80
|
+
# module MyStyledHelpers
|
81
|
+
# def styled
|
82
|
+
# with_options style: "color: red;"
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# styled.link_to "I'm red", "/"
|
87
|
+
# # => <a href="/" style="color: red;">I'm red</a>
|
88
|
+
#
|
89
|
+
# styled.button_tag "I'm red too!"
|
90
|
+
# # => <button style="color: red;">I'm red too!</button>
|
91
|
+
#
|
78
92
|
def with_options(options, &block)
|
79
93
|
option_merger = ActiveSupport::OptionMerger.new(self, options)
|
80
|
-
|
94
|
+
|
95
|
+
if block
|
96
|
+
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
|
97
|
+
else
|
98
|
+
option_merger
|
99
|
+
end
|
81
100
|
end
|
82
101
|
end
|
@@ -13,4 +13,5 @@ require "active_support/core_ext/object/instance_variables"
|
|
13
13
|
require "active_support/core_ext/object/json"
|
14
14
|
require "active_support/core_ext/object/to_param"
|
15
15
|
require "active_support/core_ext/object/to_query"
|
16
|
+
require "active_support/core_ext/object/with"
|
16
17
|
require "active_support/core_ext/object/with_options"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
class Pathname
|
6
|
+
# An Pathname is blank if it's empty:
|
7
|
+
#
|
8
|
+
# Pathname.new("").blank? # => true
|
9
|
+
# Pathname.new(" ").blank? # => false
|
10
|
+
# Pathname.new("test").blank? # => false
|
11
|
+
#
|
12
|
+
# @return [true, false]
|
13
|
+
def blank?
|
14
|
+
to_s.empty?
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
class Pathname
|
6
|
+
# Returns the receiver if the named file exists otherwise returns +nil+.
|
7
|
+
# <tt>pathname.existence</tt> is equivalent to
|
8
|
+
#
|
9
|
+
# pathname.exist? ? pathname : nil
|
10
|
+
#
|
11
|
+
# For example, something like
|
12
|
+
#
|
13
|
+
# content = pathname.read if pathname.exist?
|
14
|
+
#
|
15
|
+
# becomes
|
16
|
+
#
|
17
|
+
# content = pathname.existence&.read
|
18
|
+
#
|
19
|
+
# @return [Pathname]
|
20
|
+
def existence
|
21
|
+
self if exist?
|
22
|
+
end
|
23
|
+
end
|
@@ -15,11 +15,13 @@ module ActiveSupport
|
|
15
15
|
# The given range must be fully bounded, with both start and end.
|
16
16
|
def ===(value)
|
17
17
|
if value.is_a?(::Range)
|
18
|
+
is_backwards_op = value.exclude_end? ? :>= : :>
|
19
|
+
return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
|
18
20
|
# 1...10 includes 1..9 but it does not include 1..10.
|
19
21
|
# 1..10 includes 1...11 but it does not include 1...12.
|
20
22
|
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
21
23
|
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
22
|
-
super(value.first) && (self.end.nil? || value_max.
|
24
|
+
super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
|
23
25
|
else
|
24
26
|
super
|
25
27
|
end
|
@@ -38,34 +40,13 @@ module ActiveSupport
|
|
38
40
|
# The given range must be fully bounded, with both start and end.
|
39
41
|
def include?(value)
|
40
42
|
if value.is_a?(::Range)
|
43
|
+
is_backwards_op = value.exclude_end? ? :>= : :>
|
44
|
+
return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
|
41
45
|
# 1...10 includes 1..9 but it does not include 1..10.
|
42
46
|
# 1..10 includes 1...11 but it does not include 1...12.
|
43
47
|
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
44
48
|
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
45
|
-
super(value.first) && (self.end.nil? || value_max.
|
46
|
-
else
|
47
|
-
super
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Extends the default Range#cover? to support range comparisons.
|
52
|
-
# (1..5).cover?(1..5) # => true
|
53
|
-
# (1..5).cover?(2..3) # => true
|
54
|
-
# (1..5).cover?(1...6) # => true
|
55
|
-
# (1..5).cover?(2..6) # => false
|
56
|
-
#
|
57
|
-
# The native Range#cover? behavior is untouched.
|
58
|
-
# ('a'..'f').cover?('c') # => true
|
59
|
-
# (5..9).cover?(11) # => false
|
60
|
-
#
|
61
|
-
# The given range must be fully bounded, with both start and end.
|
62
|
-
def cover?(value)
|
63
|
-
if value.is_a?(::Range)
|
64
|
-
# 1...10 covers 1..9 but it does not cover 1..10.
|
65
|
-
# 1..10 covers 1...11 but it does not cover 1...12.
|
66
|
-
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
67
|
-
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
68
|
-
super(value.first) && (self.end.nil? || value_max.send(operator, last))
|
49
|
+
super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
|
69
50
|
else
|
70
51
|
super
|
71
52
|
end
|
@@ -1,40 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
+
# = \Range With Format
|
4
5
|
module RangeWithFormat
|
5
6
|
RANGE_FORMATS = {
|
6
7
|
db: -> (start, stop) do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
if start && stop
|
9
|
+
case start
|
10
|
+
when String then "BETWEEN '#{start}' AND '#{stop}'"
|
11
|
+
else
|
12
|
+
"BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'"
|
13
|
+
end
|
14
|
+
elsif start
|
15
|
+
case start
|
16
|
+
when String then ">= '#{start}'"
|
17
|
+
else
|
18
|
+
">= '#{start.to_fs(:db)}'"
|
19
|
+
end
|
20
|
+
elsif stop
|
21
|
+
case stop
|
22
|
+
when String then "<= '#{stop}'"
|
23
|
+
else
|
24
|
+
"<= '#{stop.to_fs(:db)}'"
|
25
|
+
end
|
11
26
|
end
|
12
27
|
end
|
13
28
|
}
|
14
29
|
|
15
30
|
# Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
|
16
31
|
#
|
32
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
33
|
+
#
|
17
34
|
# range = (1..100) # => 1..100
|
18
35
|
#
|
19
36
|
# range.to_s # => "1..100"
|
20
|
-
# range.
|
37
|
+
# range.to_fs(:db) # => "BETWEEN '1' AND '100'"
|
38
|
+
#
|
39
|
+
# range = (1..) # => 1..
|
40
|
+
# range.to_fs(:db) # => ">= '1'"
|
21
41
|
#
|
22
|
-
#
|
42
|
+
# range = (..100) # => ..100
|
43
|
+
# range.to_fs(:db) # => "<= '100'"
|
44
|
+
#
|
45
|
+
# == Adding your own range formats to to_fs
|
23
46
|
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
24
47
|
# Use the format name as the hash key and a Proc instance.
|
25
48
|
#
|
26
49
|
# # config/initializers/range_formats.rb
|
27
|
-
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.
|
28
|
-
def
|
50
|
+
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
|
51
|
+
def to_fs(format = :default)
|
29
52
|
if formatter = RANGE_FORMATS[format]
|
30
|
-
formatter.call(
|
53
|
+
formatter.call(self.begin, self.end)
|
31
54
|
else
|
32
|
-
|
55
|
+
to_s
|
33
56
|
end
|
34
57
|
end
|
35
|
-
|
36
|
-
alias_method :to_default_s, :to_s
|
37
|
-
alias_method :to_formatted_s, :to_s
|
58
|
+
alias_method :to_formatted_s, :to_fs
|
38
59
|
end
|
39
60
|
end
|
40
61
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Range
|
4
|
+
# Compare two ranges and see if they overlap each other
|
5
|
+
# (1..5).overlap?(4..6) # => true
|
6
|
+
# (1..5).overlap?(7..9) # => false
|
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
|
37
|
+
end
|
38
|
+
|
39
|
+
alias :overlaps? :overlap?
|
40
|
+
end
|