refinements 14.5.0 → 14.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 730d2c8e3fd694a24d88c05755eec1599b26002fd7317131c795e5752ed16fb5
4
- data.tar.gz: 5611e41668a0570ae5944569bee6b54e7b47176a37831ba8817c20c63edb2840
3
+ metadata.gz: 9d163c074a4394a9a24c358a571a7679e20667bcdf1321d2e62e39419f4b07f2
4
+ data.tar.gz: 1cbe04caef72d6b58c580f4cb2b255421cc12fe7b9f56187aa13537b3ae10638
5
5
  SHA512:
6
- metadata.gz: 4314a271e2c4ab6f0c5d4d0f2e4c56d13b68b4e7d5f11b46ffb3e477f1a7770d44c0a670e7fee640cec6f2df74daee191eaf5b764a379b7c17a9e0011328fd20
7
- data.tar.gz: 1eca09b429c622b3365b6cf5d2905313cebffa45264ac25684bba65332f70e58934c301655ee6651f96a3c5c59df526aeeb50e4aa5e02e126f0db1f7c8795d15
6
+ metadata.gz: b5e5ec861754742185981115feeaf58f32d79eb3c85bff1e59ae839815d6723d4e9a9b2a22c85a3bbf016386385b952b55c741c4654e98aa0a95caee5694e8b7
7
+ data.tar.gz: c8abd9681ea04eb860b796f0e96e35f7954700c54d0c11a0bf8f2fab0d0385e05f9ad235b0592daaad5476088b5d6fa27492fea1cb64672fe1605cfa80e43e4a
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -463,10 +463,10 @@ Any object that _is not_ the same type will have a `nil` value as shown in the l
463
463
 
464
464
  ===== .utc
465
465
 
466
- Answers new DateTime object for current UTC date/time.
467
-
468
466
  ⚠️ This method (and refinement) is deprecated and will be removed in the next major release.
469
467
 
468
+ Answers new DateTime object for current UTC date/time.
469
+
470
470
  [source,ruby]
471
471
  ----
472
472
  DateTime.utc # "#<DateTime: 2019-12-31T18:17:00+00:00 ((2458849j,65820s,181867000n),+0s,2299161j)>"
@@ -534,10 +534,34 @@ Merges deeply nested hashes together without mutating itself.
534
534
 
535
535
  [source,ruby]
536
536
  ----
537
- example = {a: "A", b: {one: "One", two: "Two"}}
537
+ example = {demo: {one: "One"}}
538
+
539
+ example.deep_merge demo: {one: 1} # {demo: {one: 1}}
540
+ example # {demo: {one: "One"}}
541
+ ----
542
+
543
+ Nested arrays are concatenated:
538
544
 
539
- example.deep_merge b: {one: 1} # {a: "A", b: {one: 1, two: "Two"}}
540
- example # {a: "A", b: {one: "One", two: "Two"}}
545
+ [source,ruby]
546
+ ----
547
+ {demo: [1, 2]}.deep_merge(demo: [3, 4])
548
+ # {demo: [1, 2, 3, 4]}
549
+ ----
550
+
551
+ Arrays are concatenated by index so ensure both arrays are in the same order when needing to merge nested arrays and/or hashes. If the other array has more elements which are not arrays or hashes, they will be appended. Example:
552
+
553
+ [source,ruby]
554
+ ----
555
+ {demo: [1, [2, 3], {a: 1}]}.deep_merge(demo: [:a, [4, 5], {a: :one, b: :two}, 6])
556
+ # {
557
+ # demo: [
558
+ # 1,
559
+ # [2, 3, 4, 5],
560
+ # {a: :one, b: :two},
561
+ # :a
562
+ # 6
563
+ # ]
564
+ # }
541
565
  ----
542
566
 
543
567
  ===== #deep_merge!
@@ -552,6 +576,8 @@ example.deep_merge! b: {one: 1} # {a: "A", b: {one: 1, two: "Two"}}
552
576
  example # {a: "A", b: {one: 1, two: "Two"}}
553
577
  ----
554
578
 
579
+ For more example, see `+#deep_merge+` above.
580
+
555
581
  ===== #deep_stringify_keys
556
582
 
557
583
  Answers string keys of a nested hash without mutating itself. Does not handle nested arrays, though.
@@ -616,6 +642,52 @@ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
616
642
 
617
643
  Any object that _is not_ the same type will have a `nil` value as shown in the last two examples. Two hashes with the same keys but defined in different order behave as if they had the same key order.
618
644
 
645
+ ===== #expand_keys
646
+
647
+ Allows you to expand flat keys into a nested hash. This is the reverse of `+#flatten_keys+`.
648
+
649
+ [source,ruby]
650
+ ----
651
+ {"a.a" => 0, "a.b.one" => 1, "a.b.two" => 2}.expand_keys
652
+
653
+ # {
654
+ # "a" => {
655
+ # "a" => 0,
656
+ # "b" => {
657
+ # "one" => 1,
658
+ # "two" => 2
659
+ # }
660
+ # }
661
+ # }
662
+
663
+ {"a_a" => 0, "a_b_one" => 1, "a_b_two" => 2}.expand_keys delimiter: "_"
664
+
665
+ # {
666
+ # "a" => {
667
+ # "a" => 0,
668
+ # "b" => {
669
+ # "one" => 1,
670
+ # "two" => 2
671
+ # }
672
+ # }
673
+ # }
674
+ ----
675
+
676
+ Parent values -- which are not hashes -- are ignored when a nested child hash exists. Example:
677
+
678
+ [source,ruby]
679
+ ----
680
+ {"a" => 0, "a.b" => 1, "a.b.one" => :test}.expand_keys
681
+
682
+ # {
683
+ # "a" => {
684
+ # "b" => {
685
+ # "one" => :test
686
+ # }
687
+ # }
688
+ # }
689
+ ----
690
+
619
691
  ===== #fetch_deep
620
692
 
621
693
  Fetches a nested value by combining the behavior of `#fetch` and `#dig` into a single method. This works with nested arrays too. Examples:
@@ -853,6 +925,8 @@ example # {name: "Jayne", email: "jd@example.com"}
853
925
 
854
926
  ===== #use
855
927
 
928
+ ⚠️ This method is deprecated and will be removed in the next major release.
929
+
856
930
  Uses the hash's keys as block arguments where the value of the block argument is equal to the value of the key found within the hash. Works best with hashes that use symbols for keys but falls back to string keys when symbol keys can't be found.
857
931
 
858
932
  [source,ruby]
@@ -4,6 +4,7 @@ require "refinements/shared/many"
4
4
 
5
5
  module Refinements
6
6
  # Provides additional enhancements to the Hash primitive.
7
+ # rubocop:todo-next Metrics/ModuleLength
7
8
  module Hash
8
9
  refine ::Hash.singleton_class do
9
10
  def infinite = new { |nascence, lacuna| nascence[lacuna] = new(&nascence.default_proc) }
@@ -21,20 +22,20 @@ module Refinements
21
22
  compact!
22
23
  end
23
24
 
24
- def deep_merge other
25
- clazz = self.class
25
+ def deep_merge(other, &) = dup.deep_merge!(other, &)
26
26
 
27
- merge other do |_key, this_value, other_value|
28
- if this_value.is_a?(clazz) && other_value.is_a?(clazz)
29
- this_value.deep_merge other_value
30
- else
31
- other_value
27
+ def deep_merge!(other, &)
28
+ klass = self.class
29
+
30
+ merge! other do |key, first, second|
31
+ if first.is_a?(klass) && second.is_a?(klass) then first.deep_merge(second, &)
32
+ elsif first.is_a?(::Array) && second.is_a?(::Array) then deep_concat(first, second, &)
33
+ elsif block_given? then yield key, first, second
34
+ else second
32
35
  end
33
36
  end
34
37
  end
35
38
 
36
- def deep_merge!(other) = replace(deep_merge(other))
37
-
38
39
  def deep_stringify_keys = recurse(&:stringify_keys)
39
40
 
40
41
  def deep_stringify_keys! = replace(deep_stringify_keys)
@@ -44,11 +45,18 @@ module Refinements
44
45
  def deep_symbolize_keys! = replace(deep_symbolize_keys)
45
46
 
46
47
  def diff other
47
- return differences_from other if other.is_a?(self.class) && keys.sort! == other.keys.sort!
48
+ return diff_array other if other.is_a?(self.class) && keys.sort! == other.keys.sort!
48
49
 
49
50
  each.with_object({}) { |(key, value), diff| diff[key] = [value, nil] }
50
51
  end
51
52
 
53
+ def expand_keys delimiter: "."
54
+ each.with_object({}) do |(key, value), all|
55
+ parts = String(key).split(delimiter).reverse
56
+ all.deep_merge! parts.reduce(value) { |accumulator, part| {part => accumulator} }
57
+ end
58
+ end
59
+
52
60
  def fetch_deep(*keys, default: NilClass, &)
53
61
  keys.reduce fallback(keys.shift, default, &) do |value, key|
54
62
  unless value.is_a?(::Hash) || (value.is_a?(::Array) && key.is_a?(::Integer))
@@ -104,6 +112,10 @@ module Refinements
104
112
  end
105
113
 
106
114
  def use &block
115
+ warn "`#{self.class}##{__method__}` is deprecated and will be removed " \
116
+ "in the next major version.",
117
+ category: :deprecated
118
+
107
119
  return [] unless block
108
120
 
109
121
  block.parameters
@@ -113,9 +125,28 @@ module Refinements
113
125
 
114
126
  private
115
127
 
116
- def differences_from other
117
- result = merge(other.to_h) { |_, one, two| [one, two].uniq }
118
- result.select { |_, diff| diff.size == 2 }
128
+ def deep_concat(original, second, &)
129
+ first = original.dup
130
+ klass = self.class
131
+
132
+ second.each.with_index do |second_item, index|
133
+ first_item = first[index]
134
+
135
+ if first_item.is_a?(klass) && second_item.is_a?(klass)
136
+ first[index] = first_item.deep_merge!(second_item, &)
137
+ elsif second_item.is_a? ::Array
138
+ first[index] = deep_concat(first_item, second_item, &)
139
+ else
140
+ first.append(second_item).uniq!
141
+ end
142
+ end
143
+
144
+ first
145
+ end
146
+
147
+ def diff_array other
148
+ merged = merge(other.to_h) { |_, one, two| [one, two].uniq }
149
+ merged.select { |_, diff| diff.size == 2 }
119
150
  end
120
151
 
121
152
  def fallback(key, default, &)
data/refinements.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "refinements"
5
- spec.version = "14.5.0"
5
+ spec.version = "14.6.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/refinements"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refinements
3
3
  version: !ruby/object:Gem::Version
4
- version: 14.5.0
4
+ version: 14.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  requirements: []
92
- rubygems_version: 4.0.21
92
+ rubygems_version: 4.0.22
93
93
  specification_version: 4
94
94
  summary: A collection of core object refinements.
95
95
  test_files: []
metadata.gz.sig CHANGED
Binary file