Lokkaプラグインで使うデータベースのテーブルのマイグレーション

先日、Lokka本体のソースを書き換えなくてもプラグインが追加できるようになりました。そこで、プラグインで使うデータベースのテーブルを、プラグインのルートディレクトリ(以下、PLUGIN_ROOT)でrakeタスクを実行し、マイグレーションするにはどうしたらよいのか考えてみました。

DataMapper::Resourceをインクルードしたクラス

例えば、lokka-hello_messageプラグインなるものがあり、PLUGIN_ROOT/lib/lokka/hello_message.rbにDataMapper::ResourceをインクルードしたMessageクラスがあったとします。

module Lokka
  module HelloMessage
    def self.registered(app)
      # 省略
    end
  end
end

class Message
  include DataMapper::Resource

  property :id, Serial
  property :message, String
end

Rakefile

RakefileはAPP_ROOTにあるものを参考に、PLUGIN_ROOTに作成。

require './init'

desc 'Create a table for plugin'
task 'db:migrate' do
  Message.auto_migrate!
end

init.rb

初期化するinit.rbもPLUGIN_ROOTに作成しますが、データベースの設定もここでやります。APP_ROOT/lib/lokka.rbをrequireすればいいのかなと思いましたが、APP_ROOT/lib/lokka/app.rbのload_pluginメソッド内*1でエラーが発生するのでやめました。

$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))

require 'sinatra/base'
require 'dm-core'
require 'dm-migrations'
require 'dm-timestamps'
require 'dm-validations'
require 'lokka/hello_message'

module Lokka
  class App < Sinatra::Base
    configure do
      set :root, File.expand_path('../../../../', __FILE__)
      set :config => YAML.load(ERB.new(File.read("#{root}/config.yml")).result(binding))
    end 

    configure :production do
      DataMapper.setup(:default, ENV['DATABASE_URL'] || config['production']['dsn'])
    end 

    configure :development do
      DataMapper.setup(:default, config['development']['dsn'])
    end 
  end 
end

マイグレーション

PLUGIN_ROOTで「bundle exec rake db:migrate」を実行すると、データベースにmessagesテーブルが作成されます。

*1:matchers = @routes['GET'].map(&:first)の行で、@routes['GET']がnilの為。