MongoMapper STI?

65 views
Skip to first unread message

koops

unread,
Oct 23, 2009, 4:11:01 PM10/23/09
to MongoMapper
Has anyone tried to do ActiveRecord-style single-table inheritance
with MongoMapper? Is there a clean way to do it?

The best solution I've come up with is to have a type column and use
it to dynamically include an appropriate module on method_missing.

David James

unread,
Oct 23, 2009, 6:12:25 PM10/23/09
to mongo...@googlegroups.com
Have you considered using embedded documents instead? This might solve your problem right away and more elegantly.
--
David James
Web Developer at Sunlight Labs
dja...@sunlightfoundation.com
AIM: davidatsunlight
Twitter: http://twitter.com/djsunlight
GitHub: http://github.com/djsun

koops

unread,
Oct 23, 2009, 7:00:32 PM10/23/09
to MongoMapper
Embedded documents work for data, not behavior, so I don't see how
that could solve my problem. I'd like MongoMapper to instantiate an
different class based on a type parameter.

David Cuadrado

unread,
Oct 23, 2009, 7:13:42 PM10/23/09
to mongo...@googlegroups.com
it's already implemented, for example:

class Base
  include MongoMapper::Document
  key :shared                 

  before_create { |d| d[:_type] = d.class.name }
end

class Child1 < Base
  key :a
end

class Child2 < Base
  key :b
end

Child1.create(:a => 1)
Child2.create(:b => 2)

Base.all.each { |e| puts e.inspect }
--
David Cuadrado


John Nunemaker

unread,
Oct 23, 2009, 7:21:09 PM10/23/09
to mongo...@googlegroups.com
Yep. You don't need the before_create as MM handles that for you. 


koops

unread,
Oct 26, 2009, 1:06:21 PM10/26/09
to MongoMapper
That's excellent. Does it work for embedded documents too?

John Nunemaker

unread,
Oct 26, 2009, 2:51:00 PM10/26/09
to mongo...@googlegroups.com
Yeah. I think so.

koops

unread,
Oct 26, 2009, 3:48:17 PM10/26/09
to MongoMapper
Doesn't seem to work for me:

require 'rubygems'
require 'mongo_mapper'

MongoMapper.database = 'test'

class Embed
include MongoMapper::EmbeddedDocument
end

class Embed1 < Embed
end

class Embed2 < Embed
end

class Doc
include MongoMapper::Document
key :embed, Embed
end

Doc.create(:embed => Embed1.new)
Doc.create(:embed => Embed2.new)
p Doc.all

John Nunemaker

unread,
Oct 27, 2009, 12:02:12 PM10/27/09
to mongo...@googlegroups.com
You have to define _type key in your embed model.

koops

unread,
Oct 27, 2009, 5:10:56 PM10/27/09
to MongoMapper
Sorry to say that didn't work, nor did setting the _type in the embed
document manually. It's always instantiated as the base class.

John Nunemaker

unread,
Oct 28, 2009, 2:10:09 PM10/28/09
to mongo...@googlegroups.com
Ah right now only polymorphic many embedded docs properly handle this.
I'll look into it.

Jim Mulholland

unread,
Nov 3, 2009, 12:35:10 PM11/3/09
to MongoMapper
This may have been mentioned somewhere else in the past week, but STI
is working great for us on Mongo_Mapper 0.5.8.

Very slick stuff!

jnunemaker

unread,
Nov 17, 2009, 10:28:16 PM11/17/09
to MongoMapper
This is now fixed in master and should be released in gem soon.

mepatterson

unread,
Dec 30, 2009, 1:13:27 PM12/30/09
to MongoMapper
Maybe I'm confused on how this is supposed to work --

class Animal
include MongoMapper::Document
end

class Dog < Animal
end

class Cat < Animal
end

5.times { Dog.create }
4.times { Cat.create }

>> Dog.count
=> 9

>> Cat.count
=> 9

shouldn't those counts reflect the counts of the actual type of
object, not the count of the base object?

mepatterson

unread,
Dec 30, 2009, 1:18:20 PM12/30/09
to MongoMapper
Ahh, okay. I have to manually define

key :_type, String

on my Animal model. That seems to work fine now.

Reply all
Reply to author
Forward
0 new messages