Sinatra-ActiverecordでDBをマイグレーションする


sinatra/activerecordのrakeタスクを利用して、DBのマイグレーション処理を勉強したのでメモ。元々はherokuでDBを使うための方法を調べてたら、DBマイグレーションが必要となったのがきっかけ。herokuでの利用についてはまた今度まとめる。

ちなみに、rakeはRubyのビルドツール。JavaのAntみたいなもの。`Rakefile`にrakeタスクを記述しておくと、いろんなビルドができるようになる。


## version
ruby: 2.0.0p451 (2014-02-24 revision 45167)
rake: 0.9.6
gem: 2.0.4
Bundler: 1.5.2


## Gemfile
bundleは「./vendor/bundle」にインストールすることとする。
Gemfileは`$ bundle init`とすると、自動で生成される。

```Gemfile.
source "http://rubygems.org"

gem 'sinatra'
gem 'activerecord'
gem 'sinatra-activerecord'
```


gemのインストールは、--pathオプションを利用してローカルにする。
--pathオプションを指定しないと、Systemにインストールされる。
`$ bundle exec ***`とすると、ローカルのgemを利用してくれる。

    $ bundle install --path=vendor/bundle



## Rakefileを作成する
今回はsinatra/activerecordのrakeタスクを利用する。
`Rakefile`に以下をrequireしておく。

```Rakefile.
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
```

そうすると、次のタスクが使えるようになる。rakeタスクを確認するコマンド`rake -T`で確認。

    $ bundle exec rake -T
    ***
    rake db:create_migration	# create an ActiveRecord migration in ./db/migrate
    rake db:migrate				# migrate your database
    ***


## マイグレーション用ファイルを生成する
`rake db:create_migration`コマンドを使って、マイグレーション用ファイルを生成する。
ここでは、sensorsというデータベースを作る。引数のNAMEは何でも良いが、慣習で`create_***s`とするらしい。

    $ bundle exec rake db:create_migration NAME=create_sensors

「./db/migrate」フォルダが生成され、その中にマイグレーション用ファイル「(日付)_create_sensors.rb」が生成される。

## マイグレーション用ファイルの中に、生成したいテーブル構成を記述する
ここでは、テーブルsensors、要素としてdtype,data,timeを作成する。
データベースでは、テーブル名を複数形にする。これも慣習。

調べると、self.upとself.downメソッドを定義するやり方と、changeメソッドを定義するやり方の２通りあるらしい。rakeのバージョンの違い？作り方を両方書いたが、私の環境では、changeメソッドが生成された。


```(日付)_create_counts.rb
class CreateCounts < ActiveRecord::Migration
  def self.up
    create_table :sensors do |t| #=> この引数名「:sensors」がテーブル名になる
      t.string :dtype
      t.string :data
      t.string :time
      t.timestamps  #=> この一行でcreated_atとupdated_atのカラムが定義される
    end
  end
  def self.down
    drop_table :sensors
  end
end
```

```(日付)_create_sensors.rb
class CreateCounts < ActiveRecord::Migration
  def change
    create_table :sensors do |t| #=> この引数名「:sensors」がテーブル名になる
      t.string :dtype
      t.string :data
      t.string :time
      t.timestamps  #=> この一行でcreated_atとupdated_atのカラムが定義される
    end
  end
end
```


## 生成するデータベースの種類とパスを記述する
herokuのDBがURL表記をサポートしているので、ここでもURL表記とする。`Rakefile`に接続するDBのURLを指定すれば、これを読み込み、自動でDBファイルを生成してくれる。ただ、Rubyアプリ側にも同様の記述をする必要があるため、ここでは`models/sensor.rb`という別ファイルに記述して、`Rakefile`とRubyアプリでrequireすることとする。ついでに、ORマッパーのクラスも作っておく。クラス名はテーブル名sensorsの単数形Sensorにすること。


URLはSQLite3を使う場合。

```Rubyアプリ.rb
require './models/sensor.rb'
```

```models/sensors.rb
ActiveRecord::Base.establish_connection('sqlite3:///sensor.db')
class Sensor < ActiveRecord::Base; end
```


```Rakefile.
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require './models/sensor.rb'  # 追加
```


## マイグレーションしてテーブルを生成する
最後に、`$ rake db:migrate`をすると、自動でテーブルとスキーマが生成される。

    $ bundle exec rake db:migrate

これで`sensors.db`と`db/schema.rb`が自動生成される。
あとは、RubyアプリでSensor<ActiveRecord::Baseクラスを利用するだけ。


## 参考にしたサイト
- SinatraからActiveRecord 3を使う(1) マイグレーション
http://blog.ruedap.com/2011/04/16/ruby-sinatra-active-record-3-migrate

- SinatraでActiveRecord使う
http://nomnel.net/blog/sinatra-active-record/

- Rakeの基本的な使い方まとめ
http://d.hatena.ne.jp/unageanu/20100829/1283069269

- Sinatra✕HerokuのDB設定をいい感じにする。
http://blog.notsobad.jp/post/60131290938/sinatra-heroku-db