How can I use Mongoid and ActiveRecord in parallel in Rails 3?

Viewed 7589

I'm using rails 3, and began my application with ActiveRecord. Now, I have many models, and the relations are starting to get complicated, and some could be more simply expressed with a Document-Oriented structure, so I'd like to try migrating to MongoDB and use Mongoid.

I've always heard that you didn't have to eitheer use all MongoDB or nothing, but that you could use the two in parallel while migrating. I don't see how to go about this from the docs though.

For example, I have:

class User < ActiveRecord::Base
   has_many :items
   has_many :products, :through => :items
end

class Product < ActiveRecord::Base
   has_many :items
end

class Item < ActiveRecord::Base
   belongs_to :user
   belongs_to :product

   # alot of data that fits a hierarchical document-oriented structure
end

I'd like to ideally begin by replacing my Item activerecord model with a Mongoid document, so my items are stored in MongoDB, and my Users and Products can stay in my SQL DB

Thing is, I don't see how to do this. Am I going about this the right way?

Perhaps another alternative is to keep a base AR Item

class Item < ActiveRecord::Base
   has_one :mongodb_item  ?? # I know this is wrong
end

class MongodbItem
   include Mongoid::Document
   belongs_to AR_Item ???    # I know this is also wrong
end

Thanks!

4 Answers

i created a module for spoofing the relation in active record models.

module MongoRelations
  def belongs_to_mongo(name, options = {})
    id_name = "mongo_#{name}_id".to_sym
    mongo_model = options[:through] || "Mongo::#{name.to_s.camelize}".constantize

    define_method(name) do
      id = send(id_name)
      mongo_model.find(id) if id.present?
    end

    define_method("#{name}=") do |value|
      send("#{id_name}=".to_sym, value.try(:id).to_s)
    end
  end
end

In my SQL table, I name my mongo relations using the convention mongo_XXX_id, instead of XXX_id

I also namespace all my mongo models under Mongo::

in my active record model

class Foo < ActiveRecord::Base
    belongs_to_mongo :XXX
end

which allows

Foo.new.XXX = Mongo.find('123')
Foo.XXX

or

Foo.new.XXX_id = '123'
Foo.XXX
Related