refinements 11.0.0 → 11.1.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: 252744b620f3c79a0c38b635157f62fc9e48527701145e871de885c547b44b61
4
- data.tar.gz: 411b88c5cf6b9b95c59c43055b8a2402c95d9954b612837fce70a106c4c4a5f1
3
+ metadata.gz: 0ec4e17de3e050923d08c34123d8e8f2cf7096e66b3cf035c5fec870470de049
4
+ data.tar.gz: 8d5d5449055c76a8cb4675acc8ccbd2f9e46b4eb9986e29b04e548847f6d69b3
5
5
  SHA512:
6
- metadata.gz: 0c12fb201556e5949190657cd591b126115ba7efb9f14aec4aeb107455d7cd04676b0dd1cc05f84e9bdd8b7c61e2fbadbabe377b739ffd14a643c3d98d717068
7
- data.tar.gz: db75e0359afed8603daba0bae481b8e839b9d9ede700ef22bbcde22116e2a75b221b5d56d0381500ccf992f73c11cb7a4555823c4294b131077972800a03f3c1
6
+ metadata.gz: fe21be9b51f2616eeb94664a85006332dc1b00395cee44540a2adf9b5a08397636e22d35ca4d786887f2d6bfb287bcbca6aee54e89383b71f4976f1433980001
7
+ data.tar.gz: 5bc27d6026ce8ce38fe522929b54328c67445a7ed89f44ba57759a216b2f098c5fd18696bea14c0ab4719d953b59c6173ebff1e218d2d35b9bcfb9ebfdee43e8
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -14,6 +14,7 @@ Enhances the following objects:
14
14
 
15
15
  * Array
16
16
  * BigDecimal
17
+ * Data
17
18
  * DateTime
18
19
  * Hash
19
20
  * IO
@@ -78,6 +79,7 @@ gem "refinements", require: false
78
79
  ----
79
80
  require "refinements/arrays"
80
81
  require "refinements/big_decimals"
82
+ require "refinements/data"
81
83
  require "refinements/date_times"
82
84
  require "refinements/hashes"
83
85
  require "refinements/ios"
@@ -100,6 +102,7 @@ refinement(s):
100
102
  class Example
101
103
  using Refinements::Arrays
102
104
  using Refinements::BigDecimals
105
+ using Refinements::Data
103
106
  using Refinements::DateTimes
104
107
  using Refinements::Hashes
105
108
  using Refinements::IOs
@@ -289,7 +292,7 @@ array = [{name: "a", label: "A"}, {name: "b", label: "B"}, {name: "c", label: "C
289
292
  array.pick :name # "a"
290
293
  array.pick :name, :label # ["a", "A"]
291
294
  array.pick # nil
292
- [].pick(:test) # nil
295
+ [].pick(:other) # nil
293
296
  ----
294
297
 
295
298
  ===== #pluck
@@ -303,7 +306,7 @@ array = [{name: "a", label: "A"}, {name: "b", label: "B"}, {name: "c", label: "C
303
306
  array.pluck :name # ["a", "b", "c"]
304
307
  array.pluck :name, :label # [["a", "A"], ["b", "B"], ["c", "C"]]
305
308
  array.pluck # []
306
- [].pluck :test # []
309
+ [].pluck :other # []
307
310
  ----
308
311
 
309
312
  ===== #replace_at
@@ -365,25 +368,25 @@ Useful when building documentation, answering human readable error messages, etc
365
368
  [source,ruby]
366
369
  ----
367
370
  [].to_sentence # ""
368
- ["test"].to_sentence # "test"
371
+ ["demo"].to_sentence # "demo"
369
372
  ["a", :b].to_sentence # "a and b"
370
- [1, "a", :b, 2.0, /\w+/].map(&:inspect).to_sentence # 1, "a", :b, 2.0, and /\w+/
373
+ [1, "a", :b, 2.0, /\w+/].to_sentence # "1, a, b, 2.0, and (?-mix:\\w+)"
371
374
  %w[one two three].to_sentence # "one, two, and three"
372
375
  %w[eins zwei drei].to_sentence "und", delimiter: " " # "eins zwei und drei"
373
376
  ----
374
377
 
375
378
  ===== #to_usage
376
379
 
377
- Builds upon and enhances `#to_sentence` further by answering a sentence which all elements are inspected -- where each element of the array is called with `#inspect` -- before turned into a sentence using `"and"` as the default conjunction and `", "` as the default delimiter. This is useful when providing detailed error messages _and_ you need to show the element types used.
380
+ Builds upon and enhances `#to_sentence` further by answering a sentence which all elements are inspected -- where each element of the array is called with `#inspect` -- before turned into a sentence using `"and"` as the default conjunction and `", "` as the default delimiter. This is useful when providing detailed error messages _and_ you need to detail the types of element used.
378
381
 
379
382
  [source,ruby]
380
383
  ----
381
384
  [].to_usage # ""
382
- ["test"].to_usage # "test"
383
- ["a", :b].to_usage # "a and b"
384
- [1, "a", :b, 2.0, /\w+/].map(&:inspect).to_usage # 1, "a", :b, 2.0, and /\w+/
385
- %w[one two three].to_usage # "one, two, and three"
386
- %w[eins zwei drei].to_usage "und", delimiter: " " # "eins zwei und drei"
385
+ ["demo"].to_usage # "\"demo\""
386
+ ["a", :b].to_usage # "\"a\" and :b"
387
+ [1, "a", :b, 2.0, /\w+/].to_usage # "1, \"a\", :b, 2.0, and /\\w+/"
388
+ %w[one two three].to_usage # "\"one\", \"two\", and \"three\""
389
+ %w[eins zwei drei].to_usage "und", delimiter: " " # "\"eins\" \"zwei\" und \"drei\""
387
390
  ----
388
391
 
389
392
  ==== Big Decimal
@@ -397,6 +400,28 @@ Allows one to inspect a big decimal with numeric representation.
397
400
  BigDecimal.new("5.0E-10").inspect # "#<BigDecimal:3fd3d458fe84 0.0000000005>"
398
401
  ----
399
402
 
403
+ ==== Data
404
+
405
+ ===== #diff
406
+
407
+ Allows you to obtain the differences between two objects.
408
+
409
+ [source,ruby]
410
+ ----
411
+ implementation = Data.define :a, :b, :c
412
+
413
+ one = implementation.new a: 1, b: 2, c: 3
414
+ two = implementation.new a: 3, b: 2, c: 1
415
+ three = Data.define(:x, :y).new x: 1, y: 2
416
+
417
+ one.diff one # {}
418
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
419
+ one.diff three # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
420
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
421
+ ----
422
+
423
+ Any object that _is not_ the same type will have a `nil` value as shown in the last two examples.
424
+
400
425
  ==== DateTime
401
426
 
402
427
  ===== .utc
@@ -532,6 +557,26 @@ example.deep_symbolize_keys! # {a: {b: 1}}
532
557
  example # {a: {b: 1}}
533
558
  ----
534
559
 
560
+ ===== #diff
561
+
562
+ Allows you to obtain the differences between two objects.
563
+
564
+ [source,ruby]
565
+ ----
566
+ one = {a: 1, b: 2, c: 3}
567
+ two = {a: 3, b: 2, c: 1}
568
+ three = {c: 3, b: 2, a: 1}
569
+ four = Data.define(:x, :y).new x: 1, y: 2
570
+
571
+ one.diff one # {}
572
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
573
+ one.diff three # {}
574
+ one.diff four # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
575
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
576
+ ----
577
+
578
+ 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.
579
+
535
580
  ===== #fetch_value
536
581
 
537
582
  Fetches value for exiting or missing key. Behavior is identical to `#fetch` except when the value of
@@ -540,12 +585,12 @@ expression `example.fetch(:desired_key) || "default_value"`.
540
585
 
541
586
  [source,ruby]
542
587
  ----
543
- {a: "test"}.fetch_value :a, "default" # "test"
544
- {a: "test"}.fetch_value :a # "test"
588
+ {a: "demo"}.fetch_value :a, "default" # "demo"
589
+ {a: "demo"}.fetch_value :a # "demo"
545
590
  {a: nil}.fetch_value :a, "default" # "default"
546
591
  {}.fetch_value(:a) { "default" } # "default"
547
592
  {}.fetch_value :a # KeyError
548
- {a: "test"}.fetch_value # ArgumentError
593
+ {a: "demo"}.fetch_value # ArgumentError
549
594
  ----
550
595
 
551
596
  ===== #flatten_keys
@@ -555,7 +600,7 @@ though.
555
600
 
556
601
  [source,ruby]
557
602
  ----
558
- {a: {b: 1}}.flatten_keys prefix: :test # {test_a_b: 1}
603
+ {a: {b: 1}}.flatten_keys prefix: :demo # {demo_a_b: 1}
559
604
  {a: {b: 1}}.flatten_keys delimiter: :| # {:"a|b" => 1}
560
605
 
561
606
  example = {a: {b: 1}}
@@ -570,7 +615,7 @@ though.
570
615
 
571
616
  [source,ruby]
572
617
  ----
573
- {a: {b: 1}}.flatten_keys! prefix: :test # {test_a_b: 1}
618
+ {a: {b: 1}}.flatten_keys! prefix: :demo # {demo_a_b: 1}
574
619
  {a: {b: 1}}.flatten_keys! delimiter: :| # {:"a|b" => 1}
575
620
 
576
621
  example = {a: {b: 1}}
@@ -735,11 +780,11 @@ answered instead.
735
780
 
736
781
  [source,ruby]
737
782
  ----
738
- io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
783
+ io = IO.new IO.sysopen(Pathname("demo.txt").to_s, "w+")
739
784
  other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+")
740
785
 
741
786
  io.redirect other # "#<IO:fd 20>"
742
- io.redirect(other) { |stream| stream.write "test" } # "#<IO:fd 21>"
787
+ io.redirect(other) { |stream| stream.write "demo" } # "#<IO:fd 21>"
743
788
  ----
744
789
 
745
790
  ===== #reread
@@ -748,15 +793,15 @@ Answers full stream by rewinding to beginning of stream and reading all content.
748
793
 
749
794
  [source,ruby]
750
795
  ----
751
- io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
752
- io.write "This is a test."
796
+ io = IO.new IO.sysopen(Pathname("demo.txt").to_s, "w+")
797
+ io.write "This is a demo."
753
798
 
754
- io.reread # "This is a test."
799
+ io.reread # "This is a demo."
755
800
  io.reread 4 # "This"
756
801
 
757
802
  buffer = "".dup
758
- io.reread(buffer: buffer) # "This is a test."
759
- buffer # "This is a test."
803
+ io.reread(buffer: buffer) # "This is a demo."
804
+ buffer # "This is a demo."
760
805
  ----
761
806
 
762
807
  ===== #squelch
@@ -1355,6 +1400,26 @@ Example.with_positions 1, 2, 3 # #<struct a=1, b=2, c=3>
1355
1400
  Example.with_positions 1 # #<struct a=1, b=nil, c=nil>
1356
1401
  ----
1357
1402
 
1403
+ ===== #diff
1404
+
1405
+ Allows you to obtain the differences between two objects.
1406
+
1407
+ [source,ruby]
1408
+ ----
1409
+ implementation = Struct.new :a, :b, :c
1410
+
1411
+ one = implementation.new a: 1, b: 2, c: 3
1412
+ two = implementation.new a: 3, b: 2, c: 1
1413
+ three = Struct.new(:x, :y).new x: 1, y: 2
1414
+
1415
+ one.diff one # {}
1416
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
1417
+ one.diff three # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
1418
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
1419
+ ----
1420
+
1421
+ Any object that _is not_ the same type will have a `nil` value as shown in the last two examples.
1422
+
1358
1423
  ===== #merge
1359
1424
 
1360
1425
  Merges multiple attributes without mutating itself and supports any object that responds to `#to_h`.
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/shared/values/diff"
4
+
5
+ module Refinements
6
+ # Provides additional enhancements to the Struct primitive.
7
+ module Data
8
+ refine ::Data do
9
+ import_methods Shared::Values::Diff
10
+ end
11
+ end
12
+ end
@@ -45,6 +45,12 @@ module Refinements
45
45
 
46
46
  def deep_symbolize_keys! = replace(deep_symbolize_keys)
47
47
 
48
+ def diff other
49
+ return differences_from other if other.is_a?(self.class) && keys.sort! == other.keys.sort!
50
+
51
+ each.with_object({}) { |(key, value), diff| diff[key] = [value, nil] }
52
+ end
53
+
48
54
  def fetch_value(key, *default_value, &) = fetch(key, *default_value, &) || default_value.first
49
55
 
50
56
  def flatten_keys prefix: nil, delimiter: "_"
@@ -88,6 +94,13 @@ module Refinements
88
94
  .map { |(_type, key)| self[key] || self[key.to_s] }
89
95
  .then { |values| yield values }
90
96
  end
97
+
98
+ private
99
+
100
+ def differences_from other
101
+ result = merge(other.to_h) { |_, one, two| [one, two].uniq }
102
+ result.select { |_, diff| diff.size == 2 }
103
+ end
91
104
  end
92
105
  end
93
106
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Refinements
4
+ module Shared
5
+ module Values
6
+ # Provides shared whole value functionality for knowing the difference between two objects.
7
+ module Diff
8
+ def diff other
9
+ if other.is_a? self.class
10
+ to_h.merge(other.to_h) { |_, one, two| [one, two].uniq }
11
+ .select { |_, diff| diff.size == 2 }
12
+ else
13
+ to_h.each.with_object({}) { |(key, value), diff| diff[key] = [value, nil] }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "refinements/shared/values/diff"
4
+
3
5
  module Refinements
4
6
  # Provides additional enhancements to the Struct primitive.
5
7
  module Structs
@@ -8,6 +10,8 @@ module Refinements
8
10
  end
9
11
 
10
12
  refine Struct do
13
+ import_methods Shared::Values::Diff
14
+
11
15
  def merge(...) = dup.merge!(...)
12
16
 
13
17
  def merge! object = nil
data/lib/refinements.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "refinements/arrays"
4
4
  require "refinements/big_decimals"
5
+ require "refinements/data"
5
6
  require "refinements/date_times"
6
7
  require "refinements/hashes"
7
8
  require "refinements/ios"
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 = "11.0.0"
5
+ spec.version = "11.1.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: 11.0.0
4
+ version: 11.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2023-06-13 00:00:00.000000000 Z
38
+ date: 2023-08-15 00:00:00.000000000 Z
39
39
  dependencies: []
40
40
  description:
41
41
  email:
@@ -51,6 +51,7 @@ files:
51
51
  - lib/refinements.rb
52
52
  - lib/refinements/arrays.rb
53
53
  - lib/refinements/big_decimals.rb
54
+ - lib/refinements/data.rb
54
55
  - lib/refinements/date_times.rb
55
56
  - lib/refinements/hashes.rb
56
57
  - lib/refinements/ios.rb
@@ -59,6 +60,7 @@ files:
59
60
  - lib/refinements/pathnames.rb
60
61
  - lib/refinements/shared/enumerables/many.rb
61
62
  - lib/refinements/shared/ios/reread.rb
63
+ - lib/refinements/shared/values/diff.rb
62
64
  - lib/refinements/string_ios.rb
63
65
  - lib/refinements/strings.rb
64
66
  - lib/refinements/structs.rb
@@ -90,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  - !ruby/object:Gem::Version
91
93
  version: '0'
92
94
  requirements: []
93
- rubygems_version: 3.4.14
95
+ rubygems_version: 3.4.18
94
96
  signing_key:
95
97
  specification_version: 4
96
98
  summary: A collection of core Ruby object refinements.
metadata.gz.sig CHANGED
Binary file