なぜでしょう? .classは矛盾する結果を与えるか?

私はすべて同じクラスの3つのオブジェクトを持っています。 1つは Item.new で作成され、残りの2つはデータベース(Mongoid)から取得されました。これらのオブジェクトのいずれかを別のメソッドに渡して、そのメソッドの型を is_a 経由でチェックしています:

def initialize (item, attrs = nil, options = nil)
  super(attrs, options)
  raise 'invalid item object' unless item.is_a?(Item)

さて、このレイズはヒットしています。だから私はクラス、is_aとinstance_ofのレールコンソールをチェックします。私は矛盾する結果を得ている。なぜ彼らは同じクラスを持っていますが、そのうちの1つだけが instance_of class ですか?

>> i0.is_a? Item
=> false
>> i1.is_a? Item
=> false
>> i2.is_a? Item
=> true

>> i0.class
=> Item
>> i1.class
=> Item
>> i2.class
=> Item

>> i0.instance_of?(Item)
=> false
>> i1.instance_of?(Item)
=> false
>> i2.instance_of?(Item)
=> true

このタイプの入力を確認するには、より良い方法がありますか?同じクラスの3つのものがすべてそのクラスのインスタンスにならないのはなぜですか?

6
@DaveNewton ok、クラスとis_aタイプのものを調べる良い方法はありますか?
追加された 著者 jcollum,
@ KL-7良い提案、私は私がここにそれらを掲示したときにオブジェクトの名前を変更したので出力を追加したくないので、どちらがどちらであるかわからない。しかし、彼らは私に別のobject_idを返してくれました。ですから、.classではなくobject_idを比較する必要があります。
追加された 著者 jcollum,
同じクラスですか?たとえば、AR関連はArrayであると主張しますが、そうではありません。
追加された 著者 Dave Newton,
i0.class.object_id の出力を追加できますか?他のオブジェクトも同じですか?それは、クラスの再読み込みと何か関係があり、同じクラスの2つの異なるインスタンスがあるかもしれません。
追加された 著者 KL-7,
is_a は、オブジェクトクラスをチェックするための最も一般的な方法だと思います。モンゴイドにロードされるモデルクラスには何か問題があると私は信じています。私の仕様にも同じ問題がありました。クラスのDB object_id からロードした後に、現在ロードされていたものとは異なるものでした。残念なことに、私は当時の解決策を見いださず、何とか私の仕様を変更しました。
追加された 著者 KL-7,

3 答え

Mongoidは分かりませんが、DBアクセスライブラリでは、実際のオブジェクトをデータベースから取得するのではなく、DBに格納されたオブジェクトのスタンドとして機能するプロキシオブジェクトを取得します。 Rubyには完全な透過プロキシを実装する機能がないため、特にリフレクションを使用する場合やオブジェクトアイデンティティの周りで奇妙な結果が表示されることがあります。

3
追加された

@ KL-7のコメントに触発されて、それは起こっているはずです:

class Item; end
class PseudoItem; end

# PseudodItem think it's an Item:
class << PseudoItem
  def inspect
    'Item'
  end
end

i0 = Item.new
i1 = PseudoItem.new

i0.class         #=> Item (correct!)
i1.class         #=> Item (wrong, due to redefinition of inspect!)

i0.is_a? Item    #=> true
i1.is_a? Item    #=> false, as it is a PseudoItem
2
追加された

ああ、同じ問題は...

amuglyで解決された問題(バイパス):

i0.class.to_s==Item.to_s
0
追加された