views:

550

answers:

3

Hi

I have two ruby hashes (which are essentially models) and am trying to find the differences between them, one is an old instance of an object where the other has new values assigned to some attributes. I'm trying to determine which keys have changed, but there doesn't seem to be anything built into the Hash for this. I can think of a few brute forceish solutions, but was wondering if there is perhaps an elegant solution out there.

Ideally I need to be able to take two hashs like so:

element1 = {:name => "Original", :description => "The original one!"}
element2 = {:name => "Original", :description => "The new one!"}

And be able to compare/diff them and get something back like this:

{:description => "The new one!"}

Right now all I can really think of is iterating through the keys in one hash and comparing the value at that key to the corresponding key in the second hash, but that seems too brute forced.

Any ideas? Thanks a lot!

+5  A: 

So I apparently should've just checked the rails source, rails has a nice little hash.diff method that can be easily ported into Ruby

fluid_chelsea
+2  A: 

I have found Rails' Hash diff method to not actually tell me what was on the left side and right side (which is far more useful). There was a plugin call "Riff", that has since disappeared, which would let you diff two ActiveRecord objects. Essentially:

class Hash
  def diff(other)
    self.keys.inject({}) do |memo, key|
      unless self[key] == other[key]
        memo[key] = [self[key], other[key]] 
      end
      memo
    end
  end
end
Colin Curtin
For my purpose I don't especially care since I really just need to know which fields have changed. If I were using AR this wouldn't be an issue, but everything is being abstracted through a data layer to CouchDB so I find myself needing to reinvent the wheel, so to speak, for some functionality.Thanks for the suggestion though.
fluid_chelsea
Which of course corresponds to your "brute force" comment, but I feel it's useful and not so awful or inelegant.
Colin Curtin
+1  A: 

If all you care about is what's unique in element2, you can just do:

element2.to_a - element1.to_a
glenn mcdonald