How to migrate from belongs_to, to embedded_in in Mongoid?

mongoid, ruby-on-rails

Solution

I am not so sure my solution is right or not. This is something you might try to accomplish it.

Suppose You have models - like this

#User Model
class User
  include Mongoid::Document
  has_many :books
end

#Book Model
class Book
  include Mongoid::Document
  field :title
  belongs_to :user
end

At first step I will create another model that is similar to the Book model above but it's embedded instead of referenced.

#EmbedBook Model
class EmbedBook
  include Mongoid::Document
  field :title
  embedded_in :user
end

#User Model (Update with EmbedBook Model)
class User
  include Mongoid::Document
  embeds_many :embed_books
  has_many :books
end

Then create a Mongoid Migration with something like this for the above example

class ReferenceToEmbed < Mongoid::Migration
  def up
    User.all.each do |user|
      user.books.each do |book|
        embed_book = user.embed_books.new
        embed_book.title = book.title
        embed_book.save 
        book.destroy
      end
    end
  end
  def down
    # I am not so sure How to reverse this migration so I am skipping it here
  end
end

After running the migration. From here you can see that reference books are embedded, but the name for the embedded model is EmbedBook and model Book is still there

So the next step would be to make model book as embed instead.

class Book
  include Mongoid::Document
  embedded_in :user
  field :title
end

class User
  include Mongoid::Document
  embeds_many :books
  embeds_many :embed_books
end

So the next would be to migrate embedbook type to book type

class EmbedBookToBook < Mongoid::Migration
  def up
    User.all.each do |user|
      user.embed_books.each do |embed_book|
      book = user.books.new
      book.title = embed_book.title
      book.save 
      embed_book.destroy
    end
  end
  def down
    # I am skipping this portion. Since I am not so sure how to migrate back.
  end
end

Now If you see Book is changed from referenced to embedded. You can remove EmbedBook model to make the changing complete.

- This is just the suggestion. Try this on your development before trying on production. Since, I think there might be something wrong in my suggestion.

Problem

If one first build their models with a belong_to and has_many association and then realized they need to move to a embedded_in and embeds_many association, how would one do this without invalidating thousands of records? Need to migrate them somehow.

Original source