Why .is_a? and .class give conflicting results?

I have three objects that are all the same. One of them was created through Item.new , and the other two were extracted from the database (Mongoid). Am I passing one or any of these objects to another method and checking the type of this method with is_a? :

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

OK, this raise gets hit. So I check the class, is_a and instance_of in the rails console. I get conflicting results. Why will they have the same class , but only one of them will be instance_of that 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 

Is there a better way to do type checking on my inputs? Why are three things that are the same class not all instances of this class?

+6
source share
3 answers

I don’t know Mongoid, but, as a rule, in the database access library you do not get the actual object from the database, but rather a proxy object that acts as a backup for the object stored in the database, since Ruby does not have functions for implementing a perfect transparent proxy, you will sometimes see odd results, especially when using reflection or object identification.

+3
source

Inspired by @ KL-7's comment, this should happen something like this:

 class Item; end class PseudoItem; end # PseudodItem think it 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
source

Ya, same problem here ...

The problem is solved (bypassed) with the ugly one:

 i0.class.to_s==Item.to_s 
0
source

Source: https://habr.com/ru/post/907785/


All Articles