2011-03-16 4 views
5

Selon docs de ActiveRecord::Base:ActiveRecord égalité objet

== (comparison_object) Renvoie true si comparison_object est le même objet exact ou comparison_object est du même type et auto a une carte d'identité et il est égal à comparison_object.id.

Notez que les nouveaux enregistrements sont différents de tout autre enregistrement par définition, sauf si l'autre enregistrement est le récepteur lui-même. En outre, si vous récupérez enregistrements existants avec select et laissez l'ID, vous êtes sur votre propre, ce prédicat retournera faux.

Notez également que la destruction d'un enregistrement conserve son ID dans l'instance modèle , les modèles sont donc supprimés encore comparables.

Mais mes observations montrent qu'il ne compare que instaces, non ids de sorte que suivantes sont remplies:

a = Factory.create(:user) 
b = User.find_by_email(a.email) # b is logically same as a 

a.id.should == b.id # All good 
a.should == b # FAILS: Contradicts the docs 
a.should_not == b # Contradicts the docs 
a.should_not eql b # Contradicts the docs 

La question est sont considérés comme 2 cas AR être différent alors que les documents disent explicitement que ceux-ci devraient Être égal?

MISE À JOUR: L'égalité fonctionne comme prévu. L'exemple de code ci-dessus n'est pas pertinent. Voir ma réponse ci-dessous.

+0

Note: La version actuelle de lien doc ci-dessus est à http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method -i-3D-3D – DreadPirateShawn

Répondre

5

Répondre à ma propre question (ce qui n'est pas pertinent).

Tous les contrôles d'égalité fonctionnent comme prévu (et décrits dans les documents).
Je suppose que la raison pour laquelle cela n'a pas fonctionné pour moi est que je cours autotest et quelque chose pourrait être caché ou une autre raison mythique que je ne peux pas expliquer maintenant.

Pour résumer, toutes les assertions suivantes passent en effet:

a = Factory.create(:user) 
b = User.find_by_email(a.email) # b is logically same as a 

a.id.should == b.id 
a.should == b 
a.should eql b 
User.find_by_email(a.email).should == User.find_by_email(a.email) 
a.should == User.find_by_email(a.email) 
b.should == User.find_by_email(a.email) 
+0

+1 pour mentionner l'autotest et la mise en cache, ce qui explique le problème que j'ai eu comme weel avec watchr. THX! – rdamborsky

4

Regardez de plus près à la définition: Notez que les nouveaux enregistrements sont différents de tout autre enregistrement par définition. Dans ce cas, étant donné qu'AR procède normalement à une vérification d'égalité dans la colonne d'identité, vous pouvez comparer les deux objets en comparant le résultat de ce que renvoie #attributes pour chacun.

+0

2 enregistrements sont différents. Mais 2 objets avec le même ID sont logiquement égaux (d'après 'ID .. est égal à comparison_object.id'). Si cela est vrai, je ne comprends pas pourquoi 'a == b' est' false' car il devrait être le même que 'a.id == b.id' (qui est' true'). Ou il me manque quelque chose? –

+0

Vous avez raison, mais il s'agit d'un cas particulier car la variable a contient un nouvel enregistrement et, par définition, un ne sera égal à aucun autre enregistrement. Si vous avez fait User.find (: email ..) == User.find (: email ..) .. Il retournera vrai parce que non seulement ils sont le même enregistrement mais aucun d'entre eux sont nouveaux. –

+0

Non. 'A' et' b' ne sont PAS de nouveaux enregistrements. 'a.new_record?' et 'b.new_records?' sont 'faux'. Ils sont juste 2 objets différents.Rien à voir avec 'User.find (..) == User.find (..)'. De plus, en ce moment mes spécifications * fonctionnent comme le disent les docs * et je peux utiliser 'a == b'. Je suppose qu'il y avait un problème ailleurs. Cela signifie que ma question est obsolète maintenant et (comme je m'y attendais) 'a == b' sont toujours vrais tant qu'ils ont le même ID. –