Search code examples
rubydatamapperruby-datamapper

Convert existing DataMapper app data to a different database type


I have an existing ruby application using DataMapper that I am looking to convert to a different database type, preserving the existing data and still using DataMapper. For my specific case, I want to go from sqlite3 with DataMapper to postgress with DataMapper. I did not see an elegant way to handle this with dm-migrations or the various other dm-* tools. Has anyone had success doing this?

It seems like the ideal way to handle this would be an ability for DataMapper to export to a database-independent "data mapper" format, then re-import into a specific type of database ... but I am not finding anything to do this.

I have separately tried to convert the sqlite3 database directly to postgress, but DataMapper then doesn't like the resulting postgress database (not a huge shocker).


Solution

  • This is something largely outside the scope of what an ORM is designed to handle. That being said, I have done similar with activerecord and was able to come up with something that I think should work. Obligatory "code has not been tested, use at your own risk" warning

    Step 1:

    Create a second database connection that connects to the postgres database

    Step 2 (this is the annoying part):

    Create copies of the models and specify the new connection. You should be able to use some metaprogramming to redefine the models (it worked in IRB with standard ruby objects, not sure if it will work for DM, but it should):

    Old model:

    class Foo
      include DataMapper::Resource
      # properties
    end
    

    New models:

    [Foo].each do |klass|
      Object.const_set("#{klass}Pg", Class.new(klass) do 
        def self.default_repository_name
          :name_of_second_database_connection
        end
      end)
    end
    

    Step 3:

    Loop through models:

    [Foo].each do |klass|
      klass.all.each do |obj|
        Object.const_get("#{klass}Pg").create!(obj.attributes)
      end
    end