views:

246

answers:

3

Helo,

I am pretty new to Ruby (using 1.8.6) and need to know whether the following functionality is available automatically and if not, which would be the best method to implement it.

I have class Car. And have two objects:

car_a and car_b

Is there any way I could do a compare and find what properties differ in one of the objects as compared to the other one?

For example,

car_a.color = 'Red'
car_a.sun_roof = true
car_a.wheels = 'Bridgestone'

car_b.color = 'Blue'
car_b.sun_roof = false
car_b.wheels = 'Bridgestone'

then doing a

car_a.compare_with(car_b)

should give me:

{:color => 'Blue', :sun_roof => 'false'}

or something to that effect?

A: 

Not sure if getting the difference of properties straight away is possible. But the work around would be to try the .eql? operator on both the objects

#for example, 

car_a.eql?(car_b)

#could test whether car_a and car_b have the same color, sunroof and wheels
#need to override this method in the Car class to be meaningful,otherwise it's the same as ==

If there is a difference then you could use the Object Class's To_Array method like

car_a.to_a
car_b.to_a

now comparing 2 arrays for difference would be easy.

Not tested but

(car_a | car_b ) - ( car_a & car_b )

or something like that should give you the difference in properties.

HTH

Anand
Class#to_a doesn't do what you want at all. It basically returns an array containing the receiver (i.e. String.to_a==[String]).
Ken Bloom
+1  A: 

needs some tweaking, but here's the basic idea:

module CompareIV
  def compare(other)
    h = {}
    self.instance_variables.each do |iv|
      print iv
      a, b = self.instance_variable_get(iv), other.instance_variable_get(iv)
      h[iv] = b if a != b
    end
    return h
  end
end

class A
  include CompareIV
  attr_accessor :foo, :bar, :baz

  def initialize(foo, bar, baz)
    @foo = foo
    @bar = bar
    @baz = baz
  end
end

a = A.new(foo = 1, bar = 2, baz = 3)
b = A.new(foo = 1, bar = 3, baz = 4)

p a.compare(b)
Martin DeMello
Wow! This is awesome!Will try it out! Thanks :)
saurabhj
A: 

How about

class Object
  def instance_variables_compare(o)
    Hash[*self.instance_variables.map {|v| 
      self.instance_variable_get(v)==o.instance_variable_get(v) ? [] : [v,o.instance_variable_get(v)]}.flatten]
  end
end


>> car_a.instance_variables_compare(car_b)
=> {"@color"=>"Blue", "@sun_roof"=>false}
Jonas Elfström