DiffMatcher === [![build status](http://travis-ci.org/playup/diff_matcher.png)](http://travis-ci.org/playup/diff_matcher) [![still maintained](http://stillmaintained.com/playupchris/diff_matcher.png)](http://stillmaintained.com/playupchris/diff_matcher) Generates a diff by matching against expected values, classes, regexes and/or procs. DiffMatcher performs recursive matches on values contained in hashes, arrays and combinations thereof. Values in a containing object match when: ``` ruby actual.is_a? expected # when expected is a class expected.match actual # when expected is a regexp expected.call actual # when expected is a proc actual == expected # when expected is anything else ``` Example: ``` ruby puts DiffMatcher::difference( { :a=>{ :a1=>11 }, :b=>[ 21, 22 ], :c=>/\d/, :d=>Fixnum, :e=>lambda { |x| (4..6).include? x } }, { :a=>{ :a1=>10, :a2=>12 }, :b=>[ 21 ], :c=>'3' , :d=>4 , :e=>5 }, :color_scheme=>:white_background ) ``` ![example output](https://raw.github.com/playup/diff_matcher/master/doc/diff_matcher.gif) Installation --- gem install diff_matcher Usage --- ``` ruby require 'diff_matcher' DiffMatcher::difference(actual, expected, opts={}) ``` When `expected` != `actual` ``` ruby puts DiffMatcher::difference(1, 2) # => - 1+ 2 # => Where, - 1 missing, + 1 additional ``` When `expected` == `actual` ``` ruby p DiffMatcher::difference(1, 1) # => nil ``` When `actual` is an instance of the `expected` ``` ruby p DiffMatcher::difference(String, '1') # => nil ``` When `actual` is a string that matches the `expected` regex ``` ruby p DiffMatcher::difference(/[a-z]/, "a") # => nil ``` When `actual` is a fixnum that matches the `expected` range ``` ruby p DiffMatcher::difference(1..3, 3) # => nil ``` When `actual` is passed to an `expected` proc and it returns true ``` ruby is_boolean = lambda { |x| [FalseClass, TrueClass].include? x.class } p DiffMatcher::difference(is_boolean, true) # => nil ``` When `actual` is missing one of the `expected` values ``` ruby puts DiffMatcher::difference([1, 2], [1]) # => [ # => 1 # => - 2 # => ] # => Where, - 1 missing ``` When `actual` has additional values to the `expected` ``` ruby puts DiffMatcher::difference([1], [1, 2]) # => [ # => 1 # => + 2 # => ] # => Where, + 1 additional ``` When `expected` is a `Hash` with optional keys use a `Matcher`. ``` ruby puts DiffMatcher::difference( DiffMatcher::Matcher.new({:name=>String, :age=>Fixnum}, :optional_keys=>[:age]), {:name=>0} ) { :name=>- String+ 0 } Where, - 1 missing, + 1 additional ``` When `expected` can take multiple forms use some `Matcher`s `||`ed together. ``` ruby puts DiffMatcher::difference(DiffMatcher::Matcher.new(Fixnum) || DiffMatcher.new(Float), "3") - Float+ "3" Where, - 1 missing, + 1 additional ``` (NB. `DiffMatcher::Matcher[Fixnum, Float]` can be used as a shortcut for `DiffMatcher::Matcher.new(Fixnum) || DiffMatcher.new(Float)` ) When `actual` is an array of *unknown* size use an `AllMatcher` to match against *all* the elements in the array. ``` ruby puts DiffMatcher::difference(DiffMatcher::AllMatcher.new(Fixnum), [1, 2, "3"]) [ : 1, : 2, - Fixnum+ "3" ] Where, - 1 missing, + 1 additional, : 2 match_class ``` When `actual` is an array with a *limited* size use an `AllMatcher` to match against *all* the elements in the array adhering to the limits of `:min` and or `:max` or `:size` (where `:size` is a Fixnum or range of Fixnum). ``` ruby puts DiffMatcher::difference(DiffMatcher::AllMatcher.new(Fixnum, :min=>3), [1, 2]) [ : 1, : 2, - Fixnum ] Where, - 1 missing, : 2 match_class ``` ``` ruby puts DiffMatcher::difference(DiffMatcher::AllMatcher.new(Fixnum, :size=>3..5), [1, 2]) [ : 1, : 2, - Fixnum ] Where, - 1 missing, : 2 match_class ``` When `actual` is an array of unknown size *and* `expected` can take multiple forms use a `Matcher` inside of an `AllMatcher` to match against *all* the elements in the array in any of the forms. ``` ruby puts DiffMatcher::difference( DiffMatcher::AllMatcher.new( DiffMatcher::Matcher[Fixnum, Float] ), [1, 2.00, "3"] ) [ | 1, | 2.0, - Float+ "3" ] Where, - 1 missing, + 1 additional, | 2 match_matcher ``` ### Options `:ignore_additional=>true` will match even if `actual` has additional items ``` ruby p DiffMatcher::difference([1], [1, 2], :ignore_additional=>true) # => nil ``` `:quiet=>true` shows only missing and additional items in the output ``` ruby puts DiffMatcher::difference([Fixnum, 2], [1], :quiet=>true) # => [ # => - 2 # => ] # => Where, - 1 missing ``` `:html_output=>true` will convert ansii escape codes to html spans ``` ruby puts DiffMatcher::difference(1, 2, :html_output=>true)
- 1+ 2 Where, - 1 missing, + 1 additional``` #### Prefixes The items shown in a difference are prefixed as follows: missing => "- " additional => "+ " match value => match regexp => "~ " match class => ": " match matcher => "| " match range => ". " match proc => "{ " #### Colours Colours (defined in colour schemes) can also appear in the difference. Using the `:default` colour scheme items shown in a difference are coloured as follows: missing => red additional => yellow match value => match regexp => green match class => blue match matcher => blue match range => cyan match proc => cyan Other colour schemes, eg. `:color_scheme=>:white_background` will use different colour mappings. Similar gems --- ### String differs *