Giter Club home page Giter Club logo

hashdiff's People

Contributors

cloakedcode avatar dduugg avatar eirc avatar grosser avatar jfelchner avatar keram avatar kevindew avatar koic avatar krzysiek1507 avatar liufengyun avatar lostapathy avatar m-o-e avatar marshall-lee avatar matpowel avatar nishidayuya avatar pboling avatar ronco avatar stephengroat avatar thbar avatar viraptor avatar y-yagi avatar zeropointenergy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hashdiff's Issues

Ruby 1.8.7 compatibility

The gemspec file indicates compatibility from ruby 1.8.7 while travis.yml sets up testing from ruby 1.9.3. If compatibility is supposed to be from ruby 1.8.7, then this line breaks that compatibility by using the ruby 1.9 hash syntax.

JSON data comparison failed when it has array of JSON data

xml_doc = Nokogiri::XML(response.body)
input_hash = Hash.from_xml(xml.to_s)
puts input_hash
puts "*" * 120
response_hash = Hash.from_xml(Nokogiri::XML(response.body).to_s)
puts response_hash.to_json

And I am sending input hash and response hash for diff = HashDiff.best_diffinput_hash, response_hash)

I am seeing that even there are elements present I could not get them compared

here I am giving input JSON and response JSON

JSON_1

{"requisition_header":{"requested_by":{"login":"coupasupport"},"department":{"name":"Marketing"},"pcard":null,"ship_to_address":{"name":"Address_1435124879"},"justification":null,"attachments":[],"requisition_lines":[{"item":{"name":"RISC Server with 4 CPU and 16Gb RAM"},"line_num":1,"need_by_date":"2010-09-23T07:00:00.000Z","account":{"code":"SF-Marketing-Indirect","account_type":{"name":"Ace Corporate"}}}]}}

JSON_2

{"requisition_header":{"id":5545,"created_at":"2015-06-24T05:48:19.000Z","updated_at":"2015-06-24T05:48:19.000Z","buyer_note":null,"justification":null,"need_by_date":null,"reject_reason_comment":null,"status":"draft","submitted_at":null,"exported":false,"ship_to_attention":"Coupa Support","total":"2049.0","mobile_total":"2049.0","custom_field_4":null,"custom_field_3":null,"zcust":null,"custom_field_1":null,"currency":{"id":1,"code":"USD","updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"department":{"id":1,"created_at":"2008-10-27T20:00:48.000Z","updated_at":"2015-05-15T12:35:14.000Z","name":"Marketing","active":true,"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"requested_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"ship_to_address":{"id":31420,"created_at":"2015-06-24T05:48:16.000Z","updated_at":"2015-06-24T05:48:16.000Z","name":"Address_1435124879","location_code":null,"street1":"2 W 5th Ave","street2":"Suite 300","city":"San Mateo","state":"CA","postal_code":"94404","attention":null,"active":true,"business_group_name":"Everyone","vat_number":null,"country":{"id":223,"code":"US","name":"United States"},"created_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"attachments":[],"requisition_lines":[{"id":8782,"created_at":"2015-06-24T05:48:19.000Z","updated_at":"2015-06-24T05:48:19.000Z","description":"RISC Server with 4 CPU and 16Gb RAM","line_num":1,"need_by_date":"2010-09-23T07:00:00.000Z","order_line_id":null,"receipt_required":null,"source_part_num":null,"status":null,"sub_line_num":null,"supp_aux_part_num":null,"total":"2049.0","source_type":"Catalog Item","line_type":"RequisitionAmountLine","unit_price":"2049.0","prepaid":null,"custom_field_5":null,"cf1":null,"custom_field_4":null,"user_1":null,"account":{"id":13,"created_at":"2008-10-27T20:20:36.000Z","updated_at":"2015-06-24T05:42:40.000Z","name":"San Francisco - Marketing, Indirect","code":"SF-Marketing-Indirect","active":true,"segment_1":"SF","segment_2":"Marketing","segment_3":"Indirect","segment_4":null,"segment_5":null,"segment_6":null,"segment_7":null,"segment_8":null,"segment_9":null,"segment_10":null,"segment_11":null,"segment_12":null,"segment_13":null,"segment_14":null,"segment_15":null,"segment_16":null,"segment_17":null,"segment_18":null,"segment_19":null,"segment_20":null,"account_type":{"id":1,"created_at":"2008-10-27T20:10:01.000Z","updated_at":"2015-06-18T08:06:26.000Z","name":"Ace Corporate","active":true,"currency":{"id":1,"code":"USD","updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"primary_contact":{"id":14,"created_at":"2008-10-27T20:10:01.000Z","updated_at":"2015-05-14T06:40:12.000Z","email":"[email protected]","name_prefix":null,"name_suffix":null,"name_additional":null,"name_given":"xxx","name_family":"yyy","name_fullname":null,"notes":null,"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"primary_address":{"id":31075,"created_at":"2008-10-27T20:10:01.000Z","updated_at":"2015-05-14T06:40:12.000Z","name":"test address name","location_code":null,"street1":"Line1","street2":"Line2","city":"City","state":"State","postal_code":"151515","attention":null,"active":true,"business_group_name":null,"vat_number":null,"country":{"id":22,"code":"BE","name":"Belgium"},"vat_country":{"id":22,"code":"BE","name":"Belgium"},"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"account_allocations":[],"item":{"id":230,"created_at":"2012-12-12T21:40:06.000Z","updated_at":"2015-06-24T05:44:30.000Z","description":"The minimum requirement for this bid is:A blade enclosure cost (to include all components for it to work).A server blade to the minimum specification: 2 x 72GB Hard Disk; 2 x 100mbps Ethernet ports.The server blade (preferable) or the blade enclosure must have a slot for either a 1GB Ethernet card with 2 ports or a fibre Channel (HBA) with 2 ports.The cost of the blade enclosure and server blade must include 1 years maintenance to the level indicated in the RFP.The optional cost for years 2 and 3 maintenance is to the level indicated in the RFP.The installation services cost must include, un-boxing of the product, complete installation to agreed standards, removal of boxes from site.","item_number":null,"name":"RISC Server with 4 CPU and 16Gb RAM","active":false,"storage_quantity":null,"consumption_quantity":null,"field":null,"commodity":{"id":10,"created_at":"2011-04-12T16:28:24.000Z","updated_at":"2011-04-12T21:58:19.000Z","active":true,"name":"Hardware","com_man":null,"custom_field_4":null,"custom_field_3":null,"gl_code":null,"acct":"Assets","parent":{"id":2,"created_at":"2008-10-27T20:04:00.000Z","updated_at":"2015-05-14T05:57:46.000Z","active":true,"name":"IT","com_man":null,"custom_field_4":null,"custom_field_3":null,"gl_code":null,"acct":"Indirect","created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"created_by":{"id":16,"login":"krhine","email":"[email protected]","employee_number":null,"firstname":"Kevin","lastname":"Rhine","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"uom":{"id":1,"created_at":null,"updated_at":"2015-06-18T08:06:27.000Z","code":"EA","name":"Each","allowable_precision":0,"active":true,"updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"reorder_alerts":[],"created_by":{"id":1,"login":"coupasupport","email":"[email protected]","employee_number":null,"firstname":"Coupa","lastname":"Support","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"currency":{"id":1,"code":"USD","updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"payment_term":{"id":1,"created_at":null,"updated_at":"2015-06-16T07:23:04.000Z","code":"Net 30","description":null,"days_for_net_payment":2,"days_for_discount_payment":null,"discount_rate":null,"active":true,"content_groups":[{"id":1,"created_at":"2006-08-28T02:40:04.000Z","updated_at":"2015-06-17T09:43:58.000Z","name":"Everyone","description":"All users can see documents assigned to this group","updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}}],"updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"shipping_term":{"id":1,"created_at":null,"updated_at":"2015-05-15T06:27:25.000Z","code":"Standard","description":null,"active":true,"content_groups":[{"id":1,"created_at":"2006-08-28T02:40:04.000Z","updated_at":"2015-06-17T09:43:58.000Z","name":"Everyone","description":"All users can see documents assigned to this group","updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}}],"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}},"asset_tags":[],"attachments":[],"created_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}}],"approvals":[],"created_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"updated_by":{"id":494,"login":"bhaskar","email":"[email protected]","employee_number":null,"firstname":"Bhaskar","lastname":"K","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null},"mobile_currency":{"id":1,"code":"USD","updated_by":{"id":1528,"login":"test","email":"[email protected]","employee_number":null,"firstname":"test","lastname":"key","salesforce_id":null,"custom_field_12":null,"custom_field_11":null,"date":null,"dropdown":null,"radio":null,"custom_field_8":null,"bussiness_unit":null,"purchase":null,"custom_field_3":null,"number_oksana":null,"gpo_entity":null}}}}

RESULT

-requisition_header.pcard
+requisition_header.requested_by.id1
+requisition_header.requested_by.emailupgrade+coupasupport@coupa.com
+requisition_header.requested_by.employee_number
+requisition_header.requested_by.firstnameCoupa
+requisition_header.requested_by.lastnameSupport
+requisition_header.requested_by.salesforce_id
+requisition_header.requested_by.custom_field_12
+requisition_header.requested_by.custom_field_11
+requisition_header.requested_by.date
+requisition_header.requested_by.dropdown
+requisition_header.requested_by.radio
+requisition_header.requested_by.custom_field_8
+requisition_header.requested_by.bussiness_unit
+requisition_header.requested_by.purchase
+requisition_header.requested_by.custom_field_3
+requisition_header.requested_by.number_oksana
+requisition_header.requested_by.gpo_entity
+requisition_header.department.id1
+requisition_header.department.created_at2008-10-27T20:00:48.000Z
+requisition_header.department.updated_at2015-05-15T12:35:14.000Z
+requisition_header.department.activetrue
+requisition_header.department.created_by{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
+requisition_header.department.updated_by{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
+requisition_header.ship_to_address.id31420
+requisition_header.ship_to_address.created_at2015-06-24T05:48:16.000Z
+requisition_header.ship_to_address.updated_at2015-06-24T05:48:16.000Z
+requisition_header.ship_to_address.location_code
+requisition_header.ship_to_address.street12 W 5th Ave
+requisition_header.ship_to_address.street2Suite 300
+requisition_header.ship_to_address.citySan Mateo
+requisition_header.ship_to_address.stateCA
+requisition_header.ship_to_address.postal_code94404
+requisition_header.ship_to_address.attention
+requisition_header.ship_to_address.activetrue
+requisition_header.ship_to_address.business_group_nameEveryone
+requisition_header.ship_to_address.vat_number
+requisition_header.ship_to_address.country{"id"=>223, "code"=>"US", "name"=>"United States"}
+requisition_header.ship_to_address.created_by{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
+requisition_header.ship_to_address.updated_by{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
-requisition_header.requisition_lines[0]{"item"=>{"name"=>"RISC Server with 4 CPU and 16Gb RAM"}, "line_num"=>1, "need_by_date"=>"2010-09-23T07:00:00.000Z", "account"=>{"code"=>"SF-Marketing-Indirect", "account_type"=>{"name"=>"Ace Corporate"}}}
+requisition_header.requisition_lines[0]{"id"=>8782, "created_at"=>"2015-06-24T05:48:19.000Z", "updated_at"=>"2015-06-24T05:48:19.000Z", "description"=>"RISC Server with 4 CPU and 16Gb RAM", "line_num"=>1, "need_by_date"=>"2010-09-23T07:00:00.000Z", "order_line_id"=>nil, "receipt_required"=>nil, "source_part_num"=>nil, "status"=>nil, "sub_line_num"=>nil, "supp_aux_part_num"=>nil, "total"=>"2049.0", "source_type"=>"Catalog Item", "line_type"=>"RequisitionAmountLine", "unit_price"=>"2049.0", "prepaid"=>nil, "custom_field_5"=>nil, "cf1"=>nil, "custom_field_4"=>nil, "user_1"=>nil, "account"=>{"id"=>13, "created_at"=>"2008-10-27T20:20:36.000Z", "updated_at"=>"2015-06-24T05:42:40.000Z", "name"=>"San Francisco - Marketing, Indirect", "code"=>"SF-Marketing-Indirect", "active"=>true, "segment_1"=>"SF", "segment_2"=>"Marketing", "segment_3"=>"Indirect", "segment_4"=>nil, "segment_5"=>nil, "segment_6"=>nil, "segment_7"=>nil, "segment_8"=>nil, "segment_9"=>nil, "segment_10"=>nil, "segment_11"=>nil, "segment_12"=>nil, "segment_13"=>nil, "segment_14"=>nil, "segment_15"=>nil, "segment_16"=>nil, "segment_17"=>nil, "segment_18"=>nil, "segment_19"=>nil, "segment_20"=>nil, "account_type"=>{"id"=>1, "created_at"=>"2008-10-27T20:10:01.000Z", "updated_at"=>"2015-06-18T08:06:26.000Z", "name"=>"Ace Corporate", "active"=>true, "currency"=>{"id"=>1, "code"=>"USD", "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "primary_contact"=>{"id"=>14, "created_at"=>"2008-10-27T20:10:01.000Z", "updated_at"=>"2015-05-14T06:40:12.000Z", "email"=>"[email protected]", "name_prefix"=>nil, "name_suffix"=>nil, "name_additional"=>nil, "name_given"=>"xxx", "name_family"=>"yyy", "name_fullname"=>nil, "notes"=>nil, "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "primary_address"=>{"id"=>31075, "created_at"=>"2008-10-27T20:10:01.000Z", "updated_at"=>"2015-05-14T06:40:12.000Z", "name"=>"test address name", "location_code"=>nil, "street1"=>"Line1", "street2"=>"Line2", "city"=>"City", "state"=>"State", "postal_code"=>"151515", "attention"=>nil, "active"=>true, "business_group_name"=>nil, "vat_number"=>nil, "country"=>{"id"=>22, "code"=>"BE", "name"=>"Belgium"}, "vat_country"=>{"id"=>22, "code"=>"BE", "name"=>"Belgium"}, "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "account_allocations"=>[], "item"=>{"id"=>230, "created_at"=>"2012-12-12T21:40:06.000Z", "updated_at"=>"2015-06-24T05:44:30.000Z", "description"=>"The minimum requirement for this bid is:A blade enclosure cost (to include all components for it to work).A server blade to the minimum specification: 2 x 72GB Hard Disk; 2 x 100mbps Ethernet ports.The server blade (preferable) or the blade enclosure must have a slot for either a 1GB Ethernet card with 2 ports or a fibre Channel (HBA) with 2 ports.The cost of the blade enclosure and server blade must include 1 years maintenance to the level indicated in the RFP.The optional cost for years 2 and 3 maintenance is to the level indicated in the RFP.The installation services cost must include, un-boxing of the product, complete installation to agreed standards, removal of boxes from site.", "item_number"=>nil, "name"=>"RISC Server with 4 CPU and 16Gb RAM", "active"=>false, "storage_quantity"=>nil, "consumption_quantity"=>nil, "field"=>nil, "commodity"=>{"id"=>10, "created_at"=>"2011-04-12T16:28:24.000Z", "updated_at"=>"2011-04-12T21:58:19.000Z", "active"=>true, "name"=>"Hardware", "com_man"=>nil, "custom_field_4"=>nil, "custom_field_3"=>nil, "gl_code"=>nil, "acct"=>"Assets", "parent"=>{"id"=>2, "created_at"=>"2008-10-27T20:04:00.000Z", "updated_at"=>"2015-05-14T05:57:46.000Z", "active"=>true, "name"=>"IT", "com_man"=>nil, "custom_field_4"=>nil, "custom_field_3"=>nil, "gl_code"=>nil, "acct"=>"Indirect", "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "created_by"=>{"id"=>16, "login"=>"krhine", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Kevin", "lastname"=>"Rhine", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "uom"=>{"id"=>1, "created_at"=>nil, "updated_at"=>"2015-06-18T08:06:27.000Z", "code"=>"EA", "name"=>"Each", "allowable_precision"=>0, "active"=>true, "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "reorder_alerts"=>[], "created_by"=>{"id"=>1, "login"=>"coupasupport", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Coupa", "lastname"=>"Support", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "currency"=>{"id"=>1, "code"=>"USD", "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "payment_term"=>{"id"=>1, "created_at"=>nil, "updated_at"=>"2015-06-16T07:23:04.000Z", "code"=>"Net 30", "description"=>nil, "days_for_net_payment"=>2, "days_for_discount_payment"=>nil, "discount_rate"=>nil, "active"=>true, "content_groups"=>[{"id"=>1, "created_at"=>"2006-08-28T02:40:04.000Z", "updated_at"=>"2015-06-17T09:43:58.000Z", "name"=>"Everyone", "description"=>"All users can see documents assigned to this group", "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}], "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "shipping_term"=>{"id"=>1, "created_at"=>nil, "updated_at"=>"2015-05-15T06:27:25.000Z", "code"=>"Standard", "description"=>nil, "active"=>true, "content_groups"=>[{"id"=>1, "created_at"=>"2006-08-28T02:40:04.000Z", "updated_at"=>"2015-06-17T09:43:58.000Z", "name"=>"Everyone", "description"=>"All users can see documents assigned to this group", "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}], "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}, "asset_tags"=>[], "attachments"=>[], "created_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}, "updated_by"=>{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}
+requisition_header.id5545
+requisition_header.created_at2015-06-24T05:48:19.000Z
+requisition_header.updated_at2015-06-24T05:48:19.000Z
+requisition_header.buyer_note
+requisition_header.need_by_date
+requisition_header.reject_reason_comment
+requisition_header.statusdraft
+requisition_header.submitted_at
+requisition_header.exportedfalse
+requisition_header.ship_to_attentionCoupa Support
+requisition_header.total2049.0
+requisition_header.mobile_total2049.0
+requisition_header.custom_field_4
+requisition_header.custom_field_3
+requisition_header.zcust
+requisition_header.custom_field_1
+requisition_header.currency{"id"=>1, "code"=>"USD", "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}
+requisition_header.approvals[]
+requisition_header.created_by{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
+requisition_header.updated_by{"id"=>494, "login"=>"bhaskar", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"Bhaskar", "lastname"=>"K", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}
+requisition_header.mobile_currency{"id"=>1, "code"=>"USD", "updated_by"=>{"id"=>1528, "login"=>"test", "email"=>"[email protected]", "employee_number"=>nil, "firstname"=>"test", "lastname"=>"key", "salesforce_id"=>nil, "custom_field_12"=>nil, "custom_field_11"=>nil, "date"=>nil, "dropdown"=>nil, "radio"=>nil, "custom_field_8"=>nil, "bussiness_unit"=>nil, "purchase"=>nil, "custom_field_3"=>nil, "number_oksana"=>nil, "gpo_entity"=>nil}}

Note:
-requisition_header.requisition_lines[0]
present in both input and output JSON but not compared..
Please revert me with solution asap.

Thanks,
Bhaskar

Unexpected diff in case of arrays?

As you can see in the code snippet below, there is difference in the diff even if the similarity value is changed from 0.0 to 0.000000001. And the result obtained using similarity: 0.0 seems unexpected.

hash1 = { a: "a", b_arr: [ { name: "b1" }, { name: "b2" } ] }
hash2 = { a: "a", b_arr: [ { name: "b1" } ] }

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.0)
 => [["~", "b_arr[0].name", "b1", "b2"], ["+", "b_arr[0]", {:name=>"b1"}]]

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.1)
 => [["+", "b_arr[1]", {:name=>"b2"}]] 

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.01)
 => [["+", "b_arr[1]", {:name=>"b2"}]] 

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.001)
 => [["+", "b_arr[1]", {:name=>"b2"}]] 

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.0001)
 => [["+", "b_arr[1]", {:name=>"b2"}]] 

diff1 = HashDiff.diff(hash2, hash1, similarity: 0.000000001)
 => [["+", "b_arr[1]", {:name=>"b2"}]]

Getting (+-) instead of diff (tilde) when comparing arrays

Hello. I find the following behavior (using Hashdiff 1.0.1) somewhat unexpected:

Hashdiff.diff(%w[a b c], %w[a b d])
=> [["-", "[2]", "c"], ["+", "[2]", "d"]]

Would not it be better to get

Hashdiff.diff(%w[a b c], %w[a b d])
=> [["~", "[2]", "c", "d"]]

?

Is there an option to get this behavior ?

Thanks for reading!

Custom similar? method

I'm not sure if I understand properly your code, but I feel it would be great to allow to define custom similar? method.

And that's my use case: I have an array of serialized Rails models. In this case similar? should use object's ids rather than comparing their content.

before = [{id: 1, name: "Peter"}, {id: 2, name: "John"}]
after = [{id: 2, name: "Peter"}, {id: 3, name: "Ann"}]

# current behavior
HashDiff.diff(before, after, similarity: 0.5)
# [
#   ["~", "[0].id", 1, 2], ["-", "[1]", {:id=>2, :name=>"John"}],
#   ["+", "[1]", {:id=>3, :name=>"Ann"}]
# ] 

# my proposition
HashDiff.diff(before, after, similar: -> (a, b, options) { a[:id] === b[:id] })
# [
#   ["~", "[1].name", "John", "Peter"],
#   ["-", "[0]", {:id=>1, :name=>"Peter"}],
#   ["+", "[1]", {:id=>3, :name=>"Ann"}]
# ] 

Of course I can get the same results by modifying HashDiff.similar? method (which I did), but it would be nice if I could do the same thing locally – just like custom comparison method.

It's just an idea, maybe a bad one, since I don't really understand this whole similarity mechanism. 😄 Thank you for this gem, it's elegant and very useful!

HashDiff.diff(a,b) returns array, not object with method should()

Hi there,

I'm a bit confused. I'm following the QuickStart, which says to compare in the following way (eg.):

diff = HashDiff.diff(a, b)
diff.should == [['-', 'a', 3], ['-', 'b', 2]]

However, variable diff is set to a standard array type and does not have a method 'should'. Am I missing something? Or did the specs change in the meantime?

I'm using ruby v 1.9.2. My intention is two compare two complex hash to see if they're identical. So in the code above, I just want to check if diff.should == [].

Thanks,

Wim.

Please stop the `warn` spam

now every test run/boot has a warning :(
Just remove the constant and be done with it ... or do whatever activesupport does but only when a deprecated constant is used

caused by #65

Support :case_insensitive diff-ing option

Similar to :strip and :numeric_tolerance I think it would be useful to have an option to make string comparisons case insensitive. I'm happy to provide a PR if there would be interest in adding this feature.

Please document the determinism of HashDiff.diff and friends

So looking at compare_hashes.rb there's some sorting to make sure the results are stable and deterministic independent of the ordering of the keys. Is that true for all of the diff functions? If so it would be helpful to document this (either way) so that users of the library know if they need to sort results if they need stability (for unit tests, etc)

Issues with diff

Tried with 1.0.0 release and below is against master branch:

script

require 'awesome_print'
require 'hashdiff'
a = {"order"=>1, "index_patterns"=>["logstash-cloudtrail*"], "settings"=>{"index"=>{"lifecycle"=>{"name"=>"logging_policy", "rollover_alias"=>"logstash-cloudtrail-write"}, "routing"=>{"allocation"=>{"require"=>{"node_type"=>"hot"}}}, "mapping"=>{"total_fields"=>{"limit"=>8000}, "ignore_malformed"=>"true"}, "refresh_interval"=>"30s", "number_of_shards"=>2, "merge"=>{"scheduler"=>{"max_thread_count"=>1}}, "number_of_replicas"=>2}}, "mappings"=>{"_doc"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "mapping"=>{"norms"=>false, "type"=>"text"}, "match_mapping_type"=>"string"}}, {"string_fields"=>{"mapping"=>{"norms"=>false, "type"=>"text", "fields"=>{"keyword"=>{"ignore_above"=>256, "type"=>"keyword"}}}, "match_mapping_type"=>"string", "match"=>"*"}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}}}}, "aliases"=>{"all_logs"=>{}}}

b = {"order"=>1, "aliases"=>{"all_logs"=>{}}, "mappings"=>{"_doc"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"norms"=>false, "type"=>"text"}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}}}}, "index_patterns"=>["logstash-cloudtrail*"], "settings"=>{"index"=>{"mapping.total_fields.limit"=>8000, "mapping.ignore_malformed"=>true, "routing.allocation.require.node_type"=>"hot", "refresh_interval"=>"30s", "merge.scheduler.max_thread_count"=>1, "number_of_replicas"=>2, "number_of_shards"=>2, "lifecycle.rollover_alias"=>"logstash-cloudtrail-write", "lifecycle.name"=>"logging_policy"}}}
ap Hashdiff.diff(a,b)

result

[
  [0] [
    [0] "-",
    [1] "settings.index.lifecycle",
    [2] {
                "name" => "logging_policy",
      "rollover_alias" => "logstash-cloudtrail-write"
    }
  ],
  [1] [
    [0] "-",
    [1] "settings.index.mapping",
    [2] {
      "ignore_malformed" => "true",
          "total_fields" => {
        "limit" => 8000
      }
    }
  ],
  [2] [
    [0] "-",
    [1] "settings.index.merge",
    [2] {
      "scheduler" => {
        "max_thread_count" => 1
      }
    }
  ],
  [3] [
    [0] "-",
    [1] "settings.index.routing",
    [2] {
      "allocation" => {
        "require" => {
          "node_type" => "hot"
        }
      }
    }
  ],
  [4] [
    [0] "+",
    [1] "settings.index.lifecycle.name",
    [2] "logging_policy"
  ],
  [5] [
    [0] "+",
    [1] "settings.index.lifecycle.rollover_alias",
    [2] "logstash-cloudtrail-write"
  ],
  [6] [
    [0] "+",
    [1] "settings.index.mapping.ignore_malformed",
    [2] true
  ],
  [7] [
    [0] "+",
    [1] "settings.index.mapping.total_fields.limit",
    [2] 8000
  ],
  [8] [
    [0] "+",
    [1] "settings.index.merge.scheduler.max_thread_count",
    [2] 1
  ],
  [9] [
    [0] "+",
    [1] "settings.index.routing.allocation.require.node_type",
    [2] "hot"
  ]
]

If you look at the source the true is already a Boolean so not sure why the diff for ignore_malformed shows a "true" to true.
The rest of the diff appears to be exactly the same so not sure why this is causing a diff.

Patch problem whit symbol as key

From Readme

require 'hashdiff'          #=> true
a = {a: 3}                  #=> {:a=>3}
b = {a: {a1: 1, a2: 2}}     #=> {:a=>{:a1=>1, :a2=>2}}
diff = HashDiff.diff(a, b)  #=> [["~", "a", 3, {:a1=>1, :a2=>2}]]

HashDiff.patch!(a, diff)   #=> {:a=>3, "a"=>{:a1=>1, :a2=>2}}

rspec files check only string keys

[Feature request] :ignore_keys option

I have a use-case where I often need to compare 2 hashes where I don't care about the values of particular keys. For example ones which contain timestamps, or the following example which contain a 'duration' key (representing milliseconds):

h1 = 
{
  "fonts": {
    "value": [],
    "duration": 93
  },
  "domBlockers": {
    "duration": 0
  },
  "fontPreferences": {
    "value": {
      "default": 146,
      "apple": 146,
      "serif": 146,
      "sans": 144,
      "mono": 119,
      "min": 10,
      "system": 144
    },
    "duration": 117
  },
# ...
}

h2 = 
{
  "fonts": {
    "value": [],
    "duration": 78
  },
  "domBlockers": {
    "duration": 0
  },
  "fontPreferences": {
    "value": {
      "default": 146,
      "apple": 146,
      "serif": 146,
      "sans": 144,
      "mono": 119,
      "min": 10,
      "system": 146
    },
    "duration": 134
  },
# ...
}

I can ignore differences in the 'duration' values with a block:

diff = Hashdiff.diff(h1, h2) { |path, _e, _a| true if path.split('.').last == 'duration' }
#=> [['~', 'fontPreferences.value.system', 144, 146]]

But I'd love to be able to write something like this, where :ignore_keys can take a single value or array of keys to ignore:

diff  = Hashdiff.diff(h1, h2, ignore_keys: 'duration')

The logic would be the same as above, i.e. ignored keys would have to be at the end of each path. My guess is this may be a common enough use-case that a shorthand option like this would be valuable to users.

I might have a stab at a PR if you like the idea. Awesome library btw.

Compare objects inheriting from the same class

BetterHash = Class.new Hash
EvenBetterHash = Class.new Hash

HashDiff.diff(BetterHash.new, EvenBetterHash.new)
=> [["~", "", {}, {}]]

HashDiff.diff({}, BetterHash.new)
=> []

HashDiff.diff(BetterHash.new, {})
=> [["~", "", {}, {}]]

I wonder when we can compare two objects. When they inherit from the same class or they have to be instances of the same class?

Conflicts with `hash_diff`

Note: If you've upgraded hashdiff, made sure that you've upgraded your references, and want to silence the warnings, you can manually opt-in to the 1.0 beta by following the instructions here

The name of this gem is hashdiff. There is another gem named hash_diff. When they are both required via dependencies, errors are thrown. Additionally since the behavior is different, gems that are relying on hashdiff's behavior, may get hash_diff's behavior and vice versa.

The reason for the conflict is because, based on ruby conventions, _'s are the separators for camel case.

So:

'hashdiff'.camelize # => "Hashdiff"

'hash_diff'.camelize # => "HashDiff"

Unfortunately instead of making the base module of this gem Hashdiff, it's called HashDiff and it conflicts.

Time vs String non-strict comparison

I have 2 hashes, both with a "created_at" attribute, they are the same, however, that's the behavior I get from the gem when I try to compare both:

[1] > new[:created_at]
=> "2017-08-28T12:12:22.760Z"
[2] > current[:created_at]
=> "2017-08-28T12:12:22.760Z"
[3] > current[:created_at] == new[:created_at]
=> true
[4] > HashDiff.diff(new, current)
=> [["~", "created_at", "2017-08-28T12:12:22.760Z", "2017-08-28T12:12:22.760Z"]]

Update - 29/08

The timestamps are serialized the same way, but one is a string and the other is a time.

Eitherway, if the comparinson is not strict we should declare as equal.

HashDiff never finishes when comparing two arrays

Hi,

When debugging an issue with octocatalog-diff we narrowed down the problem to HashDiff unable to compare a couple of arrays when LCS is used. Here's a reproducer:

require 'hashdiff'

a = {x: []}
(0...17000).each{ |x|
        a[:x].push((0...11).map { ('a'..'z').to_a[rand(26)] }.push('.example.org').join)
        }

b = {x: a[:x]}
 
puts "Without LCS"
diff = HashDiff.diff(a, b, :use_lcs => false)
puts diff
puts "Done!"
puts "With LCS"
diff = HashDiff.diff(a, b)
puts diff
puts "This should never be printed"

When comparing those two arrays using LCS (which is on by default) the application starts to eat up memory very quickly with 100% CPU usage until, in our case, the process is killed by the kernel's OOM killer as the test machine does not have any swap:

$ ruby reproducer_synth.rb 
Without LCS
Done!
With LCS
...
Killed
kernel: Out of memory: Kill process 18783 (ruby) score 526 or sacrifice child
kernel: Killed process 18783 (ruby) total-vm:1192540kB, anon-rss:1013324kB, file-rss:0kB, shmem-rss:0kB

Yes, that's >1GiB!

# ruby --version
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
# gem list hashdiff

*** LOCAL GEMS ***

hashdiff (0.3.8)
# 

I understand that LCS is O(n2) but not sure this is the expected behaviour as the array size is moderate.

Unexpected results

a = {a:'car', b:['truck', 'plane'] }
b = {a:'bus', b:['truck', ' plan'] }

diff = HashDiff.diff(a, b) do |path, obj1, obj2|
  case path
  when 'b[*]'
    true
  end
end
=> [["~", "a", "car", "bus"], ["-", "b[1]", "plane"], ["+", "b[1]", " plan"]]

vs.

a = {a:'car', b:['truck', 'plane'] }
b = {a:'bus', b:['truck', ' plan'] }

diff = HashDiff.diff(a, b) do |path, obj1, obj2|
  case path
  when 'b[*]'
    false
  end
end
=> [["~", "a", "car", "bus"], ["-", "b[1]", "plane"], ["+", "b[1]", " plan"]]

vs.

a = {a:'car', b:['truck', 'plane'] }
b = {a:'bus', b:['truck', ' plan'] }

diff = HashDiff.diff(a, b) do |path, obj1, obj2|
  case path
  when 'b[*]'
    raise "#{obj1} == #{obj2}"
  end
end
=> [["~", "a", "car", "bus"], ["-", "b[1]", "plane"], ["+", "b[1]", " plan"]]

It doesn't seem to make any difference what goes in the block as a custom comparator.

Also, when I do a puts inside the block to try and figure out what is going on there is no output?!

The raise is silently rescued?!

Gem hashdiff-0.2.1 is not ruby 1.8.7 compatible

please change similarity: to :similarity =>
and prefix: to :prefix =>

/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': /usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:30: odd number list for Hash (SyntaxError)
    opts = {similarity: 0.3}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:30: syntax error, unexpected ':', expecting '}'
    opts = {similarity: 0.3}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:34: odd number list for Hash
    opts = {similarity: 0.5}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:34: syntax error, unexpected ':', expecting '}'
    opts = {similarity: 0.5}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:38: odd number list for Hash
    opts = {similarity: 0.8}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:38: syntax error, unexpected ':', expecting '}'
    opts = {similarity: 0.8}.merge!(options)
                       ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:107: syntax error, unexpected ':', expecting ')'
...2[pair[1]], opts.merge(prefix: "#{opts[:prefix]}[#{pair[0]}]...
                              ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:107: syntax error, unexpected ')', expecting kEND
...#{opts[:prefix]}[#{pair[0]}]")))
                              ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:118: syntax error, unexpected kELSIF, expecting kEND
    elsif obj1.is_a?(Hash)
         ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:148: syntax error, unexpected ':', expecting ')'
...], obj2[k], opts.merge(prefix: "#{prefix}#{k}"))) }
                              ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:148: syntax error, unexpected ')', expecting '}'
...merge(prefix: "#{prefix}#{k}"))) }
                              ^
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:162: syntax error, unexpected kELSE, expecting '}'
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:165: syntax error, unexpected kEND, expecting '}'
/usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff/diff.rb:227: syntax error, unexpected kEND, expecting '}'
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
    from /usr/lib/ruby/gems/1.8/gems/hashdiff-0.2.1/lib/hashdiff.rb:3
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require'
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
    from ./shema_diff.rb:6

sort array inside hash automatically

I find this library to be extremely useful, however its missing a usecase that i badly need.

As you mentioned in the documentation, if we have array inside hash, it will need to be sorted before we can compare, else it will show them as diff.

Can we please add a option to sort arrays before comparing them? is there any specific reason why its not provided?

Thanks
Rajat JIndal

==/equal? overrides not used when checking keys

Hello,
The override of the ==/equal? methods seem to be used when checking values of an Hash, but not when checking the keys. Here is an example with a simple class :

class Color
  attr_reader :value

  def initialize(value)
    @value = value
  end

  def equal?(other)
    return false unless other.is_a?(Color)

    @value == other.value
  end

  def ==(other)
    return false unless other.is_a?(Color)

    @value == other.value
  end
end

Hashdiff.best_diff({1 => Color.new('red')}, {1 => Color.new('red')}) returns [] as expected
but
Hashdiff.best_diff({Color.new('red') => 1}, {Color.new('red') => 1}) returns [["~", "#<Color:0x000014ac0e49d418>", 1, nil]]

Thanks!

Can’t silence HashDiff constant warning

Thanks to the warning from #65, I am now aware of the HashDiff/Hashdiff conflict. I have updated my code to use the correct Hashdiff constant.

Now that I’ve done the work to fix the issue, how do I turn the warning off?

RexEx in compares?

It would be great if there where a way to use RegEx to ignore certain nodes.
I am using this to compare the results of an API call, and need it to ignore the guid and dates

Unexpected diff?

Very useful gem. However, in my case the hash is really nested with arrays and hashes inside.

hash1 = {
  a: "a1",
  b: {
    b1: "b1",
    b2: "b2",
    b3: "b2"
  },
  c: [
    {
      c1: "c1",
      c2: [
        {
          c21: "c21",
          c22: "c22",
          c23: "c23"
        }
      ]
    }
  ]
}

hash2 = {
  a: "a1",
  b: {
    b1: "b1",
    b2: "b2",
    b3: "b2"
  },
  c: [
    {
      c1: "c1",
      c2: [
        {
          c21: "c21",
          c22: "c222",
          c23: "c23"
        }
      ]
    }
  ]
}

diff = HashDiff.diff(hash1, hash2)
 => [["-", "c[0]", {:c1=>"c1", :c2=>[{:c21=>"c21", :c22=>"c22", :c23=>"c23"}]}], ["+", "c[0]", {:c1=>"c1", :c2=>[{:c21=>"c21", :c22=>"c222", :c23=>"c23"}]}]]

make use_lcs: false the default

diffing anything that has nested arrays is ugly when using lcs ... and on top of that it is slow
how about making the linear solver the default ?

before:

  -graphs[1]
    {:definition=>{:viz=>"timeseries", :requests=>[{:q=>"sum:docker.mem.rss{kube_project:gcb-vulnerability-logger} by {kube_namespace}", :conditional_formats=>[], :type=>"area"}], :autoscale=>true}, :title=>"Memory"} ->
    nil
  +graphs[1]
    nil ->
    {:title=>"Memory", :definition=>{:viz=>"timeseries", :requests=>[{:q=>"sum:docker.mem.rss{kube_project:gcb-vulnerability-logger,$environment} by {kube_namespace}", :type=>"area", :conditional_formats=>[]}], :autoscale=>true}}

after:

  ~graphs[1].definition.requests[0].q
    "sum:docker.mem.rss{kube_project:gcb-vulnerability-logger} by {kube_namespace}" ->
    "sum:docker.mem.rss{kube_project:gcb-vulnerability-logger,$environment} by {kube_namespace}"

@liufengyun

ArgumentError with heterogenous keys

I encountered an ArgumentError while comparing hashes which has keys of mixed string and symbols. While this practice is without doubt questionable, I do expect HashDiff to be able to handle this gracefully.

The following small example shows this:

require 'hashdiff'
a = { "c" => "testing", :b => "one two" }
b = { :a => "testing", "b" => "three four" }
HashDiff.diff a, b

Results in:

ArgumentError: comparison of String with :b failed
        from /home/user/.rvm/gems/ruby-2.1.5/gems/hashdiff-0.3.0/lib/hashdiff/diff.rb:130:in `sort'
        from /home/user/.rvm/gems/ruby-2.1.5/gems/hashdiff-0.3.0/lib/hashdiff/diff.rb:130:in `diff'
        from (irb):14
        from /home/user/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'

This occurs in method self.diff in file diff.rb, and can happen at the places where key arrays are sorted, e.g.:

deleted_keys.sort.each do |k|
...
added_keys.sort.each do |k|

The best solution I can think of, is to replace the default sort with something that can handle any type, as long as that type implements to_s:

deleted_keys.sort {|x,y| x.to_s <=> y.to_s}.each do |k|
...
end

This works but is ugly, it could use some refactoring. The weak part of this solution is that it depends on the presence of method to_s to work. But this at least is a step toward a more generic usage.

"use_lcs: false" does not work as expected as per documentation

In documentation it stated use_lcs: false should behave like below:

a = {x: [0, 1, 2]}
b = {x: [0, 2, 2, 3]}

diff = HashDiff.diff(a, b, :use_lcs => false)
diff.should == [["~", "x[1]", 1, 2], ["+", "x[3]", 3]]

But it got below instead for diff

[["-", "x[1]", 1], ["+", "x[1]", 2], ["+", "x[3]", 3]]

Showing same count as `=`

Hello,

Actually Hashdiff can show +, - and ~.
Is it possible to also show same counts in the diff as = ?

example output:

['-', 'b', 2], ['+', 'a', 4], ['=', 'c', 3, 3], ['~', 'd', 3, 8] 

Thanks.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

Unexpected difference between diffs of hashes vs. arrays

I have inputs

a = [1, 2, 3]
b = [1, 10, 3]

and expect a diff of

[["~", "[1]", 2, 10 ]]

but instead I get

[["-", "[1]", 2], ["+", "[1]", 10]]

I expect that because of how hash comparisons work

a = {a:1, b:2, c:3}
b = {a:1, b:10, c:3}
[["~", "b", 2, 10]]

and

a = [1, {a: 0, b: 1}, 3]
b = [1, {a: 0, b: 2}, 3]
[["~", "[1].b", 1, 2]]

Is it possible to get the results I expect?

ignore_keys ignores only common keys

require 'hashdiff'
Hashdiff::VERSION
#=> "1.1.0"

The following snippet fails to ignore top level key :a

a = { a: 4, b: {a: 5, c: 6} }
b = {       b: {a: 7, c: 3} }

diff = Hashdiff.diff(a, b, ignore_keys: :a)
#=> [["-", "a", 4], ["~", "b.c", 6, 3]]

Shouldn't diff be expected to be the below?

[["~", "b.c", 6, 3]]

The documentation on ignore_keys states that:

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.

Here line where :ignore_keys happens (in Hashdiff::ComparableHashes::call):

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

added_keys and deleted_keys don't seem to have the exclusion applied.

Is there anyway that we can get the index of changed values only ?

Thanks for great plugin, I find it's incredibly useful in my current project. I don't know if there is any internal API that I can get the index of changed diff items only ?
For example :
instead of showing this :

[["-", "[2]", {:kills=>3, :deaths=>3}], ["-", "[1]", {:kills=>4, :deaths=>3}], ["-", "[0]", {:kills=>8, :deaths=>5}], ["-", "[1]", {:kills=>1, :deaths=>4}], ["+", "[1]", {:kills=>3, :deaths=>1}], ["+", "[2]", {:kills=>2, :deaths=>1}], ["+", "[3]", {:kills=>0, :deaths=>2}], ["+", "[4]", {:kills=>4, :deaths=>2}]]

I just want to get this :

[1,2,3,4]

Custom comparison broken since 0.3.4?

Hello there.

I've been using your gem to compare large hashes of arrays with a custom comparison method and it's been working great so far.

After upgrading to 0.3.4, custom comparison seems to be broken. If you test your own example from the README:

a = {a:'car', b:['boat', 'plane'] }
b = {a:'bus', b:['truck', ' plan'] }

diff = HashDiff.diff(a, b) do |path, obj1, obj2|
  case path
  when 'b[*]'
    obj1.length == obj2.length
  end
end

diff.should == [["~", "a", "car", "bus"], ["~", "b[1]", "plane", " plan"], ["-", "b[0]", "boat"], ["+", "b[0]", "truck"]]

you'll get a different output:

diff
#=> [["~", "a", "car", "bus"], ["-", "b[1]", "plane"], ["-", "b[0]", "boat"], ["+", "b[0]", "truck"], ["+", "b[1]", " plan"]]

Has the API for custom comparison changed in the meantime and the docs are outdated, or is this a bug?

Thanks for the great work so far :-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.