Skip to content

Commit

Permalink
Merge pull request #87 from MatzFan/ignore_keys
Browse files Browse the repository at this point in the history
add ignore_keys options, fixes #86
  • Loading branch information
liufengyun authored Dec 14, 2023
2 parents 7c70482 + c129ed1 commit 4c89772
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 7 deletions.
8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,24 @@ Metrics/BlockLength:
Enabled: false
Metrics/ModuleLength:
Enabled: false
Style/CaseLikeIf:
Enabled: false
Style/Documentation:
Enabled: false
Style/FrozenStringLiteralComment:
Enabled: true
EnforcedStyle: always
Style/OptionalBooleanParameter:
Enabled: false
Style/NumericPredicate:
Enabled: false
Style/RedundantFreeze:
Enabled: false
Style/RedundantReturn:
Enabled: false
RSpec/ExampleLength:
Enabled: false
RSpec/DescribeClass:
Enabled: false
RSpec/FilePath:
Enabled: false
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ source 'http://rubygems.org'
gemspec

group :test do
gem 'rake', '< 11'
gem 'rake'
end
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,8 @@ Hashdiff.unpatch!(b, diff).should == a

### Options

There are eight options available: `:delimiter`, `:similarity`,
`:strict`, `:indifferent`, `:numeric_tolerance`, `:strip`, `:case_insensitive`,
`:array_path` and `:use_lcs`
The following options are available: `:delimiter`, `:similarity`, `:strict`, `:ignore_keys`,
`:indifferent`, `:numeric_tolerance`, `:strip`, `:case_insensitive`, `:array_path` and `:use_lcs`

#### `:delimiter`

Expand All @@ -118,6 +117,26 @@ In cases where you have similar hash objects in arrays, you can pass a custom va

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).

#### `:ignore_keys`

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. For example:

```ruby
a = { a: 1, b: { d: 2, a: 3 }, c: 4 }
b = { a: 2, b: { d: 2, a: 7 }, c: 5 }
diff = Hashdiff.diff(a, b, ignore_keys: :a)
diff.should == [['~', 'c', 4, 5]]
```
If you wish instead to ignore keys at a particlar level you should
use a [custom comparison method](https://github.com/liufengyun/hashdiff#specifying-a-custom-comparison-method) instead. For example:

```ruby
a = { a: 1, b: { d: 2, a: 3 }, c: 4 }
b = { a: 2, b: { d: 2, a: 7 }, c: 5 }
diff = Hashdiff.diff(a, b) { |path, _e, _a| true if path == 'b.a' } # note '.' is the default delimiter
diff.should == [['~', 'a', 1, 2], ['~', 'c', 4, 5]]
```

#### `:indifferent`

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})
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

* Add ignore_keys option (#86 @Matzfan)
* Remove pinned version of rake < 11
* Bump rspec dep ~> 3.5
* Bump rubocop dep >= 1.52.1
* Bump rubocop-rspec dep > 1.16.0

## v1.0.1 2020-02-25

* Add indifferent option
Expand Down
6 changes: 3 additions & 3 deletions hashdiff.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ Gem::Specification.new do |s|
s.homepage = 'https://github.com/liufengyun/hashdiff'

s.add_development_dependency('bluecloth')
s.add_development_dependency('rspec', '~> 2.0')
s.add_development_dependency('rubocop', '~> 0.49.1') # last version that works with ruby 2.0
s.add_development_dependency('rubocop-rspec')
s.add_development_dependency('rspec', '~> 3.5')
s.add_development_dependency('rubocop', '>= 1.52.1') # earliest version that works with Ruby 3.3
s.add_development_dependency('rubocop-rspec', '> 1.16.0') # https://github.com/rubocop/rubocop-rspec/issues/461
s.add_development_dependency('yard')

if s.respond_to?(:metadata)
Expand Down
2 changes: 2 additions & 0 deletions lib/hashdiff/compare_hashes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ def call(obj1, obj2, opts = {})

result = []

opts[:ignore_keys].each { |k| common_keys.delete k }

# add deleted properties
deleted_keys.each do |k|
k = opts[:indifferent] ? obj1_lookup[k] : k
Expand Down
5 changes: 5 additions & 0 deletions lib/hashdiff/diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Hashdiff
# @param [Array, Hash] obj2
# @param [Hash] options the options to use when comparing
# * :strict (Boolean) [true] whether numeric values will be compared on type as well as value. Set to false to allow comparing Integer, Float, BigDecimal to each other
# * :ignore_keys (Symbol, String or Array) [[]] a list of keys to ignore. No comparison is made for the specified key(s)
# * :indifferent (Boolean) [false] whether to treat hash keys indifferently. Set to true to ignore differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
# * :delimiter (String) ['.'] the delimiter used when returning nested key references
# * :numeric_tolerance (Numeric) [0] should be a positive numeric value. Value by which numeric differences must be greater than. By default, numeric values are compared exactly; with the :tolerance option, the difference between numeric values must be greater than the given value.
Expand Down Expand Up @@ -53,6 +54,7 @@ def self.best_diff(obj1, obj2, options = {}, &block)
# @param [Array, Hash] obj2
# @param [Hash] options the options to use when comparing
# * :strict (Boolean) [true] whether numeric values will be compared on type as well as value. Set to false to allow comparing Integer, Float, BigDecimal to each other
# * :ignore_keys (Symbol, String or Array) [[]] a list of keys to ignore. No comparison is made for the specified key(s)
# * :indifferent (Boolean) [false] whether to treat hash keys indifferently. Set to true to ignore differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
# * :similarity (Numeric) [0.8] should be between (0, 1]. Meaningful if there are similar hashes in arrays. See {best_diff}.
# * :delimiter (String) ['.'] the delimiter used when returning nested key references
Expand Down Expand Up @@ -81,6 +83,7 @@ def self.diff(obj1, obj2, options = {}, &block)
similarity: 0.8,
delimiter: '.',
strict: true,
ignore_keys: [],
indifferent: false,
strip: false,
numeric_tolerance: 0,
Expand All @@ -90,6 +93,8 @@ def self.diff(obj1, obj2, options = {}, &block)

opts[:prefix] = [] if opts[:array_path] && opts[:prefix] == ''

opts[:ignore_keys] = [*opts[:ignore_keys]] # splat covers single sym/string case

opts[:comparison] = block if block_given?

# prefer to compare with provided block
Expand Down
15 changes: 15 additions & 0 deletions spec/hashdiff/diff_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@
diff.should == []
end

context 'with the ignore_keys option' do
a = { a: 1, b: { d: 2, a: 3 }, c: 4 }
b = { a: 2, b: { d: 2, a: 7 }, c: 5 }

it 'ignores a single key' do
diff = described_class.diff(a, b, ignore_keys: :a)
diff.should == [['~', 'c', 4, 5]]
end

it 'ignores an array of keys' do
diff = described_class.diff(a, b, ignore_keys: %i[a c])
diff.should == []
end
end

it 'ignores string vs symbol differences, when indifferent is true' do
diff = described_class.diff({ 'a' => 2, :b => 2 }, { :a => 2, 'b' => 2, :c => 3 }, indifferent: true)
diff.should == [['+', 'c', 3]]
Expand Down

0 comments on commit 4c89772

Please sign in to comment.