refinements 7.14.0 → 7.18.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: 4abbbd79616d97836ca58503bb4638e2638e14732e76e7c00b3f5c033f708edc
4
- data.tar.gz: 516c79b5361a7512ca4e63c72303d8fb0d2cb85c693bc9aa13c36ef767580f10
3
+ metadata.gz: 5dd9bd6cbc9800c0c66d8c1ae4ed93124143f196a4173723438bb7d9fc12957e
4
+ data.tar.gz: 9d6651c258900528aa68db2a8b26e1bd77aef9be70fe3fbeadf63e4c0580ab45
5
5
  SHA512:
6
- metadata.gz: 2f15aa4b466d6e610a2ffc45ad16285d27107c93a4260d214abcee42e66005951a5f2a708da6b04a28826ab3abd0a85ad0e1a707782b6ba5c51ef5cb0b705ec7
7
- data.tar.gz: ec214191217bb870ca264fbfe3fa31d57b6c37c28e0f92806f779d3ea8400fbac11ee4aa38c82d6d10d7b07187a2360a7aa810ef802e6d219a217043cd76e69c
6
+ metadata.gz: bad8de30ca4c07607013a08d8346d1390b3f6223b943588ac94ce1c7e44fb5f59ebb634c9adb4d0f1773929ede430ffc7025fa9e6fcdca6f055d3bfa4c5cbeb8
7
+ data.tar.gz: d81030c3b1a8db17fff6cafea12496041d2cb95e87452cf932c7cf03c60dea4971f1bbce59c30fde5b5a8d80f713b5a00fca1cbcbba6bbb1962f77e21984f9b0
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -28,6 +28,7 @@ Enhances the following objects:
28
28
  * Pathname
29
29
  * String
30
30
  * StringIO
31
+ * Structs
31
32
 
32
33
  == Requirements
33
34
 
@@ -75,6 +76,7 @@ require "refinements/ios"
75
76
  require "refinements/pathnames"
76
77
  require "refinements/strings"
77
78
  require "refinements/string_ios"
79
+ require "refinements/structs"
78
80
  ----
79
81
 
80
82
  === Using
@@ -94,6 +96,7 @@ class Example
94
96
  using Refinements::Pathnames
95
97
  using Refinements::Strings
96
98
  using Refinements::StringIOs
99
+ using Refinements::Structs
97
100
  end
98
101
  ----
99
102
 
@@ -168,6 +171,18 @@ Answers mean/average all elements within an array.
168
171
  [1.25, 1.5, 1.75].mean # => 1.5
169
172
  ----
170
173
 
174
+ ===== #pad
175
+
176
+ Answers new array padded with given value up to a maximum size. Useful in situations where an array
177
+ needs to be a specific size with padded values.
178
+
179
+ [source,ruby]
180
+ ----
181
+ [1].pad 0 # => [1]
182
+ [1].pad 0, max: 3 # => [1, 0, 0]
183
+ [1, 2].pad 3, max: 3 # => [1, 2, 3]
184
+ ----
185
+
171
186
  ===== #ring
172
187
 
173
188
  Answers a circular array which can enumerate before, current, after elements.
@@ -237,10 +252,10 @@ Answers new hash where every top-level missing key has the same default value.
237
252
  [source,ruby]
238
253
  ----
239
254
  example = Hash.with_default ""
240
- example[:a] # => ""
255
+ example[:a] # => ""
241
256
 
242
257
  example = Hash.with_default []
243
- example[:b] # => []
258
+ example[:b] # => []
244
259
  ----
245
260
 
246
261
  ===== #deep_merge
@@ -468,7 +483,7 @@ Passes each hash value as a block argument for further processing.
468
483
  [source,ruby]
469
484
  ----
470
485
  example = {unit: "221B", street: "Baker Street", city: "London", country: "UK"}
471
- example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
486
+ example.use { |unit, street| "#{unit} #{street}" } # => "221B Baker Street"
472
487
  ----
473
488
 
474
489
  ==== IO
@@ -481,11 +496,8 @@ block, you'll need to close the stream manually.
481
496
 
482
497
  [source,ruby]
483
498
  ----
484
- io = IO.void
485
- io.closed? # => false
486
-
487
- io = IO.void { |void| void.write "nevermore" }
488
- io.closed? # => true
499
+ io = IO.void # => #<IO:fd 20>
500
+ io = IO.void { |void| void.write "nevermore" } # => #<IO:(closed)>
489
501
  ----
490
502
 
491
503
  ===== #redirect
@@ -498,11 +510,8 @@ answered instead.
498
510
  io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
499
511
  other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+")
500
512
 
501
- io.redirect other # => `io`
502
-
503
- io.redirect(other) { |stream| stream.write "test" }
504
- .close # => ""
505
- other.close # => "test"
513
+ io.redirect other # => #<IO:fd 20>
514
+ io.redirect(other) { |stream| stream.write "test" } # => #<IO:fd 21>
506
515
  ----
507
516
 
508
517
  ===== #reread
@@ -518,40 +527,110 @@ io.reread # => "This is a test."
518
527
  io.reread 4 # => "This"
519
528
 
520
529
  buffer = "".dup
521
- io.reread(buffer: buffer)
522
- buffer # => "This is a test."
530
+ io.reread(buffer: buffer) # => "This is a test."
531
+ buffer # => "This is a test."
523
532
  ----
524
533
 
525
534
  ===== #squelch
526
535
 
527
- Temporarily ignores any reads/writes for current stream for all code executed within the block. When
528
- not given a block, it answers itself.
536
+ Temporarily ignores any reads/writes for code executed within a block. Answers itself without any
537
+ arguments or when given a block.
529
538
 
530
539
  [source,ruby]
531
540
  ----
532
541
  io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
533
- io.squelch { io.write "Test" }
534
- io.reread # => ""
542
+ io.squelch # => #<IO:fd 20>
543
+ io.squelch { io.write "Test" } # => #<IO:fd 20>
544
+ io.reread # => ""
535
545
  ----
536
546
 
537
547
  ==== Pathname
538
548
 
539
549
  ===== Pathname
540
550
 
541
- Enhances the conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in
542
- order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still
543
- invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that
544
- can still be used to construct a valid path.
551
+ Enhances the `Kernel` conversion function which casts `nil` into a pathname in order to avoid:
552
+ `TypeError (no implicit conversion of nil into String)`. The pathname remains invalid but at least
553
+ you have an instance of `Pathname`, which behaves like a _Null Object_, that can be used to
554
+ construct a valid path.
545
555
 
546
556
  [source,ruby]
547
557
  ----
548
558
  Pathname(nil) # => Pathname("")
549
559
  ----
550
560
 
561
+ ===== .home
562
+
563
+ Answers user home directory.
564
+
565
+ [source,ruby]
566
+ ----
567
+ Pathname.home # => Pathname "/Users/bkuhlmann"
568
+ ----
569
+
570
+ ===== .make_temp_dir
571
+
572
+ Wraps `Dir.mktmpdir` with the following behavior (see
573
+ link:https://rubyapi.org/o/Dir.mktmpdir#method-c-mktmpdir[Dir.mktmpdir] for details):
574
+
575
+ * *Without Block* - Answers a newly created Pathname instance which is not automatically cleaned up.
576
+ * *With Block* Yields a Pathname instance, answers result of given block, and automatidally cleans
577
+ up temporary directory after block exits.
578
+
579
+ The following examples use truncated temporary directories for illustration purposes only. In
580
+ reality, these paths will be longer depending on which operating system you are using.
581
+
582
+ [source,ruby]
583
+ ----
584
+ Pathname.make_temp_dir # => Pathname:/var/folders/T/temp-20200101-16940-r8
585
+ Pathname.make_temp_dir prefix: "prefix-" # => Pathname:/var/folders/T/prefix-20200101-16940-r8
586
+ Pathname.make_temp_dir suffix: "-suffix" # => Pathname:/var/folders/T/temp-20200101-16940-r8-suffix
587
+ Pathname.make_temp_dir prefix: "prefix-", suffix: "-suffix" # => Pathname:/var/folders/T/prefix-20200101-16940-r8-suffix
588
+ Pathname.make_temp_dir root: "/example" # => Pathname:/example/temp-20200101-16940-r8
589
+ Pathname.make_temp_dir { "I am a block result" } # => "I am a block result"
590
+ Pathname.make_temp_dir { |path| path.join "sub_dir" } # => Pathname:/var/folders/T/temp-20200101-16940-r8/sub_dir
591
+ ----
592
+
593
+ ===== .require_tree
594
+
595
+ Requires all files in given root path and corresponding nested tree structure. All files are sorted
596
+ before being required to ensure consistent behavior. Example:
597
+
598
+ [source,ruby]
599
+ ----
600
+ # Before
601
+ Dir[File.join(__dir__, "support/shared_contexts/**/*.rb")].sort.each { |path| require path }
602
+
603
+ # After
604
+ Pathname.require_tree __dir__, "support/shared_contexts/**/*.rb"
605
+ ----
606
+
607
+ The following are further examples of potential usage:
608
+
609
+ [source,ruby]
610
+ ----
611
+ # Requires all files in root directory and below.
612
+ Pathname.require_tree __dir__
613
+
614
+ # Requires all files in `/test/**/*.rb` and below.
615
+ Pathname.require_tree "/test"
616
+
617
+ # Requires all files in RSpec shared examples directory structure.
618
+ Pathname.require_tree Bundler.root.join("spec"), "support/shared_examples/**/*.rb"
619
+ ----
620
+
621
+ ===== .root
622
+
623
+ Answers operating system root path.
624
+
625
+ [source,ruby]
626
+ ----
627
+ Pathname.root # => Pathname "/"
628
+ ----
629
+
551
630
  ===== #change_dir
552
631
 
553
- Inherits and wraps `Dir.chdir` behavior by changing to directory of current path. See
554
- link:https://rubyapi.org/2.7/o/s?q=Dir.chdir[Dir.chdir] for details.
632
+ Wraps `Dir.chdir` behavior by changing to directory of current path. See
633
+ link:https://rubyapi.org/o/Dir.chdir#method-c-chdir[Dir.chdir] for details.
555
634
 
556
635
  [source,ruby]
557
636
  ----
@@ -559,23 +638,23 @@ Pathname.pwd # => "/"
559
638
  Pathname("/test").make_dir.change_dir # => Pathname "/test"
560
639
  Pathname.pwd # => "/test"
561
640
 
562
- Pathname.pwd # => "/"
563
- Pathname("/test").make_dir.change_dir { # Implementation details } # => Pathname "/test"
564
- Pathname.pwd # => "/"
641
+ Pathname.pwd # => "/"
642
+ Pathname("/test").make_dir.change_dir { "example" } # => "example"
643
+ Pathname.pwd # => "/"
565
644
  ----
566
645
 
567
646
  ===== #copy
568
647
 
569
- Copies file from current location to new location.
648
+ Copies file from current location to new location while answering itself so it can be chained.
570
649
 
571
650
  [source,ruby]
572
651
  ----
573
- Pathname("input.txt").copy Pathname("output.txt")
652
+ Pathname("input.txt").copy Pathname("output.txt") # => Pathname("input.txt")
574
653
  ----
575
654
 
576
655
  ===== #directories
577
656
 
578
- Answers all or filtered directories for current path.
657
+ Answers all directories or filtered directories for current path.
579
658
 
580
659
  [source,ruby]
581
660
  ----
@@ -590,12 +669,12 @@ Answers file extensions as an array.
590
669
 
591
670
  [source,ruby]
592
671
  ----
593
- Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
672
+ Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
594
673
  ----
595
674
 
596
675
  ===== #files
597
676
 
598
- Answers all or filtered files for current path.
677
+ Answers all files or filtered files for current path.
599
678
 
600
679
  [source,ruby]
601
680
  ----
@@ -623,9 +702,9 @@ Ensures all ancestor directories are created for a path.
623
702
 
624
703
  [source,ruby]
625
704
  ----
626
- Pathname("/one/two").make_ancestors
627
- Pathname("/one").exist? # => true
628
- Pathname("/one/two").exist? # => false
705
+ Pathname("/one/two").make_ancestors # => Pathname("/one/two")
706
+ Pathname("/one").exist? # => true
707
+ Pathname("/one/two").exist? # => false
629
708
  ----
630
709
 
631
710
  ===== #make_dir
@@ -708,7 +787,8 @@ immediate writing back to the same file.
708
787
 
709
788
  [source,ruby]
710
789
  ----
711
- Pathname("/test.txt").rewrite { |content| content.sub "[placeholder]", "example" }
790
+ Pathname("/test.txt").rewrite # => Pathname("/test.txt")
791
+ Pathname("/test.txt").rewrite { |body| body.sub "[token]", "example" } # => Pathname("/test.txt")
712
792
  ----
713
793
 
714
794
  ===== #touch
@@ -717,8 +797,20 @@ Updates access and modification times for path. Defaults to current time.
717
797
 
718
798
  [source,ruby]
719
799
  ----
720
- Pathname("example.txt").touch
721
- Pathname("example.txt").touch at: Time.now - 1
800
+ Pathname("example.txt").touch # => Pathname("example.txt")
801
+ Pathname("example.txt").touch at: Time.now - 1 # => Pathname("example.txt")
802
+ ----
803
+
804
+ ===== #write
805
+
806
+ Writes to file and answers itself so it can be chained. See `IO.write` for details on additional
807
+ options.
808
+
809
+ [source,ruby]
810
+ ----
811
+ Pathname("example.txt").write "test" # => Pathname("example.txt")
812
+ Pathname("example.txt").write "test", offset: 1 # => Pathname("example.txt")
813
+ Pathname("example.txt").write "test", mode: "a" # => Pathname("example.txt")
722
814
  ----
723
815
 
724
816
  ==== String
@@ -838,8 +930,143 @@ io.reread # => "This is a test."
838
930
  io.reread 4 # => "This"
839
931
 
840
932
  buffer = "".dup
841
- io.reread(buffer: buffer)
842
- buffer # => "This is a test."
933
+ io.reread(buffer: buffer) # => "This is a test."
934
+ buffer # => "This is a test."
935
+ ----
936
+
937
+ ==== Struct
938
+
939
+ ===== .keyworded?
940
+
941
+ Answers whether a struct was constructed with keyword or positional arguments.
942
+
943
+ [source,ruby]
944
+ ----
945
+ Struct.new(:a, keyword_init: true).keyworded? # => true
946
+ Struct.new(:a).keyworded? # => false
947
+ ----
948
+
949
+ ===== .with_keywords
950
+
951
+ Answers a struct instance with given keyword arguments regardless of
952
+ whether the struct was constructed with positional or keyword arguments.
953
+
954
+ [source,ruby]
955
+ ----
956
+ Example = Struct.new :a, :b, :c
957
+ Example.with_keywords a: 1, b: 2, c: 3 # => #<struct a=1, b=2, c=3>
958
+ Example.with_keywords a: 1 # => #<struct a=1, b=nil, c=nil>
959
+ Example.with_keywords c: 1 # => #<struct a=nil, b=nil, c=1>
960
+
961
+ Example = Struct.new :a, :b, :c, keyword_init: true
962
+ Example.with_keywords a: 1, b: 2, c: 3 # => #<struct a=1, b=2, c=3>
963
+ Example.with_keywords a: 1 # => #<struct a=1, b=nil, c=nil>
964
+ Example.with_keywords c: 1 # => #<struct a=nil, b=nil, c=1>
965
+ ----
966
+
967
+ ===== .with_positions
968
+
969
+ Answers a struct instance with given positional arguments regardless of
970
+ whether the struct was constructed with positional or keyword arguments.
971
+
972
+ [source,ruby]
973
+ ----
974
+ Example = Struct.new :a, :b, :c
975
+ Example.with_positions 1, 2, 3 # => #<struct a=1, b=2, c=3>
976
+ Example.with_positions 1 # => #<struct a=1, b=nil, c=nil>
977
+
978
+ Example = Struct.new :a, :b, :c, keyword_init: true
979
+ Example.with_positions 1, 2, 3 # => #<struct a=1, b=2, c=3>
980
+ Example.with_positions 1 # => #<struct a=1, b=nil, c=nil>
981
+ ----
982
+
983
+ ===== #merge
984
+
985
+ Merges multiple attributes without mutating itself.
986
+
987
+ [source,ruby]
988
+ ----
989
+ Example = Struct.new :a, :b, :c
990
+ example = Example[1, 2, 3]
991
+ example.merge a: 10 # => #<struct a=10, b=2, c=3>
992
+ example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
993
+ example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
994
+ example # => #<struct a=1, b=2, c=3>
995
+
996
+ Example = Struct.new :a, :b, :c, keyword_init: true
997
+ example = Example[a: 1, b: 2, c: 3]
998
+ example.merge a: 10 # => #<struct a=10, b=2, c=3>
999
+ example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
1000
+ example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
1001
+ example # => #<struct a=1, b=2, c=3>
1002
+ ----
1003
+
1004
+ ===== #merge!
1005
+
1006
+ Merges multiple attributes while mutating itself.
1007
+
1008
+ [source,ruby]
1009
+ ----
1010
+ Example = Struct.new :a, :b, :c
1011
+ example = Example[1, 2, 3]
1012
+ example.merge! a: 10 # => #<struct a=10, b=2, c=3>
1013
+ example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
1014
+ example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
1015
+ example # => #<struct a=10, b=20, c=30>
1016
+
1017
+ Example = Struct.new :a, :b, :c, keyword_init: true
1018
+ example = Example[a: 1, b: 2, c: 3]
1019
+ example.merge! a: 10 # => #<struct a=10, b=2, c=3>
1020
+ example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
1021
+ example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
1022
+ example # => #<struct a=10, b=20, c=30>
1023
+ ----
1024
+
1025
+ ===== #revalue
1026
+
1027
+ Transforms values without mutating itself. An optional hash can be supplied to pinpoint and
1028
+ transform specific attributes. In the event that a block isn't supplied, the struct will answer
1029
+ itself since there is nothing to operate on. Behavior is the same regardless of whether the struct
1030
+ is constructed using positional or keyword arguments. A positional struct is used in the examples
1031
+ below but a keyword struct would work too.
1032
+
1033
+ [source,ruby]
1034
+ ----
1035
+ Example = Struct.new :a, :b, :c
1036
+
1037
+ example = Example[1, 2, 3]
1038
+ example.revalue { |value| value * 2 } # => #<struct a=2, b=4, c=6>
1039
+ example.revalue(c: 2) { |previous, current| previous + current } # => #<struct a=1, b=2, c=5>
1040
+ example.revalue c: 2 # => #<struct a=1, b=2, c=3>
1041
+ example.revalue # => #<struct a=1, b=2, c=3>
1042
+ example # => #<struct a=1, b=2, c=3>
1043
+
1044
+ ----
1045
+
1046
+ ===== #revalue!
1047
+
1048
+ Transforms values while mutating itself. An optional hash can be supplied to pinpoint and transform
1049
+ specific attributes. In the event that a block isn't supplied, the struct will answer itself since
1050
+ there is nothing to operate on. Behavior is the same regardless of whether the struct is constructed
1051
+ using positional or keyword arguments. A positional struct is used in the examples below but a
1052
+ keyword struct would work too.
1053
+
1054
+ [source,ruby]
1055
+ ----
1056
+ Example = Struct.new :a, :b, :c
1057
+
1058
+ example = Example[1, 2, 3]
1059
+ example.revalue! { |value| value * 2 } # => #<struct a=2, b=4, c=6>
1060
+ example # => #<struct a=2, b=4, c=6>
1061
+
1062
+ example = Example[1, 2, 3]
1063
+ example.revalue!(c: 2) { |previous, current| previous + current } # => #<struct a=1, b=2, c=5>
1064
+ example # => #<struct a=1, b=2, c=5>
1065
+
1066
+ example = Example[1, 2, 3]
1067
+ example.revalue! c: 2 # => #<struct a=1, b=2, c=3>
1068
+ example.revalue! # => #<struct a=1, b=2, c=3>
1069
+ example # => #<struct a=1, b=2, c=3>
843
1070
  ----
844
1071
 
845
1072
  == Development
@@ -10,3 +10,4 @@ require "refinements/ios"
10
10
  require "refinements/pathnames"
11
11
  require "refinements/strings"
12
12
  require "refinements/string_ios"
13
+ require "refinements/structs"
@@ -37,6 +37,10 @@ module Refinements
37
37
  size.zero? ? 0 : sum(0) / size
38
38
  end
39
39
 
40
+ def pad value, max: size
41
+ dup.fill value, size..(max - 1)
42
+ end
43
+
40
44
  def ring &block
41
45
  [last, *self, first].each_cons 3, &block
42
46
  end
@@ -73,7 +73,7 @@ module Refinements
73
73
  end
74
74
 
75
75
  def recurse &block
76
- return self unless block_given?
76
+ return self unless block
77
77
 
78
78
  transform = yield self
79
79
 
@@ -119,7 +119,7 @@ module Refinements
119
119
  end
120
120
 
121
121
  def use &block
122
- return [] unless block_given?
122
+ return [] unless block
123
123
 
124
124
  block.parameters
125
125
  .map { |(_type, key)| self[key] }
@@ -5,7 +5,7 @@ module Refinements
5
5
  module Identity
6
6
  NAME = "refinements"
7
7
  LABEL = "Refinements"
8
- VERSION = "7.14.0"
8
+ VERSION = "7.18.0"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}"
10
10
  end
11
11
  end
@@ -12,9 +12,27 @@ module Refinements
12
12
  end
13
13
  end
14
14
 
15
+ refine Pathname.singleton_class do
16
+ def home
17
+ new ENV["HOME"]
18
+ end
19
+
20
+ def make_temp_dir prefix: "temp-", suffix: nil, root: nil
21
+ Dir.mktmpdir([prefix, suffix], root) { |path| block_given? ? yield(new path) : new(path) }
22
+ end
23
+
24
+ def require_tree root, pattern = "**/*.rb"
25
+ new(root).files(pattern).each { |path| require path.to_s }
26
+ end
27
+
28
+ def root
29
+ new "/"
30
+ end
31
+ end
32
+
15
33
  refine Pathname do
16
34
  def change_dir &block
17
- block_given? ? Dir.chdir(self, &block) : (Dir.chdir self and self)
35
+ block ? Dir.chdir(self, &block) : (Dir.chdir self and self)
18
36
  end
19
37
 
20
38
  def copy to
@@ -82,13 +100,17 @@ module Refinements
82
100
 
83
101
  def rewrite
84
102
  read.then { |content| write yield(content) if block_given? }
85
- self
86
103
  end
87
104
 
88
105
  def touch at: Time.now
89
106
  exist? ? utime(at, at) : write("")
90
107
  self
91
108
  end
109
+
110
+ def write content, offset: nil, **options
111
+ super content, offset, **options
112
+ self
113
+ end
92
114
  end
93
115
  end
94
116
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Refinements
4
+ module Structs
5
+ refine Struct.singleton_class do
6
+ def keyworded?
7
+ inspect.include? "keyword_init: true"
8
+ end
9
+
10
+ def with_keywords arguments
11
+ keyworded? ? new(arguments) : new.merge!(arguments)
12
+ end
13
+
14
+ def with_positions *values
15
+ keyworded? ? new(Hash[members.zip values]) : new(*values)
16
+ end
17
+ end
18
+
19
+ refine Struct do
20
+ def merge **attributes
21
+ dup.merge! attributes
22
+ end
23
+
24
+ def merge! **attributes
25
+ to_h.merge(attributes).each { |key, value| self[key] = value }
26
+ self
27
+ end
28
+
29
+ def revalue attributes = each_pair
30
+ return self unless block_given?
31
+
32
+ dup.tap do |copy|
33
+ attributes.each { |key, value| copy[key] = yield self[key], value }
34
+ end
35
+ end
36
+
37
+ def revalue! attributes = each_pair
38
+ return self unless block_given?
39
+
40
+ attributes.each { |key, value| self[key] = yield self[key], value }
41
+ self
42
+ end
43
+ end
44
+ end
45
+ end
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: 7.14.0
4
+ version: 7.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -28,190 +28,8 @@ cert_chain:
28
28
  2XV8FRa7/JimI07sPLC13eLY3xd/aYTi85Z782KIA4j0G8XEEWAX0ouBhlXPocZv
29
29
  QWc=
30
30
  -----END CERTIFICATE-----
31
- date: 2020-11-14 00:00:00.000000000 Z
32
- dependencies:
33
- - !ruby/object:Gem::Dependency
34
- name: bundler-audit
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '0.7'
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '0.7'
47
- - !ruby/object:Gem::Dependency
48
- name: bundler-leak
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '0.2'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '0.2'
61
- - !ruby/object:Gem::Dependency
62
- name: guard-rspec
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '4.7'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '4.7'
75
- - !ruby/object:Gem::Dependency
76
- name: pry
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.13'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.13'
89
- - !ruby/object:Gem::Dependency
90
- name: pry-byebug
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '3.9'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '3.9'
103
- - !ruby/object:Gem::Dependency
104
- name: rake
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '13.0'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '13.0'
117
- - !ruby/object:Gem::Dependency
118
- name: reek
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '6.0'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '6.0'
131
- - !ruby/object:Gem::Dependency
132
- name: rspec
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '3.10'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '3.10'
145
- - !ruby/object:Gem::Dependency
146
- name: rubocop
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '1.3'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '1.3'
159
- - !ruby/object:Gem::Dependency
160
- name: rubocop-performance
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '1.8'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: '1.8'
173
- - !ruby/object:Gem::Dependency
174
- name: rubocop-rake
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - "~>"
178
- - !ruby/object:Gem::Version
179
- version: '0.5'
180
- type: :development
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - "~>"
185
- - !ruby/object:Gem::Version
186
- version: '0.5'
187
- - !ruby/object:Gem::Dependency
188
- name: rubocop-rspec
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '2.0'
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - "~>"
199
- - !ruby/object:Gem::Version
200
- version: '2.0'
201
- - !ruby/object:Gem::Dependency
202
- name: simplecov
203
- requirement: !ruby/object:Gem::Requirement
204
- requirements:
205
- - - "~>"
206
- - !ruby/object:Gem::Version
207
- version: '0.19'
208
- type: :development
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - "~>"
213
- - !ruby/object:Gem::Version
214
- version: '0.19'
31
+ date: 2020-12-21 00:00:00.000000000 Z
32
+ dependencies: []
215
33
  description:
216
34
  email:
217
35
  - brooke@alchemists.io
@@ -234,6 +52,7 @@ files:
234
52
  - lib/refinements/pathnames.rb
235
53
  - lib/refinements/string_ios.rb
236
54
  - lib/refinements/strings.rb
55
+ - lib/refinements/structs.rb
237
56
  homepage: https://www.alchemists.io/projects/refinements
238
57
  licenses:
239
58
  - Apache-2.0
@@ -257,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
257
76
  - !ruby/object:Gem::Version
258
77
  version: '0'
259
78
  requirements: []
260
- rubygems_version: 3.1.4
79
+ rubygems_version: 3.2.2
261
80
  signing_key:
262
81
  specification_version: 4
263
82
  summary: A collection of refinements to core Ruby objects.
metadata.gz.sig CHANGED
Binary file