activesupport 5.1.1 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +360 -442
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +6 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -3
- data/lib/active_support/benchmarkable.rb +3 -1
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +37 -36
- data/lib/active_support/cache/mem_cache_store.rb +65 -53
- data/lib/active_support/cache/memory_store.rb +61 -33
- data/lib/active_support/cache/null_store.rb +10 -3
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +68 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +305 -127
- data/lib/active_support/callbacks.rb +106 -98
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -1
- data/lib/active_support/configurable.rb +12 -14
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +7 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +3 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +18 -40
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -5
- data/lib/active_support/core_ext/date/conversions.rb +12 -10
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +174 -71
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -5
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +3 -30
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/marshal.rb +4 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +103 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +2 -1
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +13 -3
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +6 -101
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +22 -2
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +7 -2
- data/lib/active_support/core_ext/object/try.rb +19 -7
- data/lib/active_support/core_ext/object/with_options.rb +4 -2
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +3 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +3 -0
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +76 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +73 -18
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +4 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +11 -6
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +135 -60
- data/lib/active_support/deprecation/behaviors.rb +43 -11
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +30 -15
- data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +9 -2
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +6 -6
- data/lib/active_support/duration/iso8601_serializer.rb +20 -14
- data/lib/active_support/duration.rb +179 -41
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +84 -117
- data/lib/active_support/execution_wrapper.rb +3 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +3 -1
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +134 -37
- data/lib/active_support/i18n.rb +4 -1
- data/lib/active_support/i18n_railtie.rb +20 -11
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -8
- data/lib/active_support/inflector/methods.rb +87 -77
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +13 -3
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -33
- data/lib/active_support/lazy_load_hooks.rb +33 -10
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +46 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +54 -7
- data/lib/active_support/message_encryptor.rb +101 -33
- data/lib/active_support/message_verifier.rb +85 -14
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +12 -68
- data/lib/active_support/multibyte/unicode.rb +17 -327
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +118 -16
- data/lib/active_support/notifications/instrumenter.rb +73 -9
- data/lib/active_support/notifications.rb +74 -8
- data/lib/active_support/number_helper/number_converter.rb +7 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -7
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +16 -53
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +41 -12
- data/lib/active_support/option_merger.rb +24 -3
- data/lib/active_support/ordered_hash.rb +3 -1
- data/lib/active_support/ordered_options.rb +17 -5
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +3 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +60 -9
- data/lib/active_support/reloader.rb +11 -10
- data/lib/active_support/rescuable.rb +7 -6
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +6 -3
- data/lib/active_support/subscriber.rb +74 -24
- data/lib/active_support/tagged_logging.rb +44 -8
- data/lib/active_support/test_case.rb +94 -2
- data/lib/active_support/testing/assertions.rb +58 -20
- data/lib/active_support/testing/autorun.rb +2 -4
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -1
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +8 -4
- data/lib/active_support/testing/method_call_assertions.rb +30 -1
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +3 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +78 -13
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +113 -41
- data/lib/active_support/values/time_zone.rb +55 -25
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +5 -4
- data/lib/active_support/xml_mini/libxml.rb +4 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
- data/lib/active_support/xml_mini/nokogiri.rb +4 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
- data/lib/active_support/xml_mini/rexml.rb +12 -3
- data/lib/active_support/xml_mini.rb +5 -11
- data/lib/active_support.rb +18 -13
- metadata +81 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/xml_mini"
|
2
|
-
require "active_support/time"
|
3
4
|
require "active_support/core_ext/object/blank"
|
4
5
|
require "active_support/core_ext/object/to_param"
|
5
6
|
require "active_support/core_ext/object/to_query"
|
7
|
+
require "active_support/core_ext/object/try"
|
6
8
|
require "active_support/core_ext/array/wrap"
|
7
9
|
require "active_support/core_ext/hash/reverse_merge"
|
8
10
|
require "active_support/core_ext/string/inflections"
|
@@ -71,7 +73,7 @@ class Hash
|
|
71
73
|
# configure your own builder with the <tt>:builder</tt> option. The method also accepts
|
72
74
|
# options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
|
73
75
|
def to_xml(options = {})
|
74
|
-
require "active_support/builder" unless defined?(Builder)
|
76
|
+
require "active_support/builder" unless defined?(Builder::XmlMarkup)
|
75
77
|
|
76
78
|
options = options.dup
|
77
79
|
options[:indent] ||= 2
|
@@ -163,7 +165,7 @@ module ActiveSupport
|
|
163
165
|
Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
|
164
166
|
when Array
|
165
167
|
params.map { |v| normalize_keys(v) }
|
166
|
-
|
168
|
+
else
|
167
169
|
params
|
168
170
|
end
|
169
171
|
end
|
@@ -176,7 +178,7 @@ module ActiveSupport
|
|
176
178
|
process_array(value)
|
177
179
|
when String
|
178
180
|
value
|
179
|
-
|
181
|
+
else
|
180
182
|
raise "can't typecast #{value.class.name} - #{value.inspect}"
|
181
183
|
end
|
182
184
|
end
|
@@ -206,7 +208,7 @@ module ActiveSupport
|
|
206
208
|
elsif become_empty_string?(value)
|
207
209
|
""
|
208
210
|
elsif become_hash?(value)
|
209
|
-
xml_value =
|
211
|
+
xml_value = value.transform_values { |v| deep_to_h(v) }
|
210
212
|
|
211
213
|
# Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
|
212
214
|
# how multipart uploaded files from HTML appear
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
3
5
|
#
|
@@ -19,20 +21,14 @@ class Hash
|
|
19
21
|
|
20
22
|
# Same as +deep_merge+, but modifies +self+.
|
21
23
|
def deep_merge!(other_hash, &block)
|
22
|
-
other_hash
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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)
|
27
29
|
else
|
28
|
-
|
29
|
-
block.call(current_key, this_value, other_value)
|
30
|
-
else
|
31
|
-
other_value
|
32
|
-
end
|
30
|
+
other_val
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
36
|
-
self
|
37
33
|
end
|
38
34
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Returns a new hash with all values converted by the block operation.
|
5
|
+
# This includes the values from the root hash and from all
|
6
|
+
# nested hashes and arrays.
|
7
|
+
#
|
8
|
+
# hash = { person: { name: 'Rob', age: '28' } }
|
9
|
+
#
|
10
|
+
# hash.deep_transform_values{ |value| value.to_s.upcase }
|
11
|
+
# # => {person: {name: "ROB", age: "28"}}
|
12
|
+
def deep_transform_values(&block)
|
13
|
+
_deep_transform_values_in_object(self, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Destructively converts all values by using the block operation.
|
17
|
+
# This includes the values from the root hash and from all
|
18
|
+
# nested hashes and arrays.
|
19
|
+
def deep_transform_values!(&block)
|
20
|
+
_deep_transform_values_in_object!(self, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
# Support methods for deep transforming nested hashes and arrays.
|
25
|
+
def _deep_transform_values_in_object(object, &block)
|
26
|
+
case object
|
27
|
+
when Hash
|
28
|
+
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
|
29
|
+
when Array
|
30
|
+
object.map { |e| _deep_transform_values_in_object(e, &block) }
|
31
|
+
else
|
32
|
+
yield(object)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def _deep_transform_values_in_object!(object, &block)
|
37
|
+
case object
|
38
|
+
when Hash
|
39
|
+
object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
|
40
|
+
when Array
|
41
|
+
object.map! { |e| _deep_transform_values_in_object!(e, &block) }
|
42
|
+
else
|
43
|
+
yield(object)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Returns a hash that includes everything except given keys.
|
3
5
|
# hash = { a: true, b: false, c: nil }
|
@@ -8,8 +10,8 @@ class Hash
|
|
8
10
|
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
9
11
|
# @person.update(params[:person].except(:admin))
|
10
12
|
def except(*keys)
|
11
|
-
|
12
|
-
end
|
13
|
+
slice(*self.keys - keys)
|
14
|
+
end unless method_defined?(:except)
|
13
15
|
|
14
16
|
# Removes the given keys from hash and returns it.
|
15
17
|
# hash = { a: true, b: false, c: nil }
|
@@ -1,33 +1,6 @@
|
|
1
|
-
|
2
|
-
# Returns a new hash with all keys converted using the +block+ operation.
|
3
|
-
#
|
4
|
-
# hash = { name: 'Rob', age: '28' }
|
5
|
-
#
|
6
|
-
# hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
|
7
|
-
#
|
8
|
-
# If you do not provide a +block+, it will return an Enumerator
|
9
|
-
# for chaining with other methods:
|
10
|
-
#
|
11
|
-
# hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
|
12
|
-
def transform_keys
|
13
|
-
return enum_for(:transform_keys) { size } unless block_given?
|
14
|
-
result = {}
|
15
|
-
each_key do |key|
|
16
|
-
result[yield(key)] = self[key]
|
17
|
-
end
|
18
|
-
result
|
19
|
-
end
|
20
|
-
|
21
|
-
# Destructively converts all keys using the +block+ operations.
|
22
|
-
# Same as +transform_keys+ but modifies +self+.
|
23
|
-
def transform_keys!
|
24
|
-
return enum_for(:transform_keys!) { size } unless block_given?
|
25
|
-
keys.each do |key|
|
26
|
-
self[yield(key)] = delete(key)
|
27
|
-
end
|
28
|
-
self
|
29
|
-
end
|
1
|
+
# frozen_string_literal: true
|
30
2
|
|
3
|
+
class Hash
|
31
4
|
# Returns a new hash with all keys converted to strings.
|
32
5
|
#
|
33
6
|
# hash = { name: 'Rob', age: '28' }
|
@@ -139,7 +112,7 @@ class Hash
|
|
139
112
|
end
|
140
113
|
|
141
114
|
private
|
142
|
-
#
|
115
|
+
# Support methods for deep transforming nested hashes and arrays.
|
143
116
|
def _deep_transform_keys_in_object(object, &block)
|
144
117
|
case object
|
145
118
|
when Hash
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Merges the caller into +other_hash+. For example,
|
3
5
|
#
|
@@ -12,11 +14,12 @@ class Hash
|
|
12
14
|
def reverse_merge(other_hash)
|
13
15
|
other_hash.merge(self)
|
14
16
|
end
|
17
|
+
alias_method :with_defaults, :reverse_merge
|
15
18
|
|
16
19
|
# Destructive +reverse_merge+.
|
17
20
|
def reverse_merge!(other_hash)
|
18
|
-
|
19
|
-
merge!(other_hash) { |key, left, right| left }
|
21
|
+
replace(reverse_merge(other_hash))
|
20
22
|
end
|
21
23
|
alias_method :reverse_update, :reverse_merge!
|
24
|
+
alias_method :with_defaults!, :reverse_merge!
|
22
25
|
end
|
@@ -1,35 +1,13 @@
|
|
1
|
-
|
2
|
-
# Slices a hash to include only the given keys. Returns a hash containing
|
3
|
-
# the given keys.
|
4
|
-
#
|
5
|
-
# { a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b)
|
6
|
-
# # => {:a=>1, :b=>2}
|
7
|
-
#
|
8
|
-
# This is useful for limiting an options hash to valid keys before
|
9
|
-
# passing to a method:
|
10
|
-
#
|
11
|
-
# def search(criteria = {})
|
12
|
-
# criteria.assert_valid_keys(:mass, :velocity, :time)
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# search(options.slice(:mass, :velocity, :time))
|
16
|
-
#
|
17
|
-
# If you have an array of keys you want to limit to, you should splat them:
|
18
|
-
#
|
19
|
-
# valid_keys = [:mass, :velocity, :time]
|
20
|
-
# search(options.slice(*valid_keys))
|
21
|
-
def slice(*keys)
|
22
|
-
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
23
|
-
keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
|
24
|
-
end
|
1
|
+
# frozen_string_literal: true
|
25
2
|
|
3
|
+
class Hash
|
26
4
|
# Replaces the hash with only the given keys.
|
27
5
|
# Returns a hash containing the removed key/value pairs.
|
28
6
|
#
|
29
|
-
# { a: 1, b: 2, c: 3, d: 4 }
|
30
|
-
# # => {:c=>3, :d=>4}
|
7
|
+
# hash = { a: 1, b: 2, c: 3, d: 4 }
|
8
|
+
# hash.slice!(:a, :b) # => {:c=>3, :d=>4}
|
9
|
+
# hash # => {:a=>1, :b=>2}
|
31
10
|
def slice!(*keys)
|
32
|
-
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
33
11
|
omit = slice(*self.keys - keys)
|
34
12
|
hash = slice(*keys)
|
35
13
|
hash.default = default
|
@@ -40,8 +18,9 @@ class Hash
|
|
40
18
|
|
41
19
|
# Removes and returns the key/value pairs matching the given keys.
|
42
20
|
#
|
43
|
-
# { a: 1, b: 2, c: 3, d: 4 }
|
44
|
-
#
|
21
|
+
# hash = { a: 1, b: 2, c: 3, d: 4 }
|
22
|
+
# hash.extract!(:a, :b) # => {:a=>1, :b=>2}
|
23
|
+
# hash # => {:c=>3, :d=>4}
|
45
24
|
def extract!(*keys)
|
46
25
|
keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
|
47
26
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "active_support/core_ext/hash/conversions"
|
3
4
|
require "active_support/core_ext/hash/deep_merge"
|
5
|
+
require "active_support/core_ext/hash/deep_transform_values"
|
4
6
|
require "active_support/core_ext/hash/except"
|
5
7
|
require "active_support/core_ext/hash/indifferent_access"
|
6
8
|
require "active_support/core_ext/hash/keys"
|
7
9
|
require "active_support/core_ext/hash/reverse_merge"
|
8
10
|
require "active_support/core_ext/hash/slice"
|
9
|
-
require "active_support/core_ext/hash/transform_values"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Integer
|
2
4
|
# Check whether the integer is evenly divisible by the argument.
|
3
5
|
#
|
@@ -5,6 +7,6 @@ class Integer
|
|
5
7
|
# 6.multiple_of?(5) # => false
|
6
8
|
# 10.multiple_of?(2) # => true
|
7
9
|
def multiple_of?(number)
|
8
|
-
number
|
10
|
+
number == 0 ? self == 0 : self % number == 0
|
9
11
|
end
|
10
12
|
end
|
@@ -1,27 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/duration"
|
2
4
|
require "active_support/core_ext/numeric/time"
|
3
5
|
|
4
6
|
class Integer
|
5
|
-
#
|
6
|
-
# 2.hours + 4.years</tt>.
|
7
|
-
#
|
8
|
-
# These methods use Time#advance for precise date calculations when using
|
9
|
-
# <tt>from_now</tt>, +ago+, etc. as well as adding or subtracting their
|
10
|
-
# results from a Time object.
|
11
|
-
#
|
12
|
-
# # equivalent to Time.now.advance(months: 1)
|
13
|
-
# 1.month.from_now
|
7
|
+
# Returns a Duration instance matching the number of months provided.
|
14
8
|
#
|
15
|
-
# #
|
16
|
-
# 2.years.from_now
|
17
|
-
#
|
18
|
-
# # equivalent to Time.now.advance(months: 4, years: 5)
|
19
|
-
# (4.months + 5.years).from_now
|
9
|
+
# 2.months # => 2 months
|
20
10
|
def months
|
21
11
|
ActiveSupport::Duration.months(self)
|
22
12
|
end
|
23
13
|
alias :month :months
|
24
14
|
|
15
|
+
# Returns a Duration instance matching the number of years provided.
|
16
|
+
#
|
17
|
+
# 2.years # => 2 years
|
25
18
|
def years
|
26
19
|
ActiveSupport::Duration.years(self)
|
27
20
|
end
|
@@ -1,14 +1,9 @@
|
|
1
|
-
|
2
|
-
REGEXPS = [
|
3
|
-
/^no such file to load -- (.+)$/i,
|
4
|
-
/^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i,
|
5
|
-
/^Missing API definition file in (.+)$/i,
|
6
|
-
/^cannot load such file -- (.+)$/i,
|
7
|
-
]
|
1
|
+
# frozen_string_literal: true
|
8
2
|
|
3
|
+
class LoadError
|
9
4
|
# Returns true if the given path name (except perhaps for the ".rb"
|
10
5
|
# extension) is the missing file which caused the exception to be raised.
|
11
6
|
def is_missing?(location)
|
12
|
-
location.
|
7
|
+
location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
|
13
8
|
end
|
14
9
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Module
|
2
4
|
# Declares an attribute reader backed by an internally-named instance variable.
|
3
5
|
def attr_internal_reader(*attrs)
|
@@ -26,9 +28,9 @@ class Module
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def attr_internal_define(attr_name, type)
|
29
|
-
internal_name = attr_internal_ivar_name(attr_name).
|
31
|
+
internal_name = attr_internal_ivar_name(attr_name).delete_prefix("@")
|
30
32
|
# use native attr_* methods as they are faster on some Ruby implementations
|
31
|
-
|
33
|
+
public_send("attr_#{type}", internal_name)
|
32
34
|
attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
|
33
35
|
alias_method attr_name, internal_name
|
34
36
|
remove_method internal_name
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require "active_support/core_ext/regexp"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
# Extends the module object with class/module and instance accessors for
|
5
4
|
# class/module attributes, just like the native attr* accessors for instance
|
@@ -25,7 +24,7 @@ class Module
|
|
25
24
|
# end
|
26
25
|
# # => NameError: invalid attribute name: 1_Badname
|
27
26
|
#
|
28
|
-
#
|
27
|
+
# To omit the instance reader method, pass
|
29
28
|
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
|
30
29
|
#
|
31
30
|
# module HairColors
|
@@ -38,13 +37,10 @@ class Module
|
|
38
37
|
#
|
39
38
|
# Person.new.hair_colors # => NoMethodError
|
40
39
|
#
|
41
|
-
#
|
42
|
-
# Also, you can pass a block to set up the attribute with a default value.
|
40
|
+
# You can set a default value for the attribute.
|
43
41
|
#
|
44
42
|
# module HairColors
|
45
|
-
# mattr_reader :hair_colors
|
46
|
-
# [:brown, :black, :blonde, :red]
|
47
|
-
# end
|
43
|
+
# mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
|
48
44
|
# end
|
49
45
|
#
|
50
46
|
# class Person
|
@@ -52,27 +48,25 @@ class Module
|
|
52
48
|
# end
|
53
49
|
#
|
54
50
|
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
|
55
|
-
def mattr_reader(*syms)
|
56
|
-
|
51
|
+
def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
|
52
|
+
raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
|
53
|
+
location ||= caller_locations(1, 1).first
|
54
|
+
|
55
|
+
definition = []
|
57
56
|
syms.each do |sym|
|
58
57
|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
|
59
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
60
|
-
@@#{sym} = nil unless defined? @@#{sym}
|
61
58
|
|
62
|
-
|
63
|
-
@@#{sym}
|
64
|
-
end
|
65
|
-
EOS
|
59
|
+
definition << "def self.#{sym}; @@#{sym}; end"
|
66
60
|
|
67
|
-
|
68
|
-
|
69
|
-
def #{sym}
|
70
|
-
@@#{sym}
|
71
|
-
end
|
72
|
-
EOS
|
61
|
+
if instance_reader && instance_accessor
|
62
|
+
definition << "def #{sym}; @@#{sym}; end"
|
73
63
|
end
|
74
|
-
|
64
|
+
|
65
|
+
sym_default_value = (block_given? && default.nil?) ? yield : default
|
66
|
+
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
|
75
67
|
end
|
68
|
+
|
69
|
+
module_eval(definition.join(";"), location.path, location.lineno)
|
76
70
|
end
|
77
71
|
alias :cattr_reader :mattr_reader
|
78
72
|
|
@@ -94,7 +88,7 @@ class Module
|
|
94
88
|
# Person.new.hair_colors = [:blonde, :red]
|
95
89
|
# HairColors.class_variable_get("@@hair_colors") # => [:blonde, :red]
|
96
90
|
#
|
97
|
-
#
|
91
|
+
# To omit the instance writer method, pass
|
98
92
|
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
|
99
93
|
#
|
100
94
|
# module HairColors
|
@@ -107,12 +101,10 @@ class Module
|
|
107
101
|
#
|
108
102
|
# Person.new.hair_colors = [:blonde, :red] # => NoMethodError
|
109
103
|
#
|
110
|
-
#
|
104
|
+
# You can set a default value for the attribute.
|
111
105
|
#
|
112
106
|
# module HairColors
|
113
|
-
# mattr_writer :hair_colors
|
114
|
-
# [:brown, :black, :blonde, :red]
|
115
|
-
# end
|
107
|
+
# mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
|
116
108
|
# end
|
117
109
|
#
|
118
110
|
# class Person
|
@@ -120,27 +112,24 @@ class Module
|
|
120
112
|
# end
|
121
113
|
#
|
122
114
|
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
|
123
|
-
def mattr_writer(*syms)
|
124
|
-
|
115
|
+
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
|
116
|
+
raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
|
117
|
+
location ||= caller_locations(1, 1).first
|
118
|
+
|
119
|
+
definition = []
|
125
120
|
syms.each do |sym|
|
126
121
|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
|
127
|
-
|
128
|
-
@@#{sym} = nil unless defined? @@#{sym}
|
129
|
-
|
130
|
-
def self.#{sym}=(obj)
|
131
|
-
@@#{sym} = obj
|
132
|
-
end
|
133
|
-
EOS
|
122
|
+
definition << "def self.#{sym}=(val); @@#{sym} = val; end"
|
134
123
|
|
135
|
-
|
136
|
-
|
137
|
-
def #{sym}=(obj)
|
138
|
-
@@#{sym} = obj
|
139
|
-
end
|
140
|
-
EOS
|
124
|
+
if instance_writer && instance_accessor
|
125
|
+
definition << "def #{sym}=(val); @@#{sym} = val; end"
|
141
126
|
end
|
142
|
-
|
127
|
+
|
128
|
+
sym_default_value = (block_given? && default.nil?) ? yield : default
|
129
|
+
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
|
143
130
|
end
|
131
|
+
|
132
|
+
module_eval(definition.join(";"), location.path, location.lineno)
|
144
133
|
end
|
145
134
|
alias :cattr_writer :mattr_writer
|
146
135
|
|
@@ -164,14 +153,14 @@ class Module
|
|
164
153
|
# parent class. Similarly if parent class changes the value then that would
|
165
154
|
# change the value of subclasses too.
|
166
155
|
#
|
167
|
-
# class
|
156
|
+
# class Citizen < Person
|
168
157
|
# end
|
169
158
|
#
|
170
|
-
#
|
159
|
+
# Citizen.new.hair_colors << :blue
|
171
160
|
# Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]
|
172
161
|
#
|
173
|
-
# To
|
174
|
-
# To
|
162
|
+
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
163
|
+
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
175
164
|
#
|
176
165
|
# module HairColors
|
177
166
|
# mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
|
@@ -184,7 +173,7 @@ class Module
|
|
184
173
|
# Person.new.hair_colors = [:brown] # => NoMethodError
|
185
174
|
# Person.new.hair_colors # => NoMethodError
|
186
175
|
#
|
187
|
-
# Or pass <tt>instance_accessor: false</tt>, to
|
176
|
+
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
|
188
177
|
#
|
189
178
|
# module HairColors
|
190
179
|
# mattr_accessor :hair_colors, instance_accessor: false
|
@@ -197,12 +186,10 @@ class Module
|
|
197
186
|
# Person.new.hair_colors = [:brown] # => NoMethodError
|
198
187
|
# Person.new.hair_colors # => NoMethodError
|
199
188
|
#
|
200
|
-
#
|
189
|
+
# You can set a default value for the attribute.
|
201
190
|
#
|
202
191
|
# module HairColors
|
203
|
-
# mattr_accessor :hair_colors
|
204
|
-
# [:brown, :black, :blonde, :red]
|
205
|
-
# end
|
192
|
+
# mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
|
206
193
|
# end
|
207
194
|
#
|
208
195
|
# class Person
|
@@ -210,9 +197,10 @@ class Module
|
|
210
197
|
# end
|
211
198
|
#
|
212
199
|
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
|
213
|
-
def mattr_accessor(*syms, &blk)
|
214
|
-
|
215
|
-
|
200
|
+
def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
|
201
|
+
location = caller_locations(1, 1).first
|
202
|
+
mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, location: location, &blk)
|
203
|
+
mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default, location: location)
|
216
204
|
end
|
217
205
|
alias :cattr_accessor :mattr_accessor
|
218
206
|
end
|