How to compare two object instances? is "m1.to_yaml.eql?(m2.to_yaml)" a good way?

Hi,

What's an easy way to compare for equality two object instances (that
haven't been saved yet). Or in other words pretty much just two
object instances. I've tried "==" and "eql?" on the objects directly
and this doesn't work.

How about: "m1.to_yaml.eql?(m2.to_yaml)" Is this the simplest way?

(i.e. leveraging the ability to serialize the object to a yaml string)

tks

What's an easy way to compare for equality two object instances (that
haven't been saved yet).

Why do you believe equivalence has something to do with persistence?

Or in other words pretty much just two
object instances. I've tried "==" and "eql?" on the objects directly
and this doesn't work.

How about: "m1.to_yaml.eql?(m2.to_yaml)" Is this the simplest way?

(i.e. leveraging the ability to serialize the object to a yaml string)

You do not mention what classes these objects belong to. However, the proper way is to implement ==, eql? and hash in order to provide correct equivalence semantics. The easy way is to use Struct which will implement those methods for you based on the fields you define.

Kind regards

  robert

···

On 05.09.2009 11:52, Greg Hauptmann wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Have you tried using obj_1.hash == obj_2.hash ?

Also, what do you mean by "saving" the object? Persisting it as a byte
stream, a string, or in a database using ORM?

/ Vahagn

Greg Hauptmann wrote:

···

Hi,

What's an easy way to compare for equality two object instances (that
haven't been saved yet). Or in other words pretty much just two
object instances. I've tried "==" and "eql?" on the objects directly
and this doesn't work.

How about: "m1.to_yaml.eql?(m2.to_yaml)" Is this the simplest way?

(i.e. leveraging the ability to serialize the object to a yaml string)

tks

--
Posted via http://www.ruby-forum.com/\.

Why do you believe equivalence has something to do with persistence?

It's only the instances I want to compare of instances of a Rails
model class which haven't been saved (i.e. if they had been saved they
may have then received their ID attribute values which may have been
different). But yes my question is really generic to any given
custom developed class I may happen to write.

You do not mention what classes these objects belong to. However, the
proper way is to implement ==, eql? and hash in order to provide correct
equivalence semantics. The easy way is to use Struct which will implement
those methods for you based on the fields you define.

So I think you're saying if I can convert the 2 instances of class X I
want to compare to 2 instances of a Struct I create (with the same
attributes of those in my class X) then I can just leverage the
already implemented code in the Struct class for "=="? Is this what
you were meaning?

tks

···

2009/9/5 Robert Klemme <shortcutter@googlemail.com>:

I think the saving/persistence comment of mine diverted the focus of
the question. Robert's comment " the proper way is to implement ==,
eql? and hash in order to provide correct equivalence semantics. The
easy way is to use Struct which will implement those methods for you
based on the fields you define." seem to be the key I was just
asking for clarification re how the Struct can be used to save time in
implementing....

actually I just saw this posted on
"http://www.reddit.com/r/ruby/comments/9540i/ruby_developers_make_sure_you_define_eql_and_hash/"
that might be good...

    def eql?(other)
        return false unless other.class == self.class
        return false unless other.instance_variables == self.instance_variables
        self.instance_variables.each do |var|
            self_var = self.instance_variable_get(var)
            other_var = other.instance_variable_get(var)
            return false unless self_var.eql?(other_var)
        end
        true;
    end

No, I meant, if you want to be lazy you can implement your classes by using Struct. But your approach would work as well.

I don't know whether and how AR implements ==, eql? and hash - chances are that they only compare the primary key in the database which probably would not help you - but this is just a guess.

If you need to convert your objects anyway, then you could also use Arrays, e.g.

a, b = [x,y].map {|o| [o.foo, o.bar, o.baz]}

puts( a == b )

Of course, things get more complicated if your class X does not only contain primitive data (such as Fixnum, String etc.) but other AR created objects as well. Maybe it's better to then implement a to_xyz method in the class which returns something which can be compared. There is a ton of options out there but for one I'm not a Rails user and then we do not have much detail about your use case.

Kind regards

  robert

···

On 05.09.2009 13:07, Greg Hauptmann wrote:

2009/9/5 Robert Klemme <shortcutter@googlemail.com>:

Why do you believe equivalence has something to do with persistence?

It's only the instances I want to compare of instances of a Rails
model class which haven't been saved (i.e. if they had been saved they
may have then received their ID attribute values which may have been
different). But yes my question is really generic to any given
custom developed class I may happen to write.

You do not mention what classes these objects belong to. However, the
proper way is to implement ==, eql? and hash in order to provide correct
equivalence semantics. The easy way is to use Struct which will implement
those methods for you based on the fields you define.

So I think you're saying if I can convert the 2 instances of class X I
want to compare to 2 instances of a Struct I create (with the same
attributes of those in my class X) then I can just leverage the
already implemented code in the Struct class for "=="? Is this what
you were meaning?

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Thanks Robert - this looks like a good way to go then.

···

2009/9/5 Robert Klemme <shortcutter@googlemail.com>:

If you need to convert your objects anyway, then you could also use Arrays,
e.g.

a, b = [x,y].map {|o| [o.foo, o.bar, o.baz]}

puts( a == b )