Recently we were working on a Rails project where we needed to import data from legacy database. In the next few steps I will describe how we did it.

In database.yml we specified information for interaction with legacy data.

# config/database.yml
legacy_development:
  host: localhost
  database: legacy

In models directory, we added a legacy directory to which we will later add all legacy models. But first we created a Legacy::Base class which will inherit from ActiveRecord::Base. In it, we established a connection with a legacy database. This way we isolate our connection to the legacy database and all our legacy models will inherit from Legacy::Base.

# app/models/legacy/base.rb
class Legacy::Base < ActiveRecord::Base
  establish_connection :legacy_development
  self.abstract_class = true
end

So now we will create a legacy model and we will specify a table name from legacy database.

# app/models/legacy/post.rb
class Legacy::Post < Legacy::Base
  self.table_name = 'posts'
end

Once we have done this it is the time to check if legacy posts are available. So we can run bundle exec rails console in our terminal and get all legacy posts: Legacy::Post.all

In our case we added a new method which helps us to migrate data. In it we will match legacy data with our new model attributes.

 class Legacy::Post < Legacy::Base
   self.table_name = 'posts'

   def to_new_model
     new_post        = Post.new
     new_post.id     = self.id
     new_post.title  = self.title
     new_post.text   = self.text
     new_post.author = "#{self.first_name self.lastname}".strip

     new_post
   end
 end

We used a rake task to migrate data. In it we are going to loop through all legacy posts and use to_new_model method to set the data, if the data is valid they will be saved otherwise we will catch an error.

  # lib/tasks/migrate_posts.rb
  namespace :legacy do
    task migrate_posts: :environment do

      Legacy::Post.all.each do |post|
        new_post = post.to_new_model

        if new_post.save
          puts "Post with id: #{new_post.id} is created."
        else
          puts "Post with id: #{new_post.id} errors: #{new_post.errors.full_messages.join(", ")}\n"
        end
      end
    end
  end

So the final step is to run rake task: bundle exec rake legacy:migrate_posts

I hope that this helps you :)

Tags: ruby, rails, legacy, rake task

Comments

comments powered by Disqus