refinements 11.0.1 → 11.1.1

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: efdcd2042bcfde5031fad3d0049e01fc4e1ad23a9d4841ee601fdcb02a96d3af
4
- data.tar.gz: 55fac5447439c53705870a9409268e96aaf633e7a420f9d4678257f9b68f078d
3
+ metadata.gz: 91fae4e74017d86d0ca24e153dc7210fd9503276ccdf79da032e0f8f8ee2d181
4
+ data.tar.gz: eeea2c49941fe6508e9e4aab89aa42f38c2e23efd48b4f5381d4487a08061e3b
5
5
  SHA512:
6
- metadata.gz: 81949b0fb95b4aca53d6fd88f51d8cb4f0c8738bbb3eac83816880ff6b479ac86228847dd6660d8a99a861c5e3aee6e6985a0628764af037b328db55422cc7fb
7
- data.tar.gz: 6b40c6be0c5cc6304366fe60c8df54bca9e3ab366338f45308b2267f9a81f6adb123002740feb933af3313a0349a9a5035c39525c0b90d48f875842fefd0c3cf
6
+ metadata.gz: '08e77b3c0837d2158593f431a6cdd427cdc7cf9a1605178c0762444549b08807e3f3890cd7c578a8bc429d453b8961d38649a412b4616ea92889f745a721bc1f'
7
+ data.tar.gz: 20525ddb58f09cb45d4fc39fe652d0790b156f387bea40fe0f6574be0d396d8607cc6e9f692a6e6feee78f8608b102aaab5d9219ef6f4d43dcdd5e73e8ad4957
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
@@ -184,9 +187,9 @@ Answers the first element which evaluates to true from a filtered collection.
184
187
  [source,ruby]
185
188
  ----
186
189
  handlers = [
187
- ->(object) { object if object == :b },
190
+ -> object { object if object == :b },
188
191
  proc { false },
189
- ->(object) { object if object == :a }
192
+ -> object { object if object == :a }
190
193
  ]
191
194
 
192
195
  handlers.filter_find # Enumerator::Lazy
@@ -206,7 +209,7 @@ Adds given array or elements without mutating itself.
206
209
 
207
210
  ===== #intersperse
208
211
 
209
- Inserts additional elements or an array between all members of given array.
212
+ Inserts additional elements, or an array, between all members of given array.
210
213
 
211
214
  [source,ruby]
212
215
  ----
@@ -234,11 +237,13 @@ Answers the maximum extracted value from a collection of objects.
234
237
 
235
238
  [source,ruby]
236
239
  ----
237
- Point = Struct.new :x, :y
240
+ Point = Data.define :x, :y
238
241
  points = [Point[x: 1, y: 2], Point[x: 0, y: 1], Point[x: 2, y: 3]]
239
242
 
240
- points.maximum(:x) # 2
241
- points.maximum(:y) # 3
243
+ points.maximum :x # 2
244
+ points.maximum :y # 3
245
+ points.maximum :z # undefined method `z' for #<data Point x=1, y=2> (NoMethodError)
246
+ [].maximum :x # nil
242
247
  ----
243
248
 
244
249
  ===== #mean
@@ -259,11 +264,13 @@ Answers the minimum extracted value from a collection of objects.
259
264
 
260
265
  [source,ruby]
261
266
  ----
262
- Point = Struct.new :x, :y
267
+ Point = Data.define :x, :y
263
268
  points = [Point[x: 1, y: 2], Point[x: 0, y: 1], Point[x: 2, y: 3]]
264
269
 
265
- points.minimum(:x) # 0
266
- points.minimum(:y) # 1
270
+ points.minimum :x # 0
271
+ points.minimum :y # 1
272
+ points.minimum :z # undefined method `z' for #<data Point x=1, y=2> (NoMethodError)
273
+ [].minimum :x # nil
267
274
  ----
268
275
 
269
276
  ===== #pad
@@ -289,7 +296,7 @@ array = [{name: "a", label: "A"}, {name: "b", label: "B"}, {name: "c", label: "C
289
296
  array.pick :name # "a"
290
297
  array.pick :name, :label # ["a", "A"]
291
298
  array.pick # nil
292
- [].pick(:other) # nil
299
+ [].pick :other # nil
293
300
  ----
294
301
 
295
302
  ===== #pluck
@@ -312,10 +319,10 @@ Answers mutated array where an element -- at a specific index -- is replaced by
312
319
 
313
320
  [source,ruby]
314
321
  ----
315
- %i[a b c].replace_at(0, :x) # [:x, :b, :c]
316
- %i[a b c].replace_at(1, :x) # [:a, :x, :c]
317
- %i[a b c].replace_at(1, :x, :y) # [:a, :x, :y, :c]
318
- %i[a b c].replace_at(-1, :x) # [:a, :b, :x]
322
+ %i[a b c].replace_at 0, :x # [:x, :b, :c]
323
+ %i[a b c].replace_at 1, :x # [:a, :x, :c]
324
+ %i[a b c].replace_at 1, :x, :y # [:a, :x, :y, :c]
325
+ %i[a b c].replace_at -1, :x # [:a, :b, :x]
319
326
  ----
320
327
 
321
328
  ===== #ring
@@ -397,6 +404,28 @@ Allows one to inspect a big decimal with numeric representation.
397
404
  BigDecimal.new("5.0E-10").inspect # "#<BigDecimal:3fd3d458fe84 0.0000000005>"
398
405
  ----
399
406
 
407
+ ==== Data
408
+
409
+ ===== #diff
410
+
411
+ Allows you to obtain the differences between two objects.
412
+
413
+ [source,ruby]
414
+ ----
415
+ implementation = Data.define :a, :b, :c
416
+
417
+ one = implementation.new a: 1, b: 2, c: 3
418
+ two = implementation.new a: 3, b: 2, c: 1
419
+ three = Data.define(:x, :y).new x: 1, y: 2
420
+
421
+ one.diff one # {}
422
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
423
+ one.diff three # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
424
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
425
+ ----
426
+
427
+ Any object that _is not_ the same type will have a `nil` value as shown in the last two examples.
428
+
400
429
  ==== DateTime
401
430
 
402
431
  ===== .utc
@@ -532,6 +561,26 @@ example.deep_symbolize_keys! # {a: {b: 1}}
532
561
  example # {a: {b: 1}}
533
562
  ----
534
563
 
564
+ ===== #diff
565
+
566
+ Allows you to obtain the differences between two objects.
567
+
568
+ [source,ruby]
569
+ ----
570
+ one = {a: 1, b: 2, c: 3}
571
+ two = {a: 3, b: 2, c: 1}
572
+ three = {c: 3, b: 2, a: 1}
573
+ four = Data.define(:x, :y).new x: 1, y: 2
574
+
575
+ one.diff one # {}
576
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
577
+ one.diff three # {}
578
+ one.diff four # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
579
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
580
+ ----
581
+
582
+ 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.
583
+
535
584
  ===== #fetch_value
536
585
 
537
586
  Fetches value for exiting or missing key. Behavior is identical to `#fetch` except when the value of
@@ -751,12 +800,12 @@ Answers full stream by rewinding to beginning of stream and reading all content.
751
800
  io = IO.new IO.sysopen(Pathname("demo.txt").to_s, "w+")
752
801
  io.write "This is a demo."
753
802
 
754
- io.reread # "This is a demo."
755
- io.reread 4 # "This"
803
+ io.reread # "This is a demo."
804
+ io.reread 4 # "This"
756
805
 
757
806
  buffer = "".dup
758
- io.reread(buffer: buffer) # "This is a demo."
759
- buffer # "This is a demo."
807
+ io.reread(buffer:) # "This is a demo."
808
+ buffer # "This is a demo."
760
809
  ----
761
810
 
762
811
  ===== #squelch
@@ -784,17 +833,17 @@ Answers previously written content by rewinding to beginning of device.
784
833
  # With File.
785
834
  device = Logger::LogDevice.new "test.log"
786
835
  device.write "Test."
787
- device.reread # "Test."
836
+ device.reread # "Test."
788
837
 
789
838
  # With StringIO.
790
839
  device = Logger::LogDevice.new StringIO.new
791
840
  device.write "Test."
792
- device.reread # "Test."
841
+ device.reread # "Test."
793
842
 
794
843
  # With STDOUT.
795
844
  device = Logger::LogDevice.new $stdout
796
845
  device.write "Test."
797
- device.reread # ""
846
+ device.reread # ""
798
847
  ----
799
848
 
800
849
  ==== Logger
@@ -808,17 +857,17 @@ Answers previously written content by rewinding to beginning of log.
808
857
  # With File.
809
858
  logger = Logger.new "test.log"
810
859
  logger.write "Test."
811
- logger.reread # "Test."
860
+ logger.reread # "Test."
812
861
 
813
862
  # With StringIO.
814
863
  logger = Logger.new StringIO.new
815
864
  logger.write "Test."
816
- logger.reread # "Test."
865
+ logger.reread # "Test."
817
866
 
818
867
  # With STDOUT.
819
868
  logger = Logger.new $stdout
820
869
  logger.write "Test."
821
- logger.reread # ""
870
+ logger.reread # ""
822
871
  ----
823
872
 
824
873
  ===== #any
@@ -846,7 +895,7 @@ construct a valid path.
846
895
 
847
896
  [source,ruby]
848
897
  ----
849
- Pathname(nil) # Pathname("")
898
+ Pathname nil # Pathname("")
850
899
  ----
851
900
 
852
901
  ===== .home
@@ -972,9 +1021,9 @@ Deletes a path prefix and answers new pathname.
972
1021
 
973
1022
  [source,ruby]
974
1023
  ----
975
- Pathname("a/path/example-test.rb").delete_prefix("example-") # Pathname("a/path/test.rb")
976
- Pathname("example-test.rb").delete_prefix("example-") # Pathname("test.rb")
977
- Pathname("example-test.rb").delete_prefix("miss") # Pathname("example-test.rb")
1024
+ Pathname("a/path/example-test.rb").delete_prefix "example-" # Pathname("a/path/test.rb")
1025
+ Pathname("example-test.rb").delete_prefix "example-" # Pathname("test.rb")
1026
+ Pathname("example-test.rb").delete_prefix "miss" # Pathname("example-test.rb")
978
1027
  ----
979
1028
 
980
1029
  ===== #delete_suffix
@@ -983,9 +1032,9 @@ Deletes a path suffix and answers new pathname.
983
1032
 
984
1033
  [source,ruby]
985
1034
  ----
986
- Pathname("a/path/test-example.rb").delete_suffix("-example") # Pathname("a/path/test.rb")
987
- Pathname("test-example.rb").delete_suffix("-example") # Pathname("test.rb")
988
- Pathname("test-example.rb").delete_suffix("miss") # Pathname("test-example.rb")
1035
+ Pathname("a/path/test-example.rb").delete_suffix "-example" # Pathname("a/path/test.rb")
1036
+ Pathname("test-example.rb").delete_suffix "-example" # Pathname("test.rb")
1037
+ Pathname("test-example.rb").delete_suffix "miss" # Pathname("test-example.rb")
989
1038
  ----
990
1039
 
991
1040
  ===== #directories
@@ -1039,10 +1088,10 @@ Same behavior as `String#gsub` but answers a path with patterns replaced with de
1039
1088
 
1040
1089
  [source,ruby]
1041
1090
  ----
1042
- Pathname("/a/path/some/path").gsub("path", "test")
1091
+ Pathname("/a/path/some/path").gsub "path", "test"
1043
1092
  # Pathname("/a/test/some/test")
1044
1093
 
1045
- Pathname("/%placeholder%/some/%placeholder%").gsub("%placeholder%", "test")
1094
+ Pathname("/%placeholder%/some/%placeholder%").gsub "%placeholder%", "test"
1046
1095
  # Pathname("/test/some/test")
1047
1096
  ----
1048
1097
 
@@ -1090,11 +1139,11 @@ Pathname("example.txt").name # Pathname("example")
1090
1139
 
1091
1140
  ===== #relative_parent
1092
1141
 
1093
- Answers relative path from parent directory. This is a complement to `#relative_path_from`.
1142
+ Answers relative path from parent directory. This complements: `#relative_path_from`.
1094
1143
 
1095
1144
  [source,ruby]
1096
1145
  ----
1097
- Pathname("/one/two/three").relative_parent("/one") # Pathname "two"
1146
+ Pathname("/one/two/three").relative_parent "/one" # Pathname "two"
1098
1147
  ----
1099
1148
 
1100
1149
  ===== #remove_dir
@@ -1333,8 +1382,8 @@ io.reread # "This is a test."
1333
1382
  io.reread 4 # "This"
1334
1383
 
1335
1384
  buffer = "".dup
1336
- io.reread(buffer: buffer) # "This is a test."
1337
- buffer # "This is a test."
1385
+ io.reread(buffer:) # "This is a test."
1386
+ buffer # "This is a test."
1338
1387
  ----
1339
1388
 
1340
1389
  ==== Struct
@@ -1355,6 +1404,26 @@ Example.with_positions 1, 2, 3 # #<struct a=1, b=2, c=3>
1355
1404
  Example.with_positions 1 # #<struct a=1, b=nil, c=nil>
1356
1405
  ----
1357
1406
 
1407
+ ===== #diff
1408
+
1409
+ Allows you to obtain the differences between two objects.
1410
+
1411
+ [source,ruby]
1412
+ ----
1413
+ implementation = Struct.new :a, :b, :c
1414
+
1415
+ one = implementation.new a: 1, b: 2, c: 3
1416
+ two = implementation.new a: 3, b: 2, c: 1
1417
+ three = Struct.new(:x, :y).new x: 1, y: 2
1418
+
1419
+ one.diff one # {}
1420
+ one.diff two # {:a=>[1, 3], :c=>[3, 1]}
1421
+ one.diff three # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
1422
+ one.diff Object.new # {:a=>[1, nil], :b=>[2, nil], :c=>[3, nil]}
1423
+ ----
1424
+
1425
+ Any object that _is not_ the same type will have a `nil` value as shown in the last two examples.
1426
+
1358
1427
  ===== #merge
1359
1428
 
1360
1429
  Merges multiple attributes without mutating itself and supports any object that responds to `#to_h`.
@@ -1393,8 +1462,7 @@ example # #<struct Struct::Example a=10, b=20, c=30>
1393
1462
 
1394
1463
  Transforms values without mutating itself. An optional hash can be supplied to target specific
1395
1464
  attributes. In the event that a block isn't supplied, the struct will answer itself since there is
1396
- nothing to operate on. Behavior is the same regardless of whether the struct is constructed using
1397
- positional or keyword arguments. Works regardless of whether the struct is constructed with
1465
+ nothing to operate on. Works regardless of whether the struct is constructed with
1398
1466
  positional or keyword arguments.
1399
1467
 
1400
1468
  [source,ruby]
@@ -1412,8 +1480,7 @@ example # #<struct Str
1412
1480
 
1413
1481
  Transforms values while mutating itself. An optional hash can be supplied to target specific
1414
1482
  attributes. In the event that a block isn't supplied, the struct will answer itself since there is
1415
- nothing to operate on. Behavior is the same regardless of whether the struct is constructed using
1416
- positional or keyword arguments. Works regardless of whether the struct is constructed with
1483
+ nothing to operate on. Works regardless of whether the struct is constructed with
1417
1484
  positional or keyword arguments.
1418
1485
 
1419
1486
  [source,ruby]
@@ -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,7 +45,13 @@ module Refinements
45
45
 
46
46
  def deep_symbolize_keys! = replace(deep_symbolize_keys)
47
47
 
48
- def fetch_value(key, *default_value, &) = fetch(key, *default_value, &) || default_value.first
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
+
54
+ def fetch_value(key, *default, &) = fetch(key, *default, &) || default.first
49
55
 
50
56
  def flatten_keys prefix: nil, delimiter: "_"
51
57
  reduce({}) do |accumulator, (key, value)|
@@ -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.1"
5
+ spec.version = "11.1.1"
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.1
4
+ version: 11.1.1
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-19 00:00:00.000000000 Z
38
+ date: 2023-11-04 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.21
94
96
  signing_key:
95
97
  specification_version: 4
96
98
  summary: A collection of core Ruby object refinements.
metadata.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- #�],�Gi�ָ7G��ͣDw�>�' ���1D4z���+Ph(Y��&i�?���[�N)��3��b Gca0��OW��g+gV܈9e⍋dD��u�G��y��"ʥ��O�Bkl�a2m z���˗���Qx�
2
- � _8��� ��&�e�������KiEYm�ꏪgH[��?��I a��üwh!P��Nx{�bo��q�k]+8��}���֎)4�>���o�̂K�*�"���enT��Qe�W!2��C�~�z�t+���� o.(o���+�en:����T�
1
+ im����uV�?q��6
2
+ bM���e������T�`�!��9�u=�R��[m���E,�jq=7�a��EB\w8�\�����ɖv���U��(m��Z���ڌ#Np�'���f���,�=��.�x}8_����D����ce�:�(hr0���!uy ��z��#L[����x������^B���*K4ўS�+�S#�@��kR!9Z��[1���
3
+ �k�_�p�}˄��i|�a��!N!��΢hB��<0؛M�ri��?��U&u���̍9����i1?���9����V���D:�=1Y�X|�A6��v�c9�z��Y���u���u�.m�1e����nW��R�+�s���B���~�`l�h