restify 2.0.1 → 2.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +1 -1
- data/lib/restify/adapter/base.rb +1 -1
- data/lib/restify/cache.rb +1 -1
- data/lib/restify/relation.rb +7 -11
- data/lib/restify/response.rb +2 -2
- data/lib/restify/version.rb +2 -2
- data/spec/restify/adapter/base_spec.rb +33 -0
- data/spec/restify/context_spec.rb +2 -2
- data/spec/restify/features/opentelemetry_spec.rb +1 -1
- data/spec/restify/global_spec.rb +50 -1
- data/spec/restify/link_spec.rb +13 -3
- data/spec/restify/relation_spec.rb +79 -7
- data/spec/restify/resource_spec.rb +6 -0
- data/spec/restify_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/LICENSE +21 -0
- data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/README.md +23 -0
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/CHANGELOG.md +561 -0
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/MIT-LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/README.rdoc +40 -0
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/CHANGELOG.md +326 -0
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/LICENSE.txt +202 -0
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/README.md +121 -0
- data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/LICENSE.MIT +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/README.YARD.md +12 -0
- data/vendor/bundle/ruby/4.0.0/gems/base64-0.3.0/README.md +48 -0
- data/vendor/bundle/ruby/4.0.0/gems/bigdecimal-4.1.2/LICENSE +56 -0
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/CHANGELOG.md +615 -0
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/README.md +409 -0
- data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/README.md +182 -0
- data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/README.md +43 -0
- data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/CHANGELOG.md +518 -0
- data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/README.md +92 -0
- data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/LICENSE +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/README.md +409 -0
- data/vendor/bundle/ruby/4.0.0/gems/drb-2.2.3/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/CHANGELOG.md +417 -0
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/README.md +118 -0
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/CHANGELOG.md +507 -0
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE +24 -0
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE.SPECS +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/README.md +138 -0
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/LICENSE +19 -0
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/README.md +323 -0
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/changelog.md +127 -0
- data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/LICENSE.txt +16 -0
- data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/README.md +187 -0
- data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/MIT-LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/README.md +139 -0
- data/vendor/bundle/ruby/4.0.0/gems/json-2.19.9/README.md +310 -0
- data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/README.md +88 -0
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/CHANGELOG.md +15 -0
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/README.md +173 -0
- data/vendor/bundle/ruby/4.0.0/gems/little-plugger-1.1.4/README.rdoc +53 -0
- data/vendor/bundle/ruby/4.0.0/gems/logger-1.7.0/README.md +104 -0
- data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/LICENSE +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/README.md +140 -0
- data/vendor/bundle/ruby/4.0.0/gems/minitest-6.0.6/README.rdoc +763 -0
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/ChangeLog +383 -0
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/LICENSE +177 -0
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/README.md +302 -0
- data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/LICENSE.md +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/README.md +281 -0
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/LICENSE +37 -0
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/README +59 -0
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/license.md +80 -0
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/readme.md +91 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/CHANGELOG.md +219 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/README.md +68 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/CHANGELOG.md +110 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/README.md +62 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/CHANGELOG.md +97 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/README.md +155 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/CHANGELOG.md +192 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/README.md +66 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/CHANGELOG.md +31 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/README.md +40 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/CHANGELOG.md +302 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/README.md +101 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/CHANGELOG.md +65 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/LICENSE +201 -0
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/README.md +115 -0
- data/vendor/bundle/ruby/4.0.0/gems/parallel-2.1.0/MIT-LICENSE.txt +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/parser-3.3.11.1/LICENSE.txt +26 -0
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/CHANGELOG.md +786 -0
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/LICENSE.md +7 -0
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/README.md +143 -0
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/CHANGELOG.md +649 -0
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/README.md +231 -0
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/LICENSE +29 -0
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/README.md +484 -0
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/README.md +9 -0
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/rc.d/README.md +74 -0
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/ChangeLog +846 -0
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.ja.rdoc +58 -0
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.rdoc +60 -0
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/CHANGELOG.md +1346 -0
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/MIT-LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/README.md +384 -0
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/Changelog.md +101 -0
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/README.markdown +227 -0
- data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/README.rdoc +155 -0
- data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/LICENSE +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/README.md +107 -0
- data/vendor/bundle/ruby/4.0.0/gems/regexp_parser-2.12.0/LICENSE +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/README.md +57 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/LICENSE.md +27 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/README.md +47 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/Changelog.md +2447 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/LICENSE.md +26 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/README.md +389 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/Changelog.md +1366 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/LICENSE.md +25 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/README.md +326 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/Changelog.md +1351 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/LICENSE.md +25 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/README.md +465 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/Changelog.md +444 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/LICENSE.md +23 -0
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/README.md +40 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/LICENSE.txt +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/README.md +255 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/LICENSE.txt +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/README.md +54 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/CHANGELOG.md +116 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/MIT-LICENSE.md +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/README.md +91 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/CHANGELOG.md +135 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/MIT-LICENSE.md +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/README.md +91 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/LICENSE.txt +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/README.md +100 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/CHANGELOG.md +1136 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/MIT-LICENSE.md +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/README.md +112 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/CHANGELOG.md +98 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/MIT-LICENSE.md +21 -0
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/README.md +93 -0
- data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/LICENSE.txt +19 -0
- data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/README.md +131 -0
- data/vendor/bundle/ruby/4.0.0/gems/securerandom-0.4.1/README.md +72 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/CHANGELOG.md +191 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/README.md +974 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/LICENSE +202 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/README.md +65 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/CHANGELOG.md +114 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/README.md +30 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/CHANGELOG.md +13 -0
- data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/README.md +29 -0
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/CHANGELOG.md +465 -0
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/LICENSE +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/README.md +588 -0
- data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/LICENSE +19 -0
- data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/README.md +406 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/CHANGELOG.md +299 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/MIT-LICENSE.txt +22 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/README.md +194 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/CHANGELOG.md +202 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/MIT-LICENSE.txt +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/README.md +205 -0
- data/vendor/bundle/ruby/4.0.0/gems/uri-1.1.1/README.md +55 -0
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/CHANGELOG.md +2148 -0
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/LICENSE +20 -0
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/README.md +1229 -0
- metadata +171 -4
- data/doc/file.README.html +0 -192
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2012 Liu Fengyun
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# Hashdiff [](https://github.com/liufengyun/hashdiff/actions?query=workflow%3Aci) [](http://badge.fury.io/rb/hashdiff)
|
|
2
|
+
|
|
3
|
+
Hashdiff is a ruby library to compute the smallest difference between two hashes.
|
|
4
|
+
|
|
5
|
+
It also supports comparing two arrays.
|
|
6
|
+
|
|
7
|
+
Hashdiff does not monkey-patch any existing class. All features are contained inside the `Hashdiff` module.
|
|
8
|
+
|
|
9
|
+
**Docs**: [Documentation](http://rubydoc.info/gems/hashdiff)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__WARNING__: Don't use the library for comparing large arrays, say ~10K (see #49).
|
|
13
|
+
|
|
14
|
+
## Why Hashdiff?
|
|
15
|
+
|
|
16
|
+
Given two Hashes A and B, sometimes you face the question: what's the smallest modification that can be made to change A into B?
|
|
17
|
+
|
|
18
|
+
An algorithm that responds to this question has to do following:
|
|
19
|
+
|
|
20
|
+
* Generate a list of additions, deletions and changes, so that `A + ChangeSet = B` and `B - ChangeSet = A`.
|
|
21
|
+
* Compute recursively -- Arrays and Hashes may be nested arbitrarily in A or B.
|
|
22
|
+
* Compute the smallest change -- it should recognize similar child Hashes or child Arrays between A and B.
|
|
23
|
+
|
|
24
|
+
Hashdiff answers the question above using an opinionated approach:
|
|
25
|
+
|
|
26
|
+
* Hash can be represented as a list of (dot-syntax-path, value) pairs. For example, `{a:[{c:2}]}` can be represented as `["a[0].c", 2]`.
|
|
27
|
+
* The change set can be represented using the dot-syntax representation. For example, `[['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]`.
|
|
28
|
+
* It compares Arrays using the [LCS(longest common subsequence)](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem) algorithm.
|
|
29
|
+
* It recognizes similar Hashes in an Array using a similarity value (0 < similarity <= 1).
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
To use the gem, add the following to your Gemfile:
|
|
34
|
+
|
|
35
|
+
```Ruby
|
|
36
|
+
gem 'hashdiff'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Diff
|
|
42
|
+
|
|
43
|
+
Two simple hashes:
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
a = {a:3, b:2}
|
|
47
|
+
b = {}
|
|
48
|
+
|
|
49
|
+
diff = Hashdiff.diff(a, b)
|
|
50
|
+
diff.should == [['-', 'a', 3], ['-', 'b', 2]]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
More complex hashes:
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
|
|
57
|
+
b = {a:{y:3}, b:{y:3, z:30}}
|
|
58
|
+
|
|
59
|
+
diff = Hashdiff.diff(a, b)
|
|
60
|
+
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Arrays in hashes:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
a = {a:[{x:2, y:3, z:4}, {x:11, y:22, z:33}], b:{x:3, z:45}}
|
|
67
|
+
b = {a:[{y:3}, {x:11, z:33}], b:{y:22}}
|
|
68
|
+
|
|
69
|
+
diff = Hashdiff.best_diff(a, b)
|
|
70
|
+
diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Patch
|
|
74
|
+
|
|
75
|
+
patch example:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
a = {'a' => 3}
|
|
79
|
+
b = {'a' => {'a1' => 1, 'a2' => 2}}
|
|
80
|
+
|
|
81
|
+
diff = Hashdiff.diff(a, b)
|
|
82
|
+
Hashdiff.patch!(a, diff).should == b
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
unpatch example:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 1]
|
|
89
|
+
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
|
90
|
+
|
|
91
|
+
diff = Hashdiff.diff(a, b) # diff two array is OK
|
|
92
|
+
Hashdiff.unpatch!(b, diff).should == a
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Options
|
|
96
|
+
|
|
97
|
+
The following options are available: `:delimiter`, `:similarity`, `:strict`, `:ignore_keys`,
|
|
98
|
+
`:indifferent`, `:numeric_tolerance`, `:strip`, `:case_insensitive`, `:array_path`,
|
|
99
|
+
`:use_lcs`, and `:preserve_key_order`
|
|
100
|
+
|
|
101
|
+
#### `:delimiter`
|
|
102
|
+
|
|
103
|
+
You can specify `:delimiter` to be something other than the default dot. For example:
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
|
|
107
|
+
b = {a:{y:3}, b:{y:3, z:30}}
|
|
108
|
+
|
|
109
|
+
diff = Hashdiff.diff(a, b, delimiter: '\t')
|
|
110
|
+
diff.should == [['-', 'a\tx', 2], ['-', 'a\tz', 4], ['-', 'b\tx', 3], ['~', 'b\tz', 45, 30], ['+', 'b\ty', 3]]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `:similarity`
|
|
114
|
+
|
|
115
|
+
In cases where you have similar hash objects in arrays, you can pass a custom value for `:similarity` instead of the default `0.8`. This is interpreted as a ratio of similarity (default is 80% similar, whereas `:similarity => 0.5` would look for at least a 50% similarity).
|
|
116
|
+
|
|
117
|
+
#### `:strict`
|
|
118
|
+
|
|
119
|
+
The `:strict` option, which defaults to `true`, specifies whether numeric types are compared on type as well as value. By default, an Integer will never be equal to a Float (e.g. 4 != 4.0). Setting `:strict` to false makes the comparison looser (e.g. 4 == 4.0).
|
|
120
|
+
|
|
121
|
+
#### `:ignore_keys`
|
|
122
|
+
|
|
123
|
+
The `:ignore_keys` option allows you to specify one or more keys to ignore, which defaults to `[]` (none). Ignored keys are ignored at all levels in both hashes. For example:
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
a = { a: 4, g: 0, b: { a: 5, c: 6, e: 1 } }
|
|
127
|
+
b = { b: { a: 7, c: 3, f: 1 }, d: 8 }
|
|
128
|
+
diff = Hashdiff.diff(a, b, ignore_keys: %i[a f])
|
|
129
|
+
diff.should == [['-', 'g', 0], ['-', 'b.e', 1], ['~', 'b.c', 6, 3], ['+', 'd', 8]]
|
|
130
|
+
```
|
|
131
|
+
If you wish instead to ignore keys at a particlar level you should
|
|
132
|
+
use a [custom comparison method](https://github.com/liufengyun/hashdiff#specifying-a-custom-comparison-method) instead. For example to diff only at the 2nd level of both hashes:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
a = { a: 4, g: 0, b: { a: 5, c: 6, e: 1 } }
|
|
136
|
+
b = { b: { a: 7, c: 3, f: 1 }, d: 8 }
|
|
137
|
+
diff = Hashdiff.diff(a, b) do |path, _e, _a|
|
|
138
|
+
arr = path.split('.')
|
|
139
|
+
true if %w[a f].include?(arr.last) && arr.size == 2 # note '.' is the default delimiter
|
|
140
|
+
end
|
|
141
|
+
diff.should == [['-', 'a', 4], ['-', 'g', 0], ['-', 'b.e', 1], ['~', 'b.c', 6, 3], ['+', 'd', 8]]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### `:indifferent`
|
|
145
|
+
|
|
146
|
+
The `:indifferent` option, which defaults to `false`, specifies whether to treat hash keys indifferently. Setting `:indifferent` to true has the effect of ignoring differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
|
|
147
|
+
|
|
148
|
+
#### `:numeric_tolerance`
|
|
149
|
+
|
|
150
|
+
The :numeric_tolerance option allows for a small numeric tolerance.
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
a = {x:5, y:3.75, z:7}
|
|
154
|
+
b = {x:6, y:3.76, z:7}
|
|
155
|
+
|
|
156
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1)
|
|
157
|
+
diff.should == [["~", "x", 5, 6]]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### `:strip`
|
|
161
|
+
|
|
162
|
+
The :strip option strips all strings before comparing.
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
a = {x:5, s:'foo '}
|
|
166
|
+
b = {x:6, s:'foo'}
|
|
167
|
+
|
|
168
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, strip: true)
|
|
169
|
+
diff.should == [["~", "x", 5, 6]]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### `:case_insensitive`
|
|
173
|
+
|
|
174
|
+
The :case_insensitive option makes string comparisons ignore case.
|
|
175
|
+
|
|
176
|
+
```ruby
|
|
177
|
+
a = {x:5, s:'FooBar'}
|
|
178
|
+
b = {x:6, s:'foobar'}
|
|
179
|
+
|
|
180
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, case_insensitive: true)
|
|
181
|
+
diff.should == [["~", "x", 5, 6]]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### `:array_path`
|
|
185
|
+
|
|
186
|
+
The :array_path option represents the path of the diff in an array rather than
|
|
187
|
+
a string. This can be used to show differences in between hash key types and
|
|
188
|
+
is useful for `patch!` when used on hashes without string keys.
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
a = {x:5}
|
|
192
|
+
b = {'x'=>6}
|
|
193
|
+
|
|
194
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
|
195
|
+
diff.should == [['-', [:x], 5], ['+', ['x'], 6]]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
For cases where there are arrays in paths their index will be added to the path.
|
|
199
|
+
```ruby
|
|
200
|
+
a = {x:[0,1]}
|
|
201
|
+
b = {x:[0,2]}
|
|
202
|
+
|
|
203
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
|
204
|
+
diff.should == [["-", [:x, 1], 1], ["+", [:x, 1], 2]]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
This shouldn't cause problems if you are comparing an array with a hash:
|
|
208
|
+
|
|
209
|
+
```ruby
|
|
210
|
+
a = {x:{0=>1}}
|
|
211
|
+
b = {x:[1]}
|
|
212
|
+
|
|
213
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
|
214
|
+
diff.should == [["~", [:x], {0=>1}, [1]]]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### `:use_lcs`
|
|
218
|
+
|
|
219
|
+
The :use_lcs option is used to specify whether a
|
|
220
|
+
[Longest common subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)
|
|
221
|
+
(LCS) algorithm is used to determine differences in arrays. This defaults to
|
|
222
|
+
`true` but can be changed to `false` for significantly faster array comparisons
|
|
223
|
+
(O(n) complexity rather than O(n<sup>2</sup>) for LCS).
|
|
224
|
+
|
|
225
|
+
When :use_lcs is false the results of array comparisons have a tendency to
|
|
226
|
+
show changes at indexes rather than additions and subtractions when :use_lcs is
|
|
227
|
+
true.
|
|
228
|
+
|
|
229
|
+
Note, currently the :similarity option has no effect when :use_lcs is false.
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
a = {x: [0, 1, 2]}
|
|
233
|
+
b = {x: [0, 2, 2, 3]}
|
|
234
|
+
|
|
235
|
+
diff = Hashdiff.diff(a, b, use_lcs: false)
|
|
236
|
+
diff.should == [["~", "x[1]", 1, 2], ["+", "x[3]", 3]]
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### `:preserve_key_order`
|
|
240
|
+
|
|
241
|
+
By default, the change set is ordered by operation type: deletions (-) first, then updates (~), and finally additions (+).
|
|
242
|
+
Within each operation group, keys are sorted alphabetically:
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
a = {d: 1, c: 1, a: 1}
|
|
246
|
+
b = {d: 2, b: 2, a: 2}
|
|
247
|
+
|
|
248
|
+
diff = Hashdiff.diff(a, b)
|
|
249
|
+
diff.should == [["-", "c", 1], ["~", "a", 1, 2], ["~", "d", 1, 2], ["+", "b", 2]]
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Setting :preserve_key_order to true processes keys in the order they appear in the first hash.
|
|
253
|
+
Keys that only exist in the second hash are appended in their original order:
|
|
254
|
+
|
|
255
|
+
```ruby
|
|
256
|
+
a = {d: 1, c: 1, a: 1}
|
|
257
|
+
b = {d: 2, b: 2, a: 2}
|
|
258
|
+
|
|
259
|
+
diff = Hashdiff.diff(a, b, preserve_key_order: true)
|
|
260
|
+
diff.should == [["~", "d", 1, 2], ["-", "c", 1], ["~", "a", 1, 2], ["+", "b", 2]]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Specifying a custom comparison method
|
|
264
|
+
|
|
265
|
+
It's possible to specify how the values of a key should be compared.
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
a = {a:'car', b:'boat', c:'plane'}
|
|
269
|
+
b = {a:'bus', b:'truck', c:' plan'}
|
|
270
|
+
|
|
271
|
+
diff = Hashdiff.diff(a, b) do |path, obj1, obj2|
|
|
272
|
+
case path
|
|
273
|
+
when /a|b|c/
|
|
274
|
+
obj1.length == obj2.length
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
diff.should == [['~', 'b', 'boat', 'truck']]
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The yielded params of the comparison block is `|path, obj1, obj2|`, in which path is the key (or delimited compound key) to the value being compared. When comparing elements in array, the path is with the format `array[*]`. For example:
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
a = {a:'car', b:['boat', 'plane'] }
|
|
285
|
+
b = {a:'bus', b:['truck', ' plan'] }
|
|
286
|
+
|
|
287
|
+
diff = Hashdiff.diff(a, b) do |path, obj1, obj2|
|
|
288
|
+
case path
|
|
289
|
+
when 'b[*]'
|
|
290
|
+
obj1.length == obj2.length
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
diff.should == [["~", "a", "car", "bus"], ["~", "b[1]", "plane", " plan"], ["-", "b[0]", "boat"], ["+", "b[0]", "truck"]]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
When a comparison block is given, it'll be given priority over other specified options. If the block returns value other than `true` or `false`, then the two values will be compared with other specified options.
|
|
298
|
+
|
|
299
|
+
When used in conjunction with the `array_path` option, the path passed in as an argument will be an array. When determining the ordering of an array a key of `"*"` will be used in place of the `key[*]` field. It is possible, if you have hashes with integer or `"*"` keys, to have problems distinguishing between arrays and hashes - although this shouldn't be an issue unless your data is very difficult to predict and/or your custom rules are very specific.
|
|
300
|
+
|
|
301
|
+
#### Sorting arrays before comparison
|
|
302
|
+
|
|
303
|
+
An order difference alone between two arrays can create too many diffs to be useful. Consider sorting them prior to diffing.
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
a = {a:'car', b:['boat', 'plane'] }
|
|
307
|
+
b = {a:'car', b:['plane', 'boat'] }
|
|
308
|
+
|
|
309
|
+
Hashdiff.diff(a, b).should == [["+", "b[0]", "plane"], ["-", "b[2]", "plane"]]
|
|
310
|
+
|
|
311
|
+
b[:b].sort!
|
|
312
|
+
|
|
313
|
+
Hashdiff.diff(a, b).should == []
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Maintainers
|
|
317
|
+
|
|
318
|
+
- Krzysztof Rybka ([@krzysiek1507](https://github.com/krzysiek1507))
|
|
319
|
+
- Fengyun Liu ([@liufengyun](https://github.com/liufengyun))
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
Hashdiff is distributed under the MIT-LICENSE.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
## v1.2.1 2025-09-06
|
|
4
|
+
|
|
5
|
+
* Use HTTPS for the source in the Gemfile [#101](https://github.com/liufengyun/hashdiff/issues/101) ([@krzysiek1507](https://github.com/krzysiek1507))
|
|
6
|
+
|
|
7
|
+
## v1.2.0 2025-5-20
|
|
8
|
+
|
|
9
|
+
* Added :preserve_key_order option to maintain original hash key order [#99](https://github.com/liufengyun/hashdiff/issues/99) ([@robkiessling](https://github.com/robkiessling))
|
|
10
|
+
|
|
11
|
+
## v1.1.2 2024-11-12
|
|
12
|
+
|
|
13
|
+
* Fix bundler cache [#96](https://github.com/liufengyun/hashdiff/issues/96) ([@olleolleolle](https://github.com/olleolleolle))
|
|
14
|
+
* Quote the '3.0' in YAML [#95](https://github.com/liufengyun/hashdiff/issues/95) ([@olleolleolle](https://github.com/olleolleolle))
|
|
15
|
+
* Fix version in source code [#97](https://github.com/liufengyun/hashdiff/issues/97) ([@liufengyun](https://github.com/liufengyun))
|
|
16
|
+
|
|
17
|
+
## v1.1.1 2024-08-02
|
|
18
|
+
|
|
19
|
+
* Fix bug in ignore_keys option [#88](https://github.com/liufengyun/hashdiff/issues/88) ([@Matzfan](https://github.com/Matzfan))
|
|
20
|
+
* Exclude spec files from gem package [#94](https://github.com/liufengyun/hashdiff/issues/94) ([@amatsuda](https://github.com/amatsuda))
|
|
21
|
+
|
|
22
|
+
## v1.1.0 2023-12-14
|
|
23
|
+
|
|
24
|
+
* Add ignore_keys option ([#86](https://github.com/liufengyun/hashdiff/issues/86) [@Matzfan](https://github.com/Matzfan))
|
|
25
|
+
* Remove pinned version of rake < 11
|
|
26
|
+
* Bump rspec dep ~> 3.5
|
|
27
|
+
* Bump rubocop dep >= 1.52.1
|
|
28
|
+
* Bump rubocop-rspec dep > 1.16.0
|
|
29
|
+
|
|
30
|
+
## v1.0.1 2020-02-25
|
|
31
|
+
|
|
32
|
+
* Add indifferent option
|
|
33
|
+
|
|
34
|
+
## v1.0.0 2019-06-06
|
|
35
|
+
|
|
36
|
+
* Fix typo in readme ([#72](https://github.com/liufengyun/hashdiff/issues/72) [@koic](https://github.com/koic))
|
|
37
|
+
* Fix Rubocop offence ([#73](https://github.com/liufengyun/hashdiff/issues/73) [@koic](https://github.com/koic))
|
|
38
|
+
* Bumps version to v1.0.0 ([#74](https://github.com/liufengyun/hashdiff/issues/74) [@jfelchner](https://github.com/jfelchner))
|
|
39
|
+
|
|
40
|
+
## v1.0.0.beta1 2019-06-06
|
|
41
|
+
|
|
42
|
+
* fix warnings in ci ([#69](https://github.com/liufengyun/hashdiff/issues/69) [@y-yagi](https://github.com/y-yagi))
|
|
43
|
+
* drop warnings of the constant change ([#70](https://github.com/liufengyun/hashdiff/issues/70) [@jfelchner](https://github.com/jfelchner))
|
|
44
|
+
|
|
45
|
+
## v0.4.0 2019-05-28
|
|
46
|
+
|
|
47
|
+
* refactoring ([#56](https://github.com/liufengyun/hashdiff/issues/56) [#57](https://github.com/liufengyun/hashdiff/issues/57) [#59](https://github.com/liufengyun/hashdiff/issues/59) [#61](https://github.com/liufengyun/hashdiff/issues/61) [@krzysiek1507](https://github.com/krzysiek1507))
|
|
48
|
+
* fix typo in README ([#64](https://github.com/liufengyun/hashdiff/issues/64) [@pboling](https://github.com/pboling))
|
|
49
|
+
* change HashDiff to Hashdiff ([#65](https://github.com/liufengyun/hashdiff/issues/65) [@jfelchner](https://github.com/jfelchner))
|
|
50
|
+
|
|
51
|
+
## v0.3.9 2019-04-22
|
|
52
|
+
|
|
53
|
+
* Performance tweak (thanks [@krzysiek1507](https://github.com/krzysiek1507): [#51](https://github.com/liufengyun/hashdiff/issues/51) [#52](https://github.com/liufengyun/hashdiff/issues/52) [#53](https://github.com/liufengyun/hashdiff/issues/53))
|
|
54
|
+
|
|
55
|
+
## v0.3.8 2018-12-30
|
|
56
|
+
|
|
57
|
+
* Add Rubocop and drops Ruby 1.9 support [#47](https://github.com/liufengyun/hashdiff/issues/47)
|
|
58
|
+
|
|
59
|
+
## v0.3.7 2017-10-08
|
|
60
|
+
|
|
61
|
+
* remove 1.8.7 support from gemspec [#39](https://github.com/liufengyun/hashdiff/issues/39)
|
|
62
|
+
|
|
63
|
+
## v0.3.6 2017-08-22
|
|
64
|
+
|
|
65
|
+
* add option `use_lcs` [#35](https://github.com/liufengyun/hashdiff/issues/35)
|
|
66
|
+
|
|
67
|
+
## v0.3.5 2017-08-06
|
|
68
|
+
|
|
69
|
+
* add option `array_path` [#34](https://github.com/liufengyun/hashdiff/issues/34)
|
|
70
|
+
|
|
71
|
+
## v0.3.4 2017-05-01
|
|
72
|
+
|
|
73
|
+
* performance improvement of `#similar?` [#31](https://github.com/liufengyun/hashdiff/issues/31)
|
|
74
|
+
|
|
75
|
+
## v0.3.2 2016-12-27
|
|
76
|
+
|
|
77
|
+
* replace `Fixnum` by `Integer` [#28](https://github.com/liufengyun/hashdiff/issues/28)
|
|
78
|
+
|
|
79
|
+
## v0.3.1 2016-11-24
|
|
80
|
+
|
|
81
|
+
* fix an error when a hash has mixed types [#26](https://github.com/liufengyun/hashdiff/issues/26)
|
|
82
|
+
|
|
83
|
+
## v0.3.0 2016-2-11
|
|
84
|
+
|
|
85
|
+
* support `:case_insensitive` option
|
|
86
|
+
|
|
87
|
+
## v0.2.3 2015-11-5
|
|
88
|
+
|
|
89
|
+
* improve performance of LCS algorithm [#12](https://github.com/liufengyun/hashdiff/issues/12)
|
|
90
|
+
|
|
91
|
+
## v0.2.2 2014-10-6
|
|
92
|
+
|
|
93
|
+
* make library 1.8.7 compatible
|
|
94
|
+
|
|
95
|
+
## v0.2.1 2014-7-13
|
|
96
|
+
|
|
97
|
+
* yield added/deleted keys for custom comparison
|
|
98
|
+
|
|
99
|
+
## v0.2.0 2014-3-29
|
|
100
|
+
|
|
101
|
+
* support custom comparison blocks
|
|
102
|
+
* support `:strip`, `:numeric_tolerance` and `:strict` options
|
|
103
|
+
|
|
104
|
+
## v0.1.0 2013-8-25
|
|
105
|
+
|
|
106
|
+
* use options for parameters `:delimiter` and `:similarity` in interfaces
|
|
107
|
+
|
|
108
|
+
## v0.0.6 2013-3-2
|
|
109
|
+
|
|
110
|
+
* Add parameter for custom property-path delimiter.
|
|
111
|
+
|
|
112
|
+
## v0.0.5 2012-7-1
|
|
113
|
+
|
|
114
|
+
* fix a bug in judging whehter two objects are similiar.
|
|
115
|
+
* add more spec test for `.best_diff`
|
|
116
|
+
|
|
117
|
+
## v0.0.4 2012-6-24
|
|
118
|
+
|
|
119
|
+
Main changes in this version is to output the whole object in addition & deletion, instead of recursely add/deletes the object.
|
|
120
|
+
|
|
121
|
+
For example, `diff({a:2, c:[4, 5]}, {a:2}) will generate following output:
|
|
122
|
+
|
|
123
|
+
[['-', 'c', [4, 5]]]
|
|
124
|
+
|
|
125
|
+
instead of following:
|
|
126
|
+
|
|
127
|
+
[['-', 'c[0]', 4], ['-', 'c[1]', 5], ['-', 'c', []]]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
ISC LICENSE - http://opensource.org/licenses/isc-license.txt
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2008-2015 Jeremy Hinegardner
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Hitimes
|
|
2
|
+
[](https://copiousfreetime.semaphoreci.com/projects/hitimes)
|
|
3
|
+
|
|
4
|
+
* [Homepage](http://github.com/copiousfreetime/hitimes)
|
|
5
|
+
* [Github project](http://github.com/copiousfreetime/hitimes)
|
|
6
|
+
|
|
7
|
+
## DESCRIPTION
|
|
8
|
+
|
|
9
|
+
A fast, high resolution timer library for recording performance metrics.
|
|
10
|
+
|
|
11
|
+
## TABLE OF CONTENTS
|
|
12
|
+
|
|
13
|
+
* [Requirements](#requirements)
|
|
14
|
+
* [Usage](#usage)
|
|
15
|
+
* [Contributing](#contributing)
|
|
16
|
+
* [Support](#support)
|
|
17
|
+
* [License](#license)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## REQUIREMENTS
|
|
21
|
+
|
|
22
|
+
Hitimes requires the following to run:
|
|
23
|
+
|
|
24
|
+
* Ruby
|
|
25
|
+
|
|
26
|
+
## USAGE
|
|
27
|
+
|
|
28
|
+
Hitimes easiest to use when installed with `rubygems`:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
gem install hitimes
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or as part of your bundler `Gemfile`:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
gem "hitimes"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
You can load it with the standard ruby require statement.
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require "hitimes"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Interval
|
|
47
|
+
|
|
48
|
+
Use `Hitimes::Interval` to calculate only the duration of a block of code.
|
|
49
|
+
Returns the time as seconds.
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
duration = Hitimes::Interval.measure do
|
|
53
|
+
1_000_000.times do |x|
|
|
54
|
+
2 + 2
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
puts duration # => 0.047414297 (seconds)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### TimedMetric
|
|
62
|
+
|
|
63
|
+
Use a `Hitimes::TimedMetric` to calculate statistics about an iterative operation
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
timed_metric = Hitimes::TimedMetric.new("operation on items")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Explicitly use `start` and `stop`:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
collection.each do |item|
|
|
73
|
+
timed_metric.start
|
|
74
|
+
# .. do something with item
|
|
75
|
+
timed_metric.stop
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Or use the block. In `TimedMetric` the return value of `measure` is the return
|
|
80
|
+
value of the block.
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
collection.each do |item|
|
|
84
|
+
result_of_do_something = timed_metric.measure { do_something(item) }
|
|
85
|
+
# do something with result_of_do_something
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
And then look at the stats
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
puts timed_metric.mean
|
|
92
|
+
puts timed_metric.max
|
|
93
|
+
puts timed_metric.min
|
|
94
|
+
puts timed_metric.stddev
|
|
95
|
+
puts timed_metric.rate
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ValueMetric
|
|
99
|
+
|
|
100
|
+
Use a `Hitimes::ValueMetric` to calculate statistics about measured samples.
|
|
101
|
+
|
|
102
|
+
``` ruby
|
|
103
|
+
value_metric = Hitimes::ValueMetric.new("size of thing")
|
|
104
|
+
loop do
|
|
105
|
+
# ... do stuff changing sizes of 'thing'
|
|
106
|
+
value_metric.measure(thing.size)
|
|
107
|
+
# ... do other stuff that may change size of thing
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
puts value_metric.mean
|
|
111
|
+
puts value_metric.max
|
|
112
|
+
puts value_metric.min
|
|
113
|
+
puts value_metric.stddev
|
|
114
|
+
puts value_metric.rate
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### TimedValueMetric
|
|
118
|
+
|
|
119
|
+
Use a `Hitimes::TimedValueMetric` to calculate statistics about batches of samples.
|
|
120
|
+
|
|
121
|
+
``` ruby
|
|
122
|
+
timed_value_metric = Hitimes::TimedValueMetric.new("batch times")
|
|
123
|
+
loop do
|
|
124
|
+
# batch = ... # get a batch of things
|
|
125
|
+
timed_value_metric.start
|
|
126
|
+
# .. do something with batch
|
|
127
|
+
timed_value_metric.stop(batch.size)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
puts timed_value_metric.rate
|
|
131
|
+
|
|
132
|
+
puts timed_value_metric.timed_stats.mean
|
|
133
|
+
puts timed_value_metric.timed_stats.max
|
|
134
|
+
puts timed_value_metric.timed_stats.min
|
|
135
|
+
puts timed_value_metric.timed_stats.stddev
|
|
136
|
+
|
|
137
|
+
puts timed_value_metric.value_stats.mean
|
|
138
|
+
puts timed_value_metric.value_stats.max
|
|
139
|
+
puts timed_value_metric.value_stats.min
|
|
140
|
+
puts timed_value_metric.value_stats.stddev
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Implementation details
|
|
144
|
+
|
|
145
|
+
Hitimes uses the internal ruby `Process::clock_gettime()` to
|
|
146
|
+
get the highest granularity time increment possible. Generally this is
|
|
147
|
+
nanosecond resolution, or whatever the hardware in the CPU supports.
|
|
148
|
+
|
|
149
|
+
## SUPPORT
|
|
150
|
+
|
|
151
|
+
Hitimes is supported on whatever versions of ruby are currently supported.
|
|
152
|
+
Hitimes also follows [semantic versioning](http://semver.org/).
|
|
153
|
+
|
|
154
|
+
The current officially supported versions of Ruby are:
|
|
155
|
+
|
|
156
|
+
* MRI Ruby (all platforms) 3.0 - current
|
|
157
|
+
* JRuby 9.4.x.x
|
|
158
|
+
* Truffleruby 24
|
|
159
|
+
|
|
160
|
+
Unofficially supported versions, any version of MRI from Ruby 2.1 and up. Since
|
|
161
|
+
the C Extension has been removed Hitimes should work with any ruby that is 2.1
|
|
162
|
+
or greater as that is when `Process.clock_gettime()` was implemented.
|
|
163
|
+
|
|
164
|
+
For versions of Ruby before 2.1 please use Hitimes 1.3, the extension code is
|
|
165
|
+
still in there and they should still work.
|
|
166
|
+
|
|
167
|
+
## CONTRIBUTING
|
|
168
|
+
|
|
169
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on development
|
|
170
|
+
and bug reporting.
|
|
171
|
+
|
|
172
|
+
## Credits
|
|
173
|
+
|
|
174
|
+
* [Bruce Williams](https://github.com/bruce) for suggesting the idea.
|
|
175
|
+
* [Benoit Daloze](https://github.com/eregon) and [Thomas Hurst](https://github.com/Freaky) for conversations around clock_ids.
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
Hitimes is licensed under the [ISC](https://opensource.org/licenses/ISC)
|
|
180
|
+
license.
|
|
181
|
+
|
|
182
|
+
## Related Works
|
|
183
|
+
|
|
184
|
+
* [monotime](https://github.com/Freaky/monotime) - A sensible interface to Ruby's monotonic clock.
|
|
185
|
+
* [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) - [Concurrent.monotonic_time](https://github.com/ruby-concurrency/concurrent-ruby) is a straight pass through to `Process.clock_gettime(Process::CLOCK_MONOTONIC,...)`.
|
|
186
|
+
* [Instant](https://doc.rust-lang.org/src/std/time.rs.html) - The rust equivalent.
|
|
187
|
+
* [time.Now](https://pkg.go.dev/time) - The go monotonic time interface is part of this package.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2008 The Ruby I18n team
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|