README.adoc in refinements-7.14.0 vs README.adoc in refinements-7.15.0
- old
+ new
@@ -26,10 +26,11 @@
* Hash
* IO
* Pathname
* String
* StringIO
+* Structs
== Requirements
. https://www.ruby-lang.org[Ruby].
. A solid understanding of link:https://www.alchemists.io/articles/ruby_refinements[Ruby refinements
@@ -73,10 +74,11 @@
require "refinements/hashes"
require "refinements/ios"
require "refinements/pathnames"
require "refinements/strings"
require "refinements/string_ios"
+require "refinements/structs"
----
=== Using
Much like including/extending a module, you’ll need to modify your object(s) to use the
@@ -92,10 +94,11 @@
using Refinements::Hashes
using Refinements::IOs
using Refinements::Pathnames
using Refinements::Strings
using Refinements::StringIOs
+ using Refinements::Structs
end
----
=== Examples
@@ -479,15 +482,12 @@
stream. When given a block, the stream will automatically close upon block exit. When not given a
block, you'll need to close the stream manually.
[source,ruby]
----
-io = IO.void
-io.closed? # => false
-
-io = IO.void { |void| void.write "nevermore" }
-io.closed? # => true
+io = IO.void # => #<IO:fd 20>
+io = IO.void { |void| void.write "nevermore" } # => #<IO:(closed)>
----
===== #redirect
Redirects current stream to other stream when given a block. Without a block, the original stream is
@@ -496,15 +496,12 @@
[source,ruby]
----
io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+")
-io.redirect other # => `io`
-
-io.redirect(other) { |stream| stream.write "test" }
- .close # => ""
-other.close # => "test"
+io.redirect other # => #<IO:fd 20>
+io.redirect(other) { |stream| stream.write "test" } # => #<IO:fd 21>
----
===== #reread
Answers full stream by rewinding to beginning of stream and reading all content.
@@ -516,34 +513,35 @@
io.reread # => "This is a test."
io.reread 4 # => "This"
buffer = "".dup
-io.reread(buffer: buffer)
-buffer # => "This is a test."
+io.reread(buffer: buffer) # => "This is a test."
+buffer # => "This is a test."
----
===== #squelch
-Temporarily ignores any reads/writes for current stream for all code executed within the block. When
-not given a block, it answers itself.
+Temporarily ignores any reads/writes for code executed within a block. Answers itself without any
+arguments or when given a block.
[source,ruby]
----
io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+")
-io.squelch { io.write "Test" }
-io.reread # => ""
+io.squelch # => #<IO:fd 20>
+io.squelch { io.write "Test" } # => #<IO:fd 20>
+io.reread # => ""
----
==== Pathname
===== Pathname
-Enhances the conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in
-order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still
-invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that
-can still be used to construct a valid path.
+Enhances the `Kernel` conversion function which casts `nil` into a pathname in order to avoid:
+`TypeError (no implicit conversion of nil into String)`. The pathname remains invalid but at least
+you have an instance of `Pathname`, which behaves like a _Null Object_, that can be used to
+construct a valid path.
[source,ruby]
----
Pathname(nil) # => Pathname("")
----
@@ -557,27 +555,27 @@
----
Pathname.pwd # => "/"
Pathname("/test").make_dir.change_dir # => Pathname "/test"
Pathname.pwd # => "/test"
-Pathname.pwd # => "/"
-Pathname("/test").make_dir.change_dir { # Implementation details } # => Pathname "/test"
-Pathname.pwd # => "/"
+Pathname.pwd # => "/"
+Pathname("/test").make_dir.change_dir { "example" } # => "example"
+Pathname.pwd # => "/"
----
===== #copy
-Copies file from current location to new location.
+Copies file from current location to new location while answering itself so it can be chained.
[source,ruby]
----
-Pathname("input.txt").copy Pathname("output.txt")
+Pathname("input.txt").copy Pathname("output.txt") # => Pathname("input.txt")
----
===== #directories
-Answers all or filtered directories for current path.
+Answers all directories or filtered directories for current path.
[source,ruby]
----
Pathname("/example").directories # => [Pathname("a"), Pathname("b")]
Pathname("/example").directories "a*" # => [Pathname("a")]
@@ -593,11 +591,11 @@
Pathname("example.txt.erb").extensions # => [".txt", ".erb"]
----
===== #files
-Answers all or filtered files for current path.
+Answers all files or filtered files for current path.
[source,ruby]
----
Pathname("/example").files # => [Pathname("a.txt"), Pathname("a.png")]
Pathname("/example").files "*.png" # => [Pathname("a.png")]
@@ -621,13 +619,13 @@
Ensures all ancestor directories are created for a path.
[source,ruby]
----
-Pathname("/one/two").make_ancestors
-Pathname("/one").exist? # => true
-Pathname("/one/two").exist? # => false
+Pathname("/one/two").make_ancestors # => Pathname("/one/two")
+Pathname("/one").exist? # => true
+Pathname("/one/two").exist? # => false
----
===== #make_dir
Provides alternative `#mkdir` behavior by always answering itself (even when directory exists) and
@@ -706,23 +704,36 @@
When given a block, it provides the contents of the recently read file for manipulation and
immediate writing back to the same file.
[source,ruby]
----
-Pathname("/test.txt").rewrite { |content| content.sub "[placeholder]", "example" }
+Pathname("/test.txt").rewrite # => Pathname("/test.txt")
+Pathname("/test.txt").rewrite { |body| body.sub "[token]", "example" } # => Pathname("/test.txt")
----
===== #touch
Updates access and modification times for path. Defaults to current time.
[source,ruby]
----
-Pathname("example.txt").touch
-Pathname("example.txt").touch at: Time.now - 1
+Pathname("example.txt").touch # => Pathname("example.txt")
+Pathname("example.txt").touch at: Time.now - 1 # => Pathname("example.txt")
----
+===== #write
+
+Writes to file and answers itself so it can be chained. See `IO.write` for details on additional
+options.
+
+[source,ruby]
+----
+Pathname("example.txt").write "test" # => Pathname("example.txt")
+Pathname("example.txt").write "test", offset: 1 # => Pathname("example.txt")
+Pathname("example.txt").write "test", mode: "a" # => Pathname("example.txt")
+----
+
==== String
===== #blank?
Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`.
@@ -836,11 +847,55 @@
io.reread # => "This is a test."
io.reread 4 # => "This"
buffer = "".dup
-io.reread(buffer: buffer)
-buffer # => "This is a test."
+io.reread(buffer: buffer) # => "This is a test."
+buffer # => "This is a test."
+----
+
+==== Struct
+
+===== #merge
+
+Merges multiple attributes without mutating itself.
+
+[source,ruby]
+----
+Example = Struct.new :a, :b, :c
+example = Example[1, 2, 3]
+example.merge a: 10 # => #<struct a=10, b=2, c=3>
+example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
+example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
+example # => #<struct a=1, b=2, c=3>
+
+Example = Struct.new :a, :b, :c, keyword_init: true
+example = Example[a: 1, b: 2, c: 3]
+example.merge a: 10 # => #<struct a=10, b=2, c=3>
+example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30>
+example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
+example # => #<struct a=1, b=2, c=3>
+----
+
+===== #merge!
+
+Merges multiple attributes while mutating itself.
+
+[source,ruby]
+----
+Example = Struct.new :a, :b, :c
+example = Example[1, 2, 3]
+example.merge! a: 10 # => #<struct a=10, b=2, c=3>
+example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
+example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
+example # => #<struct a=10, b=20, c=30>
+
+Example = Struct.new :a, :b, :c, keyword_init: true
+example = Example[a: 1, b: 2, c: 3]
+example.merge! a: 10 # => #<struct a=10, b=2, c=3>
+example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30>
+example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30>
+example # => #<struct a=10, b=20, c=30>
----
== Development
To contribute, run: