Railsでのデータベース作成と変更および既存のデータベースをRailsに移行するケースの対応について

Railsではデータベースの作成やテーブルの構築や変更をSQLではなく、マイグレーションファイルで行うことができる。一見独自のルールを学ぶ必要があり、面倒だと感じるかもしれないが、デプロイの自動化に役立つ他、アプリの配布時にも役立つ。

ここでは一般的によく使われる機能などを紹介する。

データベースの作成

config/database.ymlにデータベースの設定を行い、rake db:createをすることで設定に従ってデータベースが作成される。

rake db:create
rake db:create RAILS_ENV=production

テーブルの作成

テーブルの作成用のマイグレーションファイルを手動で作成すれば良いのだが、これはモデル作成時にも自動的に生成される。例えば下記のコマンドを実行する。

rails g model User

すると下記のマイグレーションファイルが生成される。モデル作成時に必要なカラムを設定すれば、そのカラムの作成文も自動的にマイグレーションファイルに記載されるが、インデックスの作成やデフォルト値などの細かい設定を行う場合は、モデル作成時ではなくマイグレーションファイルを直接編集する方が分かりやすい場合がある。

class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps
end
end
end

デフォルトで作成されたマイグレーションファイルではデフォルトでid, created_at, updated_atが生成されるので、その他に必要なカラムを手作業で追加すれば良い。

例えば、ユーザー名、メールアドレスを保存するテーブルを作成する場合は、このマイグレーションファイルに下記のように追加するだけで良い。

class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end

この状態ではnameemailvarchar:255で作成される。

実際の利用ではlongtext, binary, int, datetimeの作成、インデックスの作成、デフォルト値、nullの設定を行いたい。これらを全て作成するサンプルが下記である。

class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string   :name,          :null => false, :limit => 30
t.string   :email
t.string   :role,          :null => false, :default => "user"
t.text     :profile,       :null => false, :limit => 4294967295
t.binary   :profile_image, :null => false, :limit => 4294967295
t.integer  :sign_in_count, :null => false, :default => 0
t.datetime :last_sign_in_at
t.timestamps
end
add_index :users, :name
add_index :users, :role
end
end

intintegerで作成される。bigintなどを使う場合はlimitを利用する。limitの値によって作成される型が変わる。下記はlimitの値によって作成される型のサンプルである。
How to create columns like "bigint" or "longtext" in Rails migrations, and what :limit means for column migrations - makandropedia

create_table 'example' do |t|
t.integer :int                 # int (4 bytes, max 2,147,483,647)
t.integer :int1, :limit => 1   # tinyint (1 byte, -128 to 127)
t.integer :int2, :limit => 2   # smallint (2 bytes, max 32,767)
t.integer :int3, :limit => 3   # mediumint (3 bytes, max 8,388,607)
t.integer :int4, :limit => 4   # int (4 bytes)
t.integer :int5, :limit => 5   # bigint (8 bytes, max 9,223,372,036,854,775,807)
t.integer :int8, :limit => 8   # bigint (8 bytes)
t.integer :int11, :limit => 11 # int (4 bytes)
end

textではデフォルトでtextが生成される。longtextを作成するためにサンプルではlimitを利用している。これもlimitの長さによって作成される型が変わる。
Rails 3 Migration with longtext - Stack Overflow

1 to 255 bytes: TINYTEXT
256 to 65535 bytes: TEXT
65536 to 16777215 bytes: MEDIUMTEXT
16777216 to 4294967295 bytes: LONGTEXT

ちなみにbinarylongblobで作成される。これもlimitの値によって変化する。

デフォルトではnullが許可されているが、nullを許可したくないフィールドではfalseを設定する。デフォルト値を設定したい場合はdefaultを利用する。インデックスはadd_indexで作成できる。

これらのルールを学ぶ必要があるが、仕組みを覚えてしまえばSQLを書いたり、DB管理アプリケーションが必要なくなり、デプロイの自動化が可能となる。

データベースにテーブルを作成する

ひと通りテーブルの設計が完了したら下記のコマンドでデータベースにテーブルの作成を実行できる。

rake db:migrate
rake db:migrate RAILS_ENV=production

テーブルへのカラム追加

既に開始したサービスのDBテーブルの拡張やカラムの修正といった作業を行いたい。通常は修正用のSQLを作成し、本番環境で実行するといった手続きが必要だが、Railsではこれもマイグレーションファイルで自動化できる。

マイグレーションファイルの作成

テーブルの作成ではモデルと同時に生成されたマイグレーションファイルを利用したが、このような変更時にはrails g migrationでファイルを手動作成する。

rails g migration users_update

下記のようなファイルが作成される。このファイルに処理を記述していく。

class UsersUpdate < ActiveRecord::Migration
def change
end
end

テーブルへの変更

テーブル名変更、カラム削除、カラム名変更、カラム追加、カラム修正、インデックス作成のサンプルである。分かりやすく各処理の上にコメントを書いている。

class UsersUpdate < ActiveRecord::Migration
def change
# テーブル名変更
rename_table :users, :members
# カラム削除
remove_column :members, :profile
remove_column :members, :profile_image
# カラム名変更
rename_column :members, :sign_in_count, login_count:
rename_column :members, :last_sign_in_at, login_at:
# カラム追加
add_column :members, :password, :string, :null => false, :after => :name
add_column :members, :items_count, :integer, :null => false, :default => 0, :after => :password
# カラム修正
change_column :members, :email, :string, :null => false
change_column :members, :role, :string, :limit => 10
# インデックス作成
add_index :members, :email
end
end

テーブル名変更用ファイル、カラム追加用ファイルと別々に作成する必要はなく、一つのマイグレーションファイルに様々な処理を書くことが可能。上から順に実行されるため、テーブル名を変更した場合などは、それ以降では新しいテーブル名を指定しよう。

テーブルの削除

drop_tableを利用する

class DropHoges < ActiveRecord::Migration
def change
drop_table :hoges
end
end

データベースへ変更点を反映

rake db:migrate
rake db:migrate RAILS_ENV=production

既存のデータベースをRailsで管理する

新規プロジェクトではない、別言語、別フレームワークで管理している既存プロジェクトを、Railsに移行するケースへの対応はどうするか。

Railsにはrake db:schema:dumpというコマンドがある。これを利用すればschema.rbにデータベースの構造をdumpすることができる。dumpしたschema.rbの情報を元に先に記載したカラムの変更や削除を行うマイグレーションファイルを作成し、rake db:migrateでデータベースをRails管理下に移行することができる。

またテーブル内のデータをRails用に書き直す必要がある場合はRailsのタスク機能を利用して、マイグレーション実行後にタスクを起動してRails用にアップデートすれば良い。

最新バージョンのRuby環境構築 : CentOS・RedHat編

CetnOSではyumRubyをインストールすることもできるが、バージョンがかなり古いため、Rubyをインストールする際はソースからビルドする。最終チェックは2014年10月。

必須ソフトウェアのインストール

ソースコンパイルに必要なソフトウェアのインストール。SQLiteを使う場合はsqlitesqlite-develも追加でインストールする。

yum install gcc zlib-devel openssl-devel

最新版Rubyのインストール

最新の安定版はRubyの公式サイトのダウンロードページから確認できる。ここからインストールしたいRubyソースコードをダウンロードしインストールを行う。

cd /usr/local/src
wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.3.tar.gz
tar zxvf ruby-2.1.3.tar.gz
cd ruby-2.1.3
./configure
make
make install

インストールに成功すれば下記でバージョンを確認できる

ruby -v

Rubyのアンインストール

installed.listファイルに作成されたファイル一覧がある。これを使って下記のようにアンインストールする事ができる。

cat .installed.list | xargs rm

Thanks

Rubyを最新ソースからインストール | CentOSサーバ構築術 文具堂

Ruby2.0をソースからインストールする手順 (CentOS/RedHat)

ソースからインストールしたRuby 1.9.1をアンインストールする方法 - mikage014の日記

RailsアプリをApache + Passengerで公開する : CentOS・RedHat編

Apacheが導入されているサーバーにPassengerをインストールするだけでRailsアプリを公開することができる。無論バーチャルホストで複数ドメインRailsアプリを動かしたり、別ドメインではPHPを動作させるといったことも可能である。
また、Apache + PassengerだけでなくNginx+Unicornの構成でRailsアプリを公開することも可能であり、RailsアプリをNginx + Unicornで公開する : CentOS・RedHat編で紹介しているので、好みによって好きな方で構築したい。

前提条件としてRubyをインストールしておく
最新バージョンのRuby環境構築 : CentOS・RedHat編

Passengerのインストール

gemでpassengerをインストールする。公開サーバーではドキュメントなどは不要なため--no-rdoc --no-riを付与している。

gem install passenger --no-rdoc --no-ri

下記でPassengerをインストールできる。この時足りないソフトウェアが自動的に表示される。

passenger-install-apache2-module

全くセットアップを行っていないサーバーで実行すると下記をインストールすることになると思われるが、環境によって異なる。表示された指示に従うこと。

yum install httpd http-devel curl-devel

インストール完了には10分程度の時間がかかる。インストール完了後、httpd.confに追加するLoadModuleなどの設定が表示されるため追加する。

設定を追加した後Apacheのバーチャルホストを普通に設定する。この時ドキュメントルートはRailsのpublicディレクトリを指定すれば良い。

<VirtualHost *:80>
ServerName www.yourhost.com
DocumentRoot /somewhere/public
</VirtualHost>

また、Passngerの設定は下記を追加して行う。なくてもデフォルト値で稼働するかと思うが、不要な情報の除去やチューニングを行うべき環境では設定する。
さくらVPS/entOS 6.4 Passengerのインストール手順 - 酒と泪とRubyとRailsと

Header always unset "X-Powered-By"
Header always unset "X-Rack-Cache"
Header always unset "X-Content-Digest"
Header always unset "X-Runtime"
PassengerMaxPoolSize 20
PassengerMaxInstancesPerApp 4
PassengerPoolIdleTime 3600
PassengerHighPerformance on
PassengerStatThrottleRate 10
RailsSpawnMethod smart
RailsAppSpawnerIdleTime 86400
PassengerMaxPreloaderIdleTime 0

Passengerはデフォルトでエラーページに細かなデバッグ情報を全て表示する設定となっている。本番サーバーで利用する場合はエラーページをoffにすることで非表示にできる。

PassengerFriendlyErrorPages off

Passengerはデフォルトでproductionモードで稼働しているが、開発用サーバーで稼働させる場合は下記のように設定する。

RailsEnv production

参考資料

thinかUnicornかPassengerの3択になるかと思いますがめんどかったらPassengerでいいんじゃないでしょうか。
Rubyのhttpサーバまとめ 2012年4月版(thin, Unicorn, Passenger, etc)

Railsの開発でよく使うコマンド集

Railsの新規プロジェクト作成

rails new hoge -d mysql

本番モードで起動する

rails s -e production

アセットファイルのプリコンパイル

rake assets:precompile RAILS_ENV=production

データベースを作成する

rake db:create
rake db:create RAILS_ENV=production

未実行のマイグレーションファイルを実行する

rake db:migrate
rake db:migrate RAILS_ENV=production

マイグレーションファイルを作成する

rails g migration hoge_updates

タスク一覧の表示

rake -vT

既存データベースをRailsのschemaにdump

rake db:schema:dump

RailsのGemfileに設定されたgemのインストール

bundle install
# installは省略可
bundle

unicorn

unicornの起動

bundle exec unicorn -E production -c config/unicorn.rb -D

unicornの再起動

kill -HUP `cat tmp/pids/unicorn.pid`

Unicorn | Rails3

Railsのタスクでバッチ処理を行う

下記でタスクファイルを作成する

rails g task hoge

下記は登録されている画像ファイル名を全て小文字に変更するサンプル。このようにタスクの中ではモデルに自由にアクセスできる。

namespace :hoge do
desc "処理の説明"
task :update_record => :environment do
Image.all.each do |value|
if value.update_attributes(image_name: value.image_name.downcase)
puts value.image_name + " => " + value.image_name.downcase
else
p value.errors
end
end
end
end

作成したタスクは下記で実行できる

rake hoge:update_record

作成したタスクはrake -vTから一覧で確認することもできる。タスクが増えてきた時は活用したい。

rake -vT

Railsの処理をコンソールから実行する

Railsではコンソールからrails runnerでコードを実行できる。例えば下記は現在の実行モードを確認できる

rails runner 'puts Rails.env’

複数行のコードも実行できる

rails runner '
puts Model.find(1).inspect
puts Model.find(2).inspect
'

定期的に実行するバッチ処理などは、rails runner実行する事もできるが、タスクを利用する方法が適切である。

Rubyの開発環境構築 : Mac編

Macの場合、最初からRubyがインストールされているが、古いバージョンがインストールされている場合がある。最新版のRubyやgemで開発を行いたい、プロジェクトによってRubyやgemのバージョンを切り替えたい場合、rbenvを利用するのが簡単である。

Homebrewのインストール

HomebrewとはMacのパッケージを管理するソフトウェアであり、既にMacにインストールされているパッケージとは別で、簡単にパッケージのインストールとアンインストールを行う。
Homebrew — OS X用パッケージマネージャー

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

インストール後.bash_profile/usr/local/bin/にパスを通す。brewはここにパッケージをインストールする。

export PATH=/usr/local/bin:$PATH

Terminalを再起動するか.bash_profileをリロードする。

source ~/.bash_profile

rbenvのインストール

rbenv、ruby_build、rbenv-gemset、rbenv-gem-rehashをインストールする。

brew update
brew install rbenv
brew install ruby-build
brew install rbenv-gemset
brew install rbenv-gem-rehash

rubyのインストール

ruby 2.1.2がインストール可能か調査する

rbenv install -l | grep 2.1.2

可能であればインストールする

rbenv install 2.1.2

下記のように出れば成功だが、筆者の環境では何らかの問題によってこの処理が完了するまでに1時間以上の時間がかかった。

rbenv install 2.1.2
Downloading ruby-2.1.2.tar.gz… -> ダウンロード先URL
Installing ruby-2.1.2...
Installed ruby-2.1.2 to ~/.rbenv/versions/2.1.2

インストール完了後使用するrubyのバージョンを指定し有効化を行う。この処理の実体はメインディレクトリにruby 2.1.2をコピーするようである。

rbenv global 2.1.2
rbenv rehash 

そのメインディレクトリに.bash_profileでパスを通す。既存のパスを後方に持ってくる事で、Macにデフォルトでインストールされた古いrubyより優先してrbenvのrubyを読み込めるようにする。

PATH=~/.rbenv/shims:"$PATH”

Rails入門などで古い既存のrubyやgemなどを利用してRailsなどをインストールしている場合、環境によっては古いrubyやgemが利用されてしまうため注意すること。

例えばwhichを使って現在どのコマンドを利用しているか確認できる。

which gem
which ruby
which bundle
which rake
which rails