1

同じであるべき 2 つの User オブジェクトがありますが、Ruby はそうではないと言っています。ここで何が起こっているのか誰か説明してもらえますか?

a = current_user  
b = votable.user

a == b  
false   
a.id == b.id  
true  
a.name == b.name  
true  
a.attributes == b.attributes  
true

元の投稿以降の更新/追加情報:

  • 私が抱えている問題は断続的であることがわかりました。問題のページを更新する時間の約 30% で発生します。70% の確率で A == B となり、すべてが期待どおりに機能します。しかし、30% の確率で、A は B と等しくありません。
  • 問題が発生すると、Ruby は、オブジェクト (ユーザーとユーザー) が同じに見えても、オブジェクトのクラス (型) が同じではないことを実際に教えてくれます。問題が発生している 30% の時間の出力は次のとおりです。

.

a.class == b.class AKA a.type == b.type
false (note: this is a correction to the original post which said true)
a.class.to_s
"User"
b.class.to_s
"User"
a.class.name == b.class.name
true
a.class.methods == b.class.methods
true
a.class.object_id == b.class.object_id
false

したがって、オブジェクトのクラス (型) はまったく同じに見えます。ユーザーと言われています。しかし、a.class == b.class を評価すると、ページをレンダリングする時間の 30% で答えが false になり、問題が発生します。

誰が何が起こっているのか教えてもらえますか? どうもありがとう。

➜ ~ ruby​​ --version
ruby​​ 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
➜ ~ rails --version
Rails 3.0.10

4

6 に答える 6

3

a == bが偽の場合、参照が同じオブジェクトを指している場合にのみ真になるようなことをしていると思いますa.object_id == b.object_id

a.id == b.idおそらく をチェックしているだけでUser.idあり、それが真実であることは理にかなっています。

最も簡単なことは、チェックを続けることUser.idです。本当に使いたい場合==は、 User クラスで次のようにオーバーライドする必要があります。

class User
  def ==(other)
    self.id == other.id
  end
end
于 2011-11-24T16:58:04.970 に答える
0

Railsのドキュメント(http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-3D-3D )によると、等価演算子はタイプとIDをチェックする必要があります。

# File activerecord/lib/active_record/base.rb, line 1811
def ==(comparison_object)
  super ||
    comparison_object.instance_of?(self.class) &&
    id.present? &&
    comparison_object.id == id
end

起こっているに違いないのは、それらが同じクラスではないということです。結果を確認して出力していただけませんか?

votable.user.class
current_user.class
于 2011-11-24T17:41:19.647 に答える
0

Rails 3を使用していて、上記の各メソッドがActiveRelationを返すと仮定した場合(または、少なくともそのうちの1つが返します)。次に、各ActiveRelationはおそらく異なるオブジェクトであるため、最初の比較は正しいと言っても差し支えありません。

私の答えはあなたのコードについていくつかの仮定をしますが、いくつかの洞察を提供するのに役立つかもしれません。

于 2011-11-24T17:28:10.310 に答える
0

これらがどのようなオブジェクトであるかはわかりません。彼らはまともObjectですか?

Object#==Object#===より適切な動作をオーバーライド#==して定義しない限り、実際にはそうします。= が真であるためObject#==には、実際には同等のオブジェクトではなく、同じオブジェクトへの参照である必要があります。

メソッドを定義し、#==適切なロジックを使用して 2 つのオブジェクトが同じかどうかを判断するだけです。その後、a == bと getを使用できますtrue

これらが子孫である場合、オブジェクトには適切なメソッドがあるためActiveRecord::Base、何か他のことが起こっています (ただし、その動作を上書きすることもできます)。ActiveRecord::Base#==

于 2011-11-24T16:57:39.680 に答える
0

2 つのオブジェクトは同じオブジェクトではありません。ただし、データベース内の同じユーザーを参照しています。

あなたがしたように、それらを比較することをお勧めしますid

于 2011-11-24T16:57:46.257 に答える
-2

論理的な説明:

それらは類似した属性を持っていますが、本質的に異なります。地球と火星は、両方が天の川銀河にあり、両方が惑星であるという事実だけを見ても、異なる惑星であることに注意してください。

オブジェクトが別のオブジェクトのようである場合、それは必ずしも同じではありません。

技術的な説明:

オブジェクトを作成すると、オブジェクトへの参照が作成されます。別のオブジェクトを作成すると、別の参照が作成されます。

オブジェクトAとオブジェクトがある場合。

a = current_user  
b = votable.user
a == b
false

a = current_user  
b = a
a== b
true

2つのオブジェクトは、それらの参照が同じである場合は等しくなります(もちろん、それらの属性も同じです)。標準の関係が十分でない場合は、いつでも新しい同値関係を定義するメソッドを書くことができます;)

于 2011-11-24T17:21:19.987 に答える