rmcsharry
rmcsharry

Reputation: 5562

Rails class inheritance, Mongoid fails to return data

With these models:

models/asset.rb

class Asset < Entity
     include Mongoid::Document
end

models/assets/text.rb

module Assets
    class Text < Asset
        include Mongoid::Document
        store_in collection: "#{tenant_uuid}_contents"
    end
end

the Rails console returns:

Entity.all.entries

MOPED: 127.0.0.1:27017 QUERY database=dbname collection=entities selector={} flags=[:slave_ok] limit=0 skip=0 batch_size=nil fields=nil (0.3572ms) []

Asset.all.entries

MOPED: 127.0.0.1:27017 QUERY database=dbname collection=2b66d7a9-8cb5-4802-838a-f1f58869bbf5_contents selector={"$query"=>{"_type"=>{"$in"=>["Asset"]}}, "$orderby"=>{"_id"=>1}} flags=[:slave_ok] limit=0 skip=0 batch_size=nil fields=nil (0.9501ms) []

But if I then do Entity.all.entries again (ie. after Asset.all.entries) I get a different response:

Entity.all.entries

MOPED: 127.0.0.1:27017 QUERY database=dbname collection=2b66d7a9-8cb5-4802-838a-f1f58869bbf5_contents selector={} flags=[:slave_ok] limit=0 skip=0 batch_size=nil fields=nil (3.2308ms)

MOPED: 127.0.0.1:27017 GET_MORE .... and all documents are returned here

If I remove the fact that Asset inherits from Entity, then

Assets.all.entries

always works the first time and returns all documents.

So there is something I am not understanding about the inheritance chain here. Or the fact that Entity is not stored in the contents collection - it is like an 'abstract' class (the Entity class is inherited by other objects which are stored in their own respective collections).

So is the problem here that Mongoid cannot support such an inheritance structure? Do we HAVE to store Entity in the same collection as its children?

Thanks in advance.

Upvotes: 3

Views: 594

Answers (1)

wicz
wicz

Reputation: 2313

It seems it is a pretty well know "issue". And actually it is by design.

Here are two notes from the author:

Mongoid's inheritance functions as single collection inheritance and thus all models in the inheritance chain would store in the same collection - if it changes on one it changes on all.

Similar case here. And a suggestion on how to tackle this, again from the author, is to mixin modules rather than inheritance:

If you want to have common functionality between models, but have them store in different collections you should be using modules, not inheritance.

HTH!

Upvotes: 1

Related Questions