2011-01-17 7 views
3

ich ein Modell user.rb haben (es ist ein Activerecord :: Base, nicht sicher, ob seine relevant für die Diskussion)Ruby on Rails überwiegendes gleich

In bestimmten Ansichten, vergleiche ich zwei Benutzern über:

<% if current_user == user %> 

Das Ergebnis ist unbestimmbar (manchmal ist das Ergebnis wahr, und manchmal ist es falsch), und ich bin mir nicht sicher warum.

Wenn ich schalten Sie ihn auf

<% if current_user.id == user.id %> 

Es funktioniert wie erwartet. Aber dann muss ich den Fall behandeln, in dem die Benutzer null sein können.

Meine Frage ist, was ist hier los?

Warum schlägt user1 == user2 hier fehl?

Soll ich zwingende == sein, oder

Soll ich eine alternative Methode wie gleich ?, sein mit === oder eql?

Sollte nicht die Tatsache, dass user.rb ist ein ActiveRecord :: Base Mean == standardmäßig vergleicht die ID-Felder bereits?

Antwort

3

Wenn Sie sich den Quellcode schauen von ==

 # File lib/active_record/base.rb, line 2427 
2427:  def ==(comparison_object) 
2428:   comparison_object.equal?(self) || 
2429:   (comparison_object.instance_of?(self.class) && 
2430:    comparison_object.id == id && 
2431:    !comparison_object.new_record?) 
2432:  end 

können Sie sehen, dass es wahr zurückgeben sollte, wenn das Objekt-IDs übereinstimmen.Wenn Ihr Code <% if current_user == user %> für dasselbe Benutzerobjekt fehlschlägt, haben Sie definitiv etwas merkwürdiges vor sich.

Können Sie dieses Code-Snippet im Kontext posten?

+0

Vielen Dank für den Schnipsel, auf jeden Fall beruhigend zu betrachten. Da es nur ein direkter Vergleich ist, ist es schwer, kurz relevant zu geben, was ich in der ursprünglichen Frage enthalten habe ... – tstyle

+0

@tstyle dies in Ihrem Code und lassen Sie uns wissen, was Sie bekommen: wenn current_user! = Benutzer; puts user.inspect; puts current_user.inspect; Ende – DanSingerman

+0

Hey @DanSingerman sorry, ich habe es einfach total vergessen über diese Frage zurückkommen. Gelegentlich funktionierte es durch Überschreiben == in dem Benutzerobjekt mit dem obigen Code. Vielen Dank. – tstyle

1

Von http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-%3D%3D

Gibt true zurück, wenn comparison_object exakt das gleiche Objekt oder comparison_object ist vom gleichen Typ und selbst eine ID hat und es zu comparison_object.id gleich.

Beachten Sie, dass neue Datensätze unterschiedlich sind von einem anderen Datensatz per definitionem es sei denn, der andere Datensatz der Empfänger selbst ist. Wenn Sie die vorhandenen Datensätze mit select abrufen und die ID auslassen, sind Sie auf sich allein gestellt, dieses Prädikat wird false zurückgeben.

Beachten Sie auch, dass die Zerstörung eines Datensatzes seine ID im Modell Instanz erhält, so dass gelöschte Modelle immer noch vergleichbar sind.

Es sollte current_user == user

übereinstimmen Wie werden Sie holen current_user Objekt?

+0

Wenn der Benutzer sich anmeldet, speichere ich seine ID in einem permanenten Cookie als "saved_id". Dann innerhalb von current_user, gebe ich User.find_by_id (saved_id) zurück. Da current_user.id == user.id scheinbar funktioniert, glaube ich, dass ich den korrekten "aktuellen Benutzer" zurückgebe. – tstyle

+0

Könnten Sie versuchen, 'user.class' und' current_user.class' zu drucken und die Ausgabe zu posten? – Dogbert

+0

Ich habe diese Zeilen hinzugefügt, <% = debugge current_user.class%> <% = debug wunsch.user.class%>, direkt vor dem Vergleich, und beide drucken Benutzer (id: integer, name: string, email: string ... – tstyle

1

, wenn Sie weiter auf Gleichheit in Ruby gehen wollen, werfen Sie einen Blick auf diesen sehr guten Blog-Post:

http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/

Hoffnung, dies hilft Ihnen zu verstehen.

+2

Dies ist eine Frage zu '==' in Ruby on Rails.Rails überschreibt Rubys '==', daher ist diese Antwort für diese Frage sehr ein Ablenkungsmanöver RoR == verwendet nur Rubys == zum Vergleichen ganzer Zahlen – DanSingerman

+1

Sie sind völlig richtig! – Pasta