From: Graham Menhennitt Date: 2013-06-18T06:25:16+09:00 Subject: Re: Comparing objects This is a multi-part message in MIME format. --------------080503050508000401030808 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On 18/06/2013 2:06 AM, Josh Cheek wrote: > On Mon, Jun 17, 2013 at 10:52 AM, Thom T. > wrote: > > How do I compare two objects in Ruby, considering only attributes > values? > > For example: > > class Foo > attr_accessor :bar, :baz > end > > lorem = Foo.new > ipsum = Foo.new > > lorem.bar = 1 > lorem.baz = 2 > > ipsum.bar = 1 > ipsum.baz = 2 > > puts lorem == ipsum # false > > Both objects belongs to the same class and also have the same > attributes > values. > > Thanks. > > > I'd do it like this > > class Foo > attr_accessor :bar, :baz > def ==(foo) > foo.kind_of?(self.class) && bar == foo.bar && baz == foo.baz > end > end > > Only define <=> if your foos are ordered. I suspect that the OP is looking for something a bit more generalised. def ==(rhs) return false unless rhs.is_a?(self.class) instance_variables.each do |var| return false unless instance_variable_get(var) == rhs.instance_variable_get(var) end return true end Note that the first line of this can be changed according to taste: - as above, two objects will compare as equal if the class of the right hand side is the same as or a sub-class of the left hand side - remove it completely in which case you get "duck typing" equality (no relationship needed between classes of object) - change it to "return false unless rhs.class == lhs.class" in which case the two objects must be of the same class In the first case, a == b will not necessarily return the same as b == a. Also, note that this code allows the right hand side to have extra instance variables that the left hand side does not, but they can still compare as equal. That may or may not be desirable. If not, you need to test for it as well. Again, the way I've written it, a == b is not the same as b == a. Graham - --------------080503050508000401030808 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit
On 18/06/2013 2:06 AM, Josh Cheek wrote:
On Mon, Jun 17, 2013 at 10:52 AM, Thom T. <lists@ruby-forum.com> wrote:
How do I compare two objects in Ruby, considering only attributes
values?

For example:

  class Foo
      attr_accessor :bar, :baz
  end

  lorem = Foo.new
  ipsum = Foo.new

  lorem.bar = 1
  lorem.baz = 2

  ipsum.bar = 1
  ipsum.baz = 2

  puts lorem == ipsum # false

Both objects belongs to the same class and also have the same attributes
values.

Thanks.


I'd do it like this

class Foo
  attr_accessor :bar, :baz
  def ==(foo)
    foo.kind_of?(self.class) && bar == foo.bar && baz == foo.baz
  end
end

Only define <=> if your foos are ordered.
I suspect that the OP is looking for something a bit more generalised.

        def ==(rhs)
            return false unless rhs.is_a?(self.class)
            instance_variables.each do |var|
                return false unless instance_variable_get(var) == rhs.instance_variable_get(var)
            end
            return true
        end

Note that the first line of this can be changed according to taste:
- as above, two objects will compare as equal if the class of the right hand side is the same as or a sub-class of the left hand side
- remove it completely in which case you get "duck typing" equality (no relationship needed between classes of object)
- change it to "return false unless rhs.class == lhs.class" in which case the two objects must be of the same class
In the first case, a == b will not necessarily return the same as b == a.

Also, note that this code allows the right hand side to have extra instance variables that the left hand side does not, but they can still compare as equal. That may or may not be desirable. If not, you need to test for it as well. Again, the way I've written it, a == b is not the same as b == a.

Graham
-
--------------080503050508000401030808--