RailsでSqliteからMysqlにデータを移行する方法

最近のRailsではデフォルトのDBがsqliteになっている。このsqliteを使い続けていくと「ガッカリだよ!」な状態になる。そこでsqliteからmysqlに移行しようと思う。

sqlite2mysqlなものを探してみると以下のものが見つかる。

どちらのプログラムも、sqliteの.dumpでダンプしたSQLファイルをmysql向けに修正してくれるスクリプトだ。

今回、これらのスクリプトを利用しようとしたが、肥大化したsqliteダンプを脆弱なVPSで処理しようとしたら、メモリを全て食い尽くそうとする始末。

Railsではsqlitemysqlも簡単に扱えるので、Rails上でやってみた。

script/copy.rb

module Dev
  class Entry < Entry
    self.abstract_class = true
    establish_connection(:dev)
  end
end

def copy source
  p source.constantize.count
  p "Dev::#{source}".constantize.count
  source.constantize.all.each do |item|
   p item.id
   c = "Dev::#{source}".constantize.create item.attributes
  end
  p source.constantize.count
  p "Dev::#{source}".constantize.count
end

copy "Entry"

config/database.yml

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000
  
dev:
  adapter: mysql
  encoding: utf8
  username: "user"
  password: "********"
  database: "database"
  socket: /var/run/mysqld/mysqld.sock
  timeout: 5000

前準備として、mysql側のdbに対してrake db:createとrake db:scheme:loadを行っておく。

Devモジュールを新たに定義し、モジュール内のモデルにて既存のapp/model内のモデルを利用しながらも、mysqlデータベースに接続する。これにて例えば、

p Entry.count
p Dev::Entry.count

で値が違うことを確認する。

  source.constantize.all.each do |item|
   p item.id
   c = "Dev::#{source}".constantize.create item.attributes
  end

では、source="Entry"だとすれば、

"Entry".constantize.all.each do |item|
  "Dev::Entry".constantize.create item.attributes
end

すなわち

Entry.all.each do |item|
  Dev::Entry.create item.attributes
end

の処理を行う。

もうちょっと上手いコードを書きたいな。