facets 3.2.2 → 4.0.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 +4 -4
- data/CONTRIBUTING.md +44 -15
- data/HISTORY.md +99 -0
- data/LICENSE.txt +1 -1
- data/README.md +50 -219
- data/lib/core/facets/array/nonuniq.rb +2 -2
- data/lib/core/facets/array/standard_deviation.rb +1 -1
- data/lib/core/facets/array/uniq_by.rb +5 -1
- data/lib/core/facets/array.rb +5 -1
- data/lib/core/facets/binding/self.rb +2 -1
- data/lib/core/facets/comparable/clip.rb +2 -1
- data/lib/core/facets/dir/recurse.rb +17 -4
- data/lib/core/facets/enumerable/compact_map.rb +1 -1
- data/lib/core/facets/enumerable/defer.rb +1 -1
- data/lib/core/facets/enumerable/frequency.rb +1 -1
- data/lib/core/facets/enumerable/hashify.rb +2 -2
- data/lib/core/facets/enumerable/hinge.rb +1 -1
- data/lib/core/facets/enumerable/map_with_index.rb +1 -1
- data/lib/core/facets/enumerable/mash.rb +2 -1
- data/lib/core/facets/enumerable/uniq_by.rb +3 -1
- data/lib/core/facets/essentials.rb +4 -1
- data/lib/core/facets/exception/error_print.rb +4 -2
- data/lib/core/facets/file/null.rb +2 -1
- data/lib/core/facets/file/read_binary.rb +2 -1
- data/lib/core/facets/file.rb +1 -1
- data/lib/core/facets/hash/fetch_nested.rb +2 -1
- data/lib/core/facets/hash/update_keys.rb +2 -1
- data/lib/core/facets/hash/update_values.rb +2 -1
- data/lib/core/facets/hash.rb +6 -4
- data/lib/core/facets/kernel/eigenclass.rb +2 -1
- data/lib/core/facets/kernel/extension.rb +2 -1
- data/lib/core/facets/kernel/instance_class.rb +2 -1
- data/lib/core/facets/kernel/instance_send.rb +2 -1
- data/lib/core/facets/kernel/like.rb +7 -2
- data/lib/core/facets/kernel/load_relative.rb +2 -1
- data/lib/core/facets/kernel/memo.rb +2 -1
- data/lib/core/facets/kernel/meta.rb +1 -1
- data/lib/core/facets/kernel/object_class.rb +2 -1
- data/lib/core/facets/kernel/object_send.rb +2 -1
- data/lib/core/facets/kernel/qua_class.rb +2 -1
- data/lib/core/facets/kernel/returning.rb +3 -1
- data/lib/core/facets/kernel/silence.rb +38 -30
- data/lib/core/facets/kernel/tee.rb +3 -0
- data/lib/core/facets/kernel/try.rb +25 -14
- data/lib/core/facets/kernel/with.rb +15 -9
- data/lib/core/facets/kernel.rb +1 -1
- data/lib/core/facets/module/alias_method_chain.rb +3 -1
- data/lib/core/facets/module/alias_module_function.rb +4 -1
- data/lib/core/facets/module/can.rb +2 -1
- data/lib/core/facets/objectspace/op_fetch.rb +2 -1
- data/lib/core/facets/proc/compose.rb +4 -2
- data/lib/core/facets/rails_bridge.rb +27 -0
- data/lib/core/facets/string/camelcase.rb +6 -0
- data/lib/core/facets/string/similarity.rb +3 -2
- data/lib/core/facets/struct/attributes.rb +1 -1
- data/lib/core/facets/time/to_time.rb +7 -2
- data/lib/core/facets/time/trunc.rb +2 -1
- data/lib/core/facets/unboundmethod/arguments.rb +1 -1
- data/lib/core/facets/version.rb +1 -1
- data/lib/rails/facets/hash/to_options.rb +14 -0
- data/lib/{core → rails}/facets/module/mattr.rb +30 -30
- data/lib/standard/facets/cloneable.rb +2 -1
- data/lib/standard/facets/continuation.rb +2 -1
- data/lib/standard/facets/enumargs.rb +14 -2
- data/lib/standard/facets/getoptlong.rb +2 -1
- data/lib/standard/facets/interval.rb +4 -3
- data/lib/standard/facets/load_monitor.rb +2 -1
- data/lib/standard/facets/pathname/null.rb +2 -1
- data/lib/standard/facets/random.rb +8 -4
- metadata +14 -12
- data/lib/core/facets/hash/to_options.rb +0 -1
- /data/lib/{core → rails}/facets/array/extract_options.rb +0 -0
- /data/lib/{core → rails}/facets/cattr.rb +0 -0
- /data/lib/{core → rails}/facets/class/cattr.rb +0 -0
- /data/lib/{standard → rails}/facets/date.rb +0 -0
- /data/lib/{core → rails}/facets/file/atomic_write.rb +0 -0
- /data/lib/{core → rails}/facets/hash/slice.rb +0 -0
- /data/lib/{core → rails}/facets/hash/stringify_keys.rb +0 -0
- /data/lib/{core → rails}/facets/hash/symbolize_keys.rb +0 -0
- /data/lib/{core → rails}/facets/module/cattr.rb +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af1581fdee797dd22551c3257c73b76e2d0e5ee659ecb60690eee877672a5a00
|
|
4
|
+
data.tar.gz: 8693eedfa8dc78cfa8c47964cac6f2834996337dc00bbf0e9672c2b664bc2cea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e4a41b846c6bf81d6103ec0fcac3f8b729f5ab324676ab7f2b25a4126bfe878ec36a7113d58b4a7c32c5d1748cd4a1a9ae4ebba80fa82e7226c83bc7d7220af1
|
|
7
|
+
data.tar.gz: 5c32bd85bdeb4336d5774689023e73d5c7e74ee86eff5003e5ef4da1644f10c6de5c897b6a0f268f09c7976055b28acaba10cf420b546380ae21c4d73508da86
|
data/CONTRIBUTING.md
CHANGED
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
The Lemon unit tests are for testing a method in detail whereas the QED
|
|
19
19
|
demos are for demonstrating usage.
|
|
20
20
|
|
|
21
|
-
* Facets
|
|
22
|
-
Almost all
|
|
23
|
-
|
|
24
|
-
per-script.
|
|
21
|
+
* Facets groups libraries into `core`, `standard`, and `rails` areas.
|
|
22
|
+
Almost all core extensions can be loaded at once with `require 'facets'`.
|
|
23
|
+
Standard and rails extensions should be required by file.
|
|
25
24
|
|
|
26
|
-
* Some core methods are
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
* Some core methods are *uncommon* and are not loaded by `require 'facets'`.
|
|
26
|
+
Mark them with an `@uncommon` tag in the method comments, showing the
|
|
27
|
+
require line, and comment out their line in the aggregator file with
|
|
28
|
+
`# uncommon`.
|
|
29
29
|
|
|
30
30
|
* Standard libraries that are not extensions of existing standard libraries
|
|
31
31
|
do not have to be divvied up into individual method files. But note that
|
|
@@ -102,11 +102,40 @@ explanation if needed, including *when* and *why* the method could be useful.
|
|
|
102
102
|
|
|
103
103
|
## Testing
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*
|
|
108
|
-
|
|
109
|
-
*
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
The test suite uses four tools:
|
|
106
|
+
|
|
107
|
+
* **RubyTest** provides the test runner interface; `rubytest-cli` supplies the
|
|
108
|
+
`ruby-test` command used by the Rake tasks.
|
|
109
|
+
* **Lemon** defines the `test_case`, `method`, and `test` structure of the unit
|
|
110
|
+
tests.
|
|
111
|
+
* **AE** provides assertions such as `.assert` and `expect`, used in both the
|
|
112
|
+
unit tests and the QED demos. It is installed as a Lemon dependency.
|
|
113
|
+
* **QED** runs the executable examples in `demo/`. They show how a method is
|
|
114
|
+
intended to be used as well as checking its behavior.
|
|
115
|
+
|
|
116
|
+
Install the development dependencies and run the same two suites as CI:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
bundle install
|
|
120
|
+
bundle exec rake test
|
|
121
|
+
bundle exec rake qed
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
For a focused unit test, set `TESTS` to a test file, for example:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
TESTS=test/core/array/test_average.rb bundle exec rake test
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The Rakefile also provides `test:core`, `test:standard`, `test:rails` and the
|
|
131
|
+
corresponding `qed:*` tasks for each library area.
|
|
132
|
+
|
|
133
|
+
* A core method in `lib/core/facets/{class}/{method}.rb` normally has a Lemon
|
|
134
|
+
test in `test/core/{class}/test_{method}.rb` and a QED demo in
|
|
135
|
+
`demo/core/{class}/{method}.md`. Standard and rails libraries use
|
|
136
|
+
their respective `test/` and `demo/` directories.
|
|
137
|
+
* A file that only requires another file does not need its own unit test. A file
|
|
138
|
+
that also defines an alias can test the alias without repeating every test
|
|
139
|
+
for the underlying method.
|
|
140
|
+
* Demos should show the behavior of each method. An alias can have a short demo
|
|
141
|
+
that points readers to the main method's demo.
|
data/HISTORY.md
CHANGED
|
@@ -1,5 +1,100 @@
|
|
|
1
1
|
# Facets Release History
|
|
2
2
|
|
|
3
|
+
## 4.0.0 / 2026-09-27
|
|
4
|
+
|
|
5
|
+
A major release, because it changes behavior: `Kernel#try!` is now the
|
|
6
|
+
lenient variant and `#try` is strict, `require 'facets'` no longer loads
|
|
7
|
+
`Kernel#with`, and Rails-compatible methods move to the new `lib/rails`
|
|
8
|
+
area (still loaded by `require 'facets'` with a warning until 2027-09-30).
|
|
9
|
+
Every deprecation now names that same removal date.
|
|
10
|
+
|
|
11
|
+
Changes:
|
|
12
|
+
|
|
13
|
+
* Breaking
|
|
14
|
+
|
|
15
|
+
* `Kernel#try!` now returns `nil` when the receiver doesn't respond to the
|
|
16
|
+
method (or it is private), instead of raising `NoMethodError`. `#try`
|
|
17
|
+
stays strict. This is deliberately the opposite of ActiveSupport, which
|
|
18
|
+
since Rails 4.0 makes `#try` lenient and `#try!` strict. In Ruby the bang
|
|
19
|
+
marks the more dangerous method, and quietly ignoring a missing method is
|
|
20
|
+
the dangerous behavior. The docs no longer claim ActiveSupport
|
|
21
|
+
compatibility.
|
|
22
|
+
* `require 'facets'` no longer loads `Kernel#with`, since a global `with`
|
|
23
|
+
breaks other libraries' methods of that name, such as RSpec's
|
|
24
|
+
`receive(...).with` (#290). It is still available, deprecated, with
|
|
25
|
+
`require 'facets/kernel/with'`.
|
|
26
|
+
* `Kernel#try` no longer calls private methods. It now behaves exactly like
|
|
27
|
+
a normal call or `&.`, raising `NoMethodError` for them.
|
|
28
|
+
|
|
29
|
+
* Enhancements
|
|
30
|
+
|
|
31
|
+
* New `lib/rails` library for Rails-compatible methods that Facets carries
|
|
32
|
+
but doesn't endorse as its own: `Hash#symbolize_keys`/`#stringify_keys`,
|
|
33
|
+
`Hash#to_options`, `Hash#slice!`, `Array#extract_options!`,
|
|
34
|
+
`Module#mattr_*`/`#cattr_*`, `File.atomic_write` and the `facets/date`
|
|
35
|
+
extensions. Require paths are unchanged (`require 'facets/hash/slice'`
|
|
36
|
+
still works), and `require 'facets'` still provides the same methods.
|
|
37
|
+
|
|
38
|
+
* Deprecations
|
|
39
|
+
|
|
40
|
+
* `require 'facets'` will stop providing the lib/rails methods after
|
|
41
|
+
2027-09-30. Until then, the first call to one of them through
|
|
42
|
+
`require 'facets'` warns and names the file to require. Requiring that
|
|
43
|
+
file directly avoids the warning.
|
|
44
|
+
* `Kernel#returning`, `Module#alias_method_chain`, `Array#uniq_by!`,
|
|
45
|
+
`Enumerable#uniq_by`, `Kernel#silence_stream` and Facets' fallback
|
|
46
|
+
`Time#to_time` are scheduled for removal after 2027-09-30. Each warns
|
|
47
|
+
with its replacement and the removal date.
|
|
48
|
+
* Every existing deprecation now names a removal date, 2027-09-30, in its
|
|
49
|
+
`@deprecated` note and its warning. `String#upper_camelcase`/
|
|
50
|
+
`#lower_camelcase`, `Kernel#equate?`, `facets/kernel/tee` and
|
|
51
|
+
`Interval#each(n, d)` were deprecated in docs only (or "will be") and
|
|
52
|
+
now warn as well.
|
|
53
|
+
* `Kernel#with` is deprecated in favor of `instance_eval`, also for removal
|
|
54
|
+
after 2027-09-30. Rails 7.1's unrelated `Object#with` (which temporarily
|
|
55
|
+
sets attributes) was silently replaced by it when both were loaded.
|
|
56
|
+
* `Kernel#silence` now does the stream silencing itself; `silently`,
|
|
57
|
+
`silence_stderr` and `silence_stdout` use it and do not warn.
|
|
58
|
+
|
|
59
|
+
* Bug Fixes
|
|
60
|
+
|
|
61
|
+
* `Hash#to_options` and `#to_options!` now exist. `facets/hash/to_options`
|
|
62
|
+
only loaded `symbolize_keys` and never defined the aliases.
|
|
63
|
+
* `Module#alias_module_function` now aliases the singleton method directly.
|
|
64
|
+
On JRuby, the singleton method `module_function` created turned private
|
|
65
|
+
when aliased again, which broke `URI.hash_to_query` under the test suite.
|
|
66
|
+
* `Dir.recurse` and `Dir.ls_r` once again return an Array that leaves out
|
|
67
|
+
the starting directory. Deprecating them in favor of `Dir.find` had
|
|
68
|
+
quietly changed both.
|
|
69
|
+
* `Enumerable::Argumentable#min` and `#max` now pass their arguments to
|
|
70
|
+
`#each`, as documented, rather than to Ruby's own `min(n)`/`max(n)`.
|
|
71
|
+
* `String#similarity` now divides the shared length by the longer string's
|
|
72
|
+
length, not length + 1, so 9 of 10 matching characters score 0.9 as its
|
|
73
|
+
docs said (it gave 0.818). Scores for non-identical strings rise slightly.
|
|
74
|
+
* `require 'facets'` no longer crashes on Ruby 4.1, which removed
|
|
75
|
+
`ObjectSpace._id2ref`. `ObjectSpace[]` is only defined where `_id2ref`
|
|
76
|
+
exists.
|
|
77
|
+
* `Kernel#silence` now supports `:verbose`/`:warnings` and `:debug`, as its
|
|
78
|
+
docs always said, instead of raising `NoMethodError`. They set `$VERBOSE`
|
|
79
|
+
to nil and `$DEBUG` to false within the block.
|
|
80
|
+
|
|
81
|
+
* Internal
|
|
82
|
+
|
|
83
|
+
* Run the qed demos in CI.
|
|
84
|
+
* Remove leftover build files that nothing reads anymore: `MANIFEST`,
|
|
85
|
+
`Assembly` (Detroit), `.index`, `Indexfile` and `lib/core/facets.yml`.
|
|
86
|
+
The Rakefile takes its version from `Facets::VERSION` (`.index` still said
|
|
87
|
+
3.1.1), and `rake package` no longer needs the `mast` and `index` tools.
|
|
88
|
+
* The gemspec reads its version from `Facets::VERSION`, so the version now
|
|
89
|
+
lives in one place, `lib/core/facets/version.rb`.
|
|
90
|
+
* Fix the qed demos, which had 8 failures and 2 errors. Most were stale
|
|
91
|
+
expectations (`Array#from`, `#step`, `#arrange`, `String#similarity`)
|
|
92
|
+
and the date demo held pasted irb output.
|
|
93
|
+
* CONTRIBUTING.md explains the test stack (RubyTest, Lemon, AE and QED)
|
|
94
|
+
and the `@uncommon` convention.
|
|
95
|
+
* The `String#trim` demo no longer drops random cases, so the QED
|
|
96
|
+
assertion count is the same on every run.
|
|
97
|
+
|
|
3
98
|
## 3.2.2 / 2026-06-15
|
|
4
99
|
|
|
5
100
|
Patch release with cross-version fixes surfaced by CI on Ruby 3.1–3.4.
|
|
@@ -64,6 +159,10 @@ Changes:
|
|
|
64
159
|
Modernization release targeting Ruby 3.1+. Cleans up long-standing
|
|
65
160
|
compatibility issues and incorporates community contributions.
|
|
66
161
|
|
|
162
|
+
**Note:** This release removed methods and raised the minimum Ruby version
|
|
163
|
+
to 3.1, so it should have been released as 4.0.0. Treat the 3.2 series as a
|
|
164
|
+
major upgrade from 3.1, and review the Removals below before upgrading.
|
|
165
|
+
|
|
67
166
|
Changes:
|
|
68
167
|
|
|
69
168
|
* New Features
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,253 +1,84 @@
|
|
|
1
|
-
# Ruby Facets
|
|
1
|
+
# Ruby Facets <img src="docs/assets/images/cherries.svg" alt="cherries" width="34" height="34">
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/facets)
|
|
4
4
|
[](https://github.com/rubyworks/facets/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
+
**More of Ruby, one method at a time.** Facets is a collection of extensions to Ruby's core classes and standard library, plus a few small, reusable classes and modules. Most methods live in their own files, so you can load one extension, a class's extensions, or the core collection.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Facets took its name in 2004, growing out of a small methods library started in 2002, and is still maintained. The current release is **3.2.2**, which requires **Ruby 3.1 or newer**. See the [release history](HISTORY.md) for changes and migration notes from earlier versions. The `main` branch also contains changes awaiting the next release.
|
|
8
9
|
|
|
10
|
+
## Install
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
```sh
|
|
13
|
+
gem install facets
|
|
14
|
+
```
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
extensions and standard additions for the Ruby programming language.
|
|
16
|
+
With Bundler, add this to your Gemfile:
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
The methods are stored in individual files so that each can be required
|
|
19
|
-
independently. This gives developers the potential for much finer control over
|
|
20
|
-
which extra methods to bring into their code.
|
|
18
|
+
```ruby
|
|
19
|
+
gem 'facets', require: false
|
|
20
|
+
```
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
plus a small collection of add-on classes and modules. Together these
|
|
24
|
-
libraries constitute an reliable source of reusable components, suitable
|
|
25
|
-
to a wide variety of usecases.
|
|
22
|
+
`require: false` lets you choose which extensions to load. Omit it if you want Bundler to load the core collection automatically.
|
|
26
23
|
|
|
24
|
+
## Choose how much to load
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
### One method
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* Wiki Pages: https://github.com/rubyworks/facets/wiki
|
|
33
|
-
* Source Code: https://github.com/rubyworks/facets
|
|
28
|
+
```ruby
|
|
29
|
+
require 'facets/array/to_ranges'
|
|
34
30
|
|
|
31
|
+
[1, 2, 3, 6, 7].to_ranges
|
|
32
|
+
#=> [1..3, 6..7]
|
|
33
|
+
```
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Facets has special documentation needs due to its extensive breadth.
|
|
39
|
-
The documentation generated when installing via RubyGems, or the YARD
|
|
40
|
-
docs provided by rubydoc.info can be somewhat unwieldy because it
|
|
41
|
-
combines all of Facets in one large set. When using these resources,
|
|
42
|
-
it is important to remain aware of the source location of particular
|
|
43
|
-
methods.
|
|
44
|
-
|
|
45
|
-
For better organized online documentation, generated to separate core
|
|
46
|
-
extensions from standard libraries, see the [Learn Facets](https://rubyworks.github.io/facets/learn.html) page on the website for links to available documentation.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
## Installation
|
|
50
|
-
|
|
51
|
-
### Bundler
|
|
52
|
-
|
|
53
|
-
If you are using Bundler with your project, add the facets gem to the project's
|
|
54
|
-
Gemfile. Unless you want all of facets loaded be sure to add the `:require => false`
|
|
55
|
-
option.
|
|
56
|
-
|
|
57
|
-
gem "facets", require: false
|
|
58
|
-
|
|
59
|
-
### RubyGems
|
|
60
|
-
|
|
61
|
-
The easiest way to install is via RubyGems.
|
|
62
|
-
|
|
63
|
-
$ gem install facets
|
|
64
|
-
|
|
65
|
-
### Requirements
|
|
66
|
-
|
|
67
|
-
Facets 3.2+ requires Ruby 3.1 or higher.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## Mission
|
|
71
|
-
|
|
72
|
-
Facets holds to the notion that the more we can *reasonably* integrate into
|
|
73
|
-
a common foundation, directed toward general needs, the better that foundation
|
|
74
|
-
will be able to serve the community. There are a number of advantages here:
|
|
75
|
-
|
|
76
|
-
* Better Code-reuse
|
|
77
|
-
* Collaborative Improvements
|
|
78
|
-
* Greater Name Consistency
|
|
79
|
-
* One-stop Shop and Installation
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
## Usage
|
|
83
|
-
|
|
84
|
-
### CORE Library
|
|
85
|
-
|
|
86
|
-
At the heart of Ruby Facets is the CORE extensions library. CORE provides
|
|
87
|
-
a sizable collection of generally useful methods, along with a few supporting
|
|
88
|
-
classes, that extend the functionality of Ruby's core classes and modules.
|
|
89
|
-
|
|
90
|
-
With the exception of a few *uncommon* extensions, CORE contains anything that
|
|
91
|
-
will load automatically when issuing:
|
|
92
|
-
|
|
93
|
-
require 'facets'
|
|
94
|
-
|
|
95
|
-
This loads all the CORE functionality at once. If you plan to use more then a
|
|
96
|
-
handful of Facets core methods it is recommended that you require the library in
|
|
97
|
-
this way. However, you can also "cherry pick" the CORE library as you prefer.
|
|
98
|
-
And for uncommon extensions this must be done. The general require statement for
|
|
99
|
-
a core extension library is:
|
|
100
|
-
|
|
101
|
-
require 'facets/<class|module>/<method>'
|
|
102
|
-
|
|
103
|
-
For example:
|
|
104
|
-
|
|
105
|
-
require 'facets/time/stamp'
|
|
106
|
-
|
|
107
|
-
Most "atoms" contain only one method, but exceptions occur when methods
|
|
108
|
-
are closely tied together.
|
|
35
|
+
### One class's core extensions
|
|
109
36
|
|
|
110
|
-
|
|
111
|
-
|
|
37
|
+
```ruby
|
|
38
|
+
require 'facets/string'
|
|
112
39
|
|
|
113
|
-
|
|
40
|
+
'Ruby Facets'.snakecase
|
|
41
|
+
#=> "ruby_facets"
|
|
42
|
+
```
|
|
114
43
|
|
|
115
|
-
|
|
44
|
+
### The core collection
|
|
116
45
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
they had more specialized use cases, where as CORE extensions are intended as
|
|
120
|
-
general purpose.
|
|
46
|
+
```ruby
|
|
47
|
+
require 'facets'
|
|
121
48
|
|
|
122
|
-
|
|
49
|
+
[1, 2, 3].average
|
|
50
|
+
#=> 2.0
|
|
51
|
+
```
|
|
123
52
|
|
|
124
|
-
|
|
125
|
-
`Proc#*` is `proc/op_mul`.
|
|
53
|
+
`require 'facets'` loads the broadly useful **core** extensions: roughly 860 methods from 448 files, adding about 35 ms of load time and 2 MB of memory (Ruby 3.3, Linux). Some specialized core extensions are opt-in; require their method file directly. To load Facets extensions to a Ruby standard library, require that library through Facets:
|
|
126
54
|
|
|
127
|
-
|
|
55
|
+
```ruby
|
|
56
|
+
require 'facets/ostruct'
|
|
57
|
+
```
|
|
128
58
|
|
|
129
|
-
|
|
130
|
-
-@ => op_minus
|
|
131
|
-
+ => op_add
|
|
132
|
-
- => op_sub
|
|
133
|
-
** => op_pow
|
|
134
|
-
* => op_mul
|
|
135
|
-
/ => op_div
|
|
136
|
-
% => op_mod
|
|
137
|
-
~ => op_tilde
|
|
138
|
-
<=> => op_cmp
|
|
139
|
-
<< => op_lshift
|
|
140
|
-
>> => op_rshift
|
|
141
|
-
< => op_lt
|
|
142
|
-
> => op_gt
|
|
143
|
-
=== => op_case
|
|
144
|
-
== => op_equal
|
|
145
|
-
=~ => op_apply
|
|
146
|
-
<= => op_lt_eq
|
|
147
|
-
>= => op_gt_eq
|
|
148
|
-
| => op_or
|
|
149
|
-
& => op_and
|
|
150
|
-
^ => op_xor
|
|
151
|
-
[]= => op_store
|
|
152
|
-
[] => op_fetch
|
|
59
|
+
This loads `ostruct` and Facets' OpenStruct extensions. On Ruby 3.5+, declare the `ostruct` gem separately because it is no longer a default gem.
|
|
153
60
|
|
|
154
|
-
|
|
155
|
-
file systems. Also, if a method ends in '=', '?' or '!' it is simply removed.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
### MORE Library (aka Standard Library)
|
|
159
|
-
|
|
160
|
-
On top of the extensive CORE library, Facets provides extensions for Ruby's
|
|
161
|
-
standard library, as well as a small collection of additional modules and
|
|
162
|
-
classes to supplement it.
|
|
163
|
-
|
|
164
|
-
Use this library like you would any other 3rd party library.
|
|
165
|
-
The only difference between Facet's Standard library and other libraries
|
|
166
|
-
is the lack of any enclosing `Facets::` namespace.
|
|
167
|
-
|
|
168
|
-
When using Facets extended versions of Ruby's standard libraries,
|
|
169
|
-
the libraries have to loaded individually. However you do not need
|
|
170
|
-
to load Ruby's library first, as the Facets' library will do that
|
|
171
|
-
automatically.
|
|
172
|
-
|
|
173
|
-
For example, normally one load Ruby's OpenStruct class via:
|
|
174
|
-
|
|
175
|
-
require 'ostruct'
|
|
176
|
-
|
|
177
|
-
To load 'ostruct.rb' plus Facets extensions for it simply use:
|
|
178
|
-
|
|
179
|
-
require 'facets/ostruct'
|
|
61
|
+
## Documentation
|
|
180
62
|
|
|
181
|
-
|
|
182
|
-
|
|
63
|
+
- [Getting started and loading guide](https://rubyworks.github.io/facets/learn.html)
|
|
64
|
+
- [Generated API documentation on RubyDoc.info](https://www.rubydoc.info/gems/facets) (check the displayed version)
|
|
65
|
+
- [Release history](HISTORY.md)
|
|
183
66
|
|
|
67
|
+
The split between `lib/core`, `lib/standard` and `lib/rails` is visible in API source paths. This helps you tell whether a method is loaded by `require 'facets'` or needs an explicit require. The `lib/rails` area, new in 4.0.0, holds Rails-compatible helpers; see the release history for details.
|
|
184
68
|
|
|
185
69
|
## Contribute
|
|
186
70
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
If you have any extension methods, classes or modules that you think have
|
|
190
|
-
very general applicability and would like to see them included in
|
|
191
|
-
this project, don't hesitate to submit. Also, if you have better versions
|
|
192
|
-
of any thing already included or simply have a patch, they are more than
|
|
193
|
-
welcome. We want Ruby Facets to be of the highest quality.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
## Development
|
|
197
|
-
|
|
198
|
-
Facets uses the [Lemon](https://rubyworks.github.io/lemon) testing framework
|
|
199
|
-
to handle unit testing, while [QED](https://rubyworks.github.io/qed) specifications
|
|
200
|
-
provide tested documentation. Run the test suite with [Rake](https://ruby.github.io/rake/):
|
|
201
|
-
|
|
202
|
-
$ rake test
|
|
203
|
-
|
|
204
|
-
Continuous integration runs on GitHub Actions (see `.github/workflows/ci.yml`).
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
## Authors
|
|
208
|
-
|
|
209
|
-
Much of this collection was written and/or inspired by a variety of great Ruby
|
|
210
|
-
developers. Fortunately nearly all utilized works were copyrighted under the same
|
|
211
|
-
open licenses, the Ruby License or the more liberal BSD and MIT licenses. In the
|
|
212
|
-
one or two exceptions the copyright notice has been included with the source code.
|
|
213
|
-
We have since received permission from the various authors to normalize the licensing
|
|
214
|
-
to a single license. For this purpose we have chosen the BSD 2 Clause License.
|
|
215
|
-
This is the license Ruby itself now uses, so it seemed the most appropriate choice.
|
|
216
|
-
It is also almost identical to the MIT license. Any code file not specifically labeled
|
|
217
|
-
otherwise shall fall under the this license (which is BSD 2-clause).
|
|
218
|
-
|
|
219
|
-
In all cases, every effort has been made to give credit where credit is due.
|
|
220
|
-
You will find these acknowledgments embedded in the source code. You can see
|
|
221
|
-
them in "CREDIT:" and/or "@author" lines.
|
|
222
|
-
Also see the [Contributors page](https://github.com/rubyworks/facets/wiki/Contributors)
|
|
223
|
-
on the Wiki for a list of all contributing Rubyists. If anyone is missing from
|
|
224
|
-
the list, please let us know so we can correct. Thanks.
|
|
225
|
-
|
|
226
|
-
This collection was put together by, and much of it written by [trans](https://github.com/trans).
|
|
227
|
-
If need be, he can be reached via email at transfire at gmail.com.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
## License
|
|
231
|
-
|
|
232
|
-
The collection PER COLLECTION is licensed as follows:
|
|
233
|
-
|
|
234
|
-
Ruby Facets
|
|
235
|
-
Copyright (c) 2005 Rubyworks
|
|
236
|
-
|
|
237
|
-
Distributed under the terms of the BSD-2 License (same as Ruby license).
|
|
238
|
-
|
|
239
|
-
The BSD 2 Clause License is a simple open source license. The complete text of the
|
|
240
|
-
license accompany this document (see the enclosed LICENSE file).
|
|
241
|
-
|
|
242
|
-
Acknowledgments and Copyrights for particular snippets of borrowed code
|
|
243
|
-
are given in their respective source. At this point, all licensing has been normalized
|
|
244
|
-
for all included code. Original authors have given permission for inclusion of their
|
|
245
|
-
code under such license, with appropriate credit citations.
|
|
71
|
+
Issues and pull requests are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md) for the library's method organization, demos, and test conventions. The test suite runs with:
|
|
246
72
|
|
|
73
|
+
```sh
|
|
74
|
+
bundle install
|
|
75
|
+
bundle exec rake test
|
|
76
|
+
```
|
|
247
77
|
|
|
248
|
-
|
|
78
|
+
[Source](https://github.com/rubyworks/facets) · [Issues](https://github.com/rubyworks/facets/issues) · [Website](https://rubyworks.github.io/facets/)
|
|
249
79
|
|
|
250
|
-
|
|
80
|
+
## License and credits
|
|
251
81
|
|
|
252
|
-
|
|
82
|
+
Facets is distributed under the [BSD 2-Clause License](LICENSE.txt). Thomas Sawyer started the project, and many Rubyists have contributed code, ideas, tests, and documentation. Individual files record additional credits where applicable.
|
|
253
83
|
|
|
84
|
+
*All your base are belong to Ruby.*
|
|
@@ -11,14 +11,14 @@ class Array
|
|
|
11
11
|
# CREDIT: Martin DeMello
|
|
12
12
|
|
|
13
13
|
def nonuniq
|
|
14
|
-
warn "Array#nonuniq is deprecated. Use Array#duplicates instead.", uplevel: 1
|
|
14
|
+
warn "Array#nonuniq is deprecated. Use Array#duplicates instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
15
15
|
duplicates
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Same as `#nonuniq` but acts in place.
|
|
19
19
|
|
|
20
20
|
def nonuniq!
|
|
21
|
-
warn "Array#nonuniq! is deprecated. Use Array#duplicates instead.", uplevel: 1
|
|
21
|
+
warn "Array#nonuniq! is deprecated. Use Array#duplicates instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
22
22
|
self.replace(duplicates)
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -20,7 +20,7 @@ class Array
|
|
|
20
20
|
alias sd stddev
|
|
21
21
|
|
|
22
22
|
def standard_deviation
|
|
23
|
-
warn "Array#standard_deviation is deprecated. Use Array#stddev or Array#sd instead.", uplevel: 1
|
|
23
|
+
warn "Array#standard_deviation is deprecated. Use Array#stddev or Array#sd instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
24
24
|
stddev
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -15,8 +15,12 @@ class Array
|
|
|
15
15
|
#
|
|
16
16
|
# Returns [Array] of unique elements.
|
|
17
17
|
#
|
|
18
|
+
# @deprecated Use Array#uniq! with a block instead (Ruby 1.9.2+).
|
|
19
|
+
# Scheduled for removal after 2027-09-30.
|
|
20
|
+
#
|
|
18
21
|
def uniq_by!(&block) #:yield:
|
|
19
|
-
warn "Array#uniq_by! is deprecated. Use Array#uniq!(&block) instead."
|
|
22
|
+
warn "Array#uniq_by! is deprecated. Use Array#uniq!(&block) instead. " \
|
|
23
|
+
"It will be removed after 2027-09-30.", uplevel: 1
|
|
20
24
|
uniq!(&block)
|
|
21
25
|
end
|
|
22
26
|
|
data/lib/core/facets/array.rb
CHANGED
|
@@ -15,7 +15,6 @@ require_relative 'array/duplicates.rb'
|
|
|
15
15
|
require_relative 'array/each_pair.rb'
|
|
16
16
|
require_relative 'array/each_value.rb'
|
|
17
17
|
require_relative 'array/entropy.rb'
|
|
18
|
-
require_relative 'array/extract_options.rb'
|
|
19
18
|
require_relative 'array/from.rb'
|
|
20
19
|
require_relative 'array/indexable.rb'
|
|
21
20
|
#require_relative 'array/intersection.rb' # too new
|
|
@@ -47,3 +46,8 @@ require_relative 'array/thru.rb'
|
|
|
47
46
|
require_relative 'array/traverse.rb'
|
|
48
47
|
require_relative 'array/uniq_by.rb'
|
|
49
48
|
|
|
49
|
+
|
|
50
|
+
# Rails-compatible methods from lib/rails; see facets/rails_bridge.
|
|
51
|
+
require_relative 'rails_bridge.rb'
|
|
52
|
+
Facets.rails_bridge(Array, 'facets/array/extract_options', :extract_options!)
|
|
53
|
+
Facets.rails_bridge(Hash, 'facets/array/extract_options', :extractable_options?)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
class Binding
|
|
2
2
|
|
|
3
3
|
# @deprecated Use Binding#receiver instead (built-in since Ruby 2.6).
|
|
4
|
+
# Scheduled for removal after 2027-09-30.
|
|
4
5
|
def self
|
|
5
|
-
warn "Binding#self is deprecated. Use Binding#receiver instead.", uplevel: 1
|
|
6
|
+
warn "Binding#self is deprecated. Use Binding#receiver instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
6
7
|
receiver
|
|
7
8
|
end
|
|
8
9
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
module Comparable
|
|
2
2
|
|
|
3
3
|
# @deprecated Use Comparable#clamp instead (built-in since Ruby 2.4).
|
|
4
|
+
# Scheduled for removal after 2027-09-30.
|
|
4
5
|
def clip(lower, upper=nil)
|
|
5
|
-
warn "Comparable#clip is deprecated. Use Comparable#clamp instead.", uplevel: 1
|
|
6
|
+
warn "Comparable#clip is deprecated. Use Comparable#clamp instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
6
7
|
upper ? clamp(lower, upper) : clamp(lower..)
|
|
7
8
|
end
|
|
8
9
|
|
|
@@ -2,16 +2,29 @@ require 'facets/dir/find'
|
|
|
2
2
|
|
|
3
3
|
class Dir
|
|
4
4
|
|
|
5
|
+
# Recursively list every entry below +path+ (not +path+ itself),
|
|
6
|
+
# yielding each one to the block if given.
|
|
7
|
+
#
|
|
5
8
|
# @deprecated Use Dir.find or Find.find instead.
|
|
9
|
+
# Scheduled for removal after 2027-09-30.
|
|
6
10
|
def self.recurse(path='.', &block)
|
|
7
|
-
warn "Dir.recurse is deprecated. Use Dir.find or Find.find instead.", uplevel: 1
|
|
8
|
-
|
|
11
|
+
warn "Dir.recurse is deprecated. Use Dir.find or Find.find instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
12
|
+
recurse_entries(path, &block)
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
# @deprecated Use Dir.find or Find.find instead.
|
|
16
|
+
# Scheduled for removal after 2027-09-30.
|
|
12
17
|
def self.ls_r(path='.', &block)
|
|
13
|
-
warn "Dir.ls_r is deprecated. Use Dir.find or Find.find instead.", uplevel: 1
|
|
14
|
-
|
|
18
|
+
warn "Dir.ls_r is deprecated. Use Dir.find or Find.find instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
19
|
+
recurse_entries(path, &block)
|
|
15
20
|
end
|
|
16
21
|
|
|
22
|
+
# Dir.find yields +path+ first; the old #recurse did not include it.
|
|
23
|
+
def self.recurse_entries(path, &block)
|
|
24
|
+
list = Dir.find(path).drop(1)
|
|
25
|
+
list.each(&block) if block
|
|
26
|
+
list
|
|
27
|
+
end
|
|
28
|
+
private_class_method :recurse_entries
|
|
29
|
+
|
|
17
30
|
end
|
|
@@ -15,7 +15,7 @@ module Enumerable
|
|
|
15
15
|
# does almost the same thing and enum.map{}.compact works too.
|
|
16
16
|
|
|
17
17
|
def compact_map(&block)
|
|
18
|
-
warn "Enumerable#compact_map is deprecated. Use Enumerable#filter_map instead.", uplevel: 1
|
|
18
|
+
warn "Enumerable#compact_map is deprecated. Use Enumerable#filter_map instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
19
19
|
filter_map(&block)
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -27,7 +27,7 @@ module Enumerable
|
|
|
27
27
|
# to output each result and discard it.
|
|
28
28
|
#
|
|
29
29
|
def defer(&blk)
|
|
30
|
-
warn "Enumerable#defer is deprecated. Use Enumerable#lazy instead.", uplevel: 1
|
|
30
|
+
warn "Enumerable#defer is deprecated. Use Enumerable#lazy instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
31
31
|
lazy
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -16,7 +16,7 @@ module Enumerable
|
|
|
16
16
|
#++
|
|
17
17
|
|
|
18
18
|
def frequency
|
|
19
|
-
warn "Enumerable#frequency is deprecated. Use Enumerable#tally instead.", uplevel: 1
|
|
19
|
+
warn "Enumerable#frequency is deprecated. Use Enumerable#tally instead. It will be removed after 2027-09-30.", uplevel: 1
|
|
20
20
|
tally
|
|
21
21
|
end
|
|
22
22
|
|