Migrating legacy data

Download Migrating legacy data

Post on 18-Jan-2015

1.347 views

Category:

Technology

0 download

Embed Size (px)

DESCRIPTION

A way to migrate data into your rails app

TRANSCRIPT

  • 1. Migrating legacy data A way to migrate data into your rails app

2. About me Patrick Hsler Freelance developer @ http://www.huesler- informatik.ch Apple enthusiast Surng and Kung Fu 3. Legacy... 4. Us... 5. ConsiderationsRDBMS Keys Philosophy Structure Naming 6. TasksConnect? Retrieve? Integrate? Map? Validate? 7. Connect database adapter (hopefully) add it to database.yml set_table_name set_primary_key set_sequence_name dene associations 8. RetrieveCreate corresponding ARmodels Tell AR to connect to thelegacy database Use ARs features to adjustthings like table name,primary key etc Set up associations 9. 1 class Legacy::User < ActiveRecord::Base 2 3 establish_connection("legacydb") 4 set_table_name :users 5 6 belongs_to :login, :class_name => "Legacy::Login" 7 end 10. 1 class Legacy::Base < ActiveRecord::Base2 self.abstract_class = true3 establish_connection("legacydb")4 end56 class Legacy::User < Legacy::Base7 belongs_to :login, :class_name => "Legacy::Login"8 end9 10 11. IntegratePut models in their ownnamespace to avoid collisions Put them in their own folder 12. 1 class Legacy::Base < ActiveRecord::Base2 self.abstract_class = true3 establish_connection("legacydb")4 end56 class Legacy::User < Legacy::Base7 belongs_to :login, :class_name => "Legacy::Login"8 end9 10 13. Map Let the models handle the mapping 14. 1 class Legacy::Country < Legacy::Base 2 3 has_many :regions, :class_name => "Legacy::Region" 4 5 def code 6 abbrev 7 end 8 end 15. ValidateJust use Active Record Create nders and scopesto only migrate the datayou want Use memoization tospeed up retrieval (e.g.fetch only valid records) 16. 1 class Legacy::User < Legacy::Base 2 belongs_to :login, :class_name => "Legacy::Login" 3 4 named_scope :active , :conditions => ["status = 1"] 5 6 validates_uniqueness_of :email, :scope => :status 7 validates_presence_of :first_name 8 validates_associated :login 9 end 17. MigrateUse migrators/importers 18. 1 # General Importer2 # Code removed for the sake of this example3 class Migration::Importer4 def initialize(_entity_to_migrate,_migrated_entity)5 @entity_to_migrate = _entity_to_migrate6 @migrated_entity = _migrated_entity7 end89 def migrate 10 @migrated_entity.attributes.symbolize_keys.keys.each do |attr| 11 if @entity_to_migrate.respond_to?(attr) 12 @migrated_entity.send("#{attr}=",@entity_to_migrate.send(attr)) 13 end 14 end 15 @migrated_entity 16 end 17 end 19. 1 # General Importer2 # Lines removed for the sake of this example3 class Migration::Importer4 def self.migrate_all(source_class,entity_name = nil)5 migrate_all_from_collection(source_class.send(:all),entity_name)6 end78 def self.migrate_all_from_collection(collection,entity_name = nil)9 entity_name ||= collection.first.class.to_s.pluralize 10 collection.each do |entity| 11 result = self.new(entity).migrate 12 result.save! 13 end 14 end 15 end 20. 1 class Migration::UserImporter < Migration::Importer 2 def initialize(user) 3 super(user,User.new) 4 end 5 6 def self.migrate_all 7 migrate_all_from_collection(Legacy::User.valid) 8 end 9 end 21. TestIntegrates seamlessly withyour rails test suit A separate folder helps toorganize it 22. 1 require File.dirname(__FILE__) + '/../../spec_helper'23 describe Migration::UserImporter do45 before(:all) do6 # setup your test here7 end89 it "should map email address" do 10@migrated_user.email.should equal(@user_to_migrate.email) 11 end 12 13 it "should map login to old login" do 14 @migrated_user.old_login.should == @user_to_migrate.login.login 15 end 16 17 it "should not have an empty salt" do 18 @migrated_user.salt.should_not be_blank 19 end 20 21 end 23. Automate Rake to the rescueLet it deal with dependencies 24. 1 namespace :legacy do2 namespace :data do3 desc "import data from legacy schema"4 task :import => :environment do5 Rake::Task['legacy:data:import:users'].invoke6 end7 namespace :import do8 task :fields_of_study do9 puts "Migrating Fields of study" 10 Migration::FieldOfStudyImporter.migrate_all 11 puts "Done migrating fields of study" 12 end 13 14 task :universities do 15 puts "Migrating universities" 16 Migration::UniversityImporter.migrate_all 17 puts "Done migrating universities" 18 end 19 20 task :users => [:fields_of_study,:universities] do 21 puts "Migrating users" 22 Migration::UserImporter.migrate_all 23 puts "Done migrating users" 24 end 25 end 26 end 27 end 25. Deploy Just put in deploy.rb and let capistrano handle the rest 26. 1 namespace :deploy do2 desc "Migrate data"3 task :migrate_legacy_data, :roles => :app do4 # Actual one liner that would not fit5 # on a presentation screen6 command = "cd #{deploy_to}/current;"7 command