CodeIgniter から参照される既存データベースを残しつつ、新たに Rails で Web API を追加開発した話
環境
既存環境: PHP 5.4 / CodeIgniter 新規環境: Ruby 2.1.3 / Rails 4.1.6
実現したいこと
- ネイティブアプリ向けに Web API を追加開発したい。
- Ruby / Rails を採用したい。
- 既存ソースにはないテストをしっかり書きたい。
- 既存のデータベース(MySQL)は、そのまま使いまわしたい。
実装のポイント
1. 技術選定
今回は rails-api を選定した。この gem を採用するにあたり、下記の動画が大変参考になった。
— #348 The Rails API Gem - RailsCasts
また、テストの書き方も情報量の多さから RSpec を導入することとにした。テストの書き方は下記のサイトを参考にさせてもらった。
今回は Rspec と MySQL を利用したいため、下記の通りプロジェクトを作成した。
--skip-test-unit
: RSpec を使用するため、デフォルトの Test::Unit を除外--skip-bundle
: Gemfile を編集してからbundle install
を実行するため、プロジェクト生成時の実行をスキップ--database=mysql
: デフォルトの SQLite ではなく、MySQL を使用する
$ bundle exec rails-api new api --skip-bundle --skip-test-unit --database=mysql
2. 既存データベースとの連携
スキーマの取り込み
database.yml
を既存のデータベースに向け、以下のコマンドを実行することで、 schema.rb
を生成できた。
$ bundle exec rake db:schema:dump
全く同じ疑問を持っていた方がいたため、以下のサイトを参考にさせてもらった。
— mysql - Putting Rails over top of an existing database - Stack Overflow
テーブル名の規約対応
既存のテーブル名が Rails の規約に沿っていないことが問題になることが想定されたが、model に self.table_name
を追加することで解決できた。まずは、migration を作成したくないので --migration=false
オプションをつけてモデルを生成する。
$ bundle exec rails g model user --migration=false
そして、モデルクラスに既存のテーブル名を指定する。
class User < ActiveRecord::Base
self.table_name = 'user'
end
3. テスト環境の構築
テスト用のデータベースを作成する
テストを実行すると、以下のようなメッセージがでた。
ActiveRecord::NoDatabaseError: Unknown database 'test'Run `$ bin/rake db:create db:migrate` to create your database
既存のデータベースを利用しているとはいえ、これまでテストがなかったのでテスト用のDBを用意する必要がある。
$ bundle exec rake db:create
テスト用のテーブルを作成する
データベースの作成後、再度テストを実行するとまたエラーが発生した。
ActiveRecord::StatementInvalid:
Mysql2::Error: Table 'test.foobar' doesn't exist: SHOW FULL FIELDS FROM `foobar`
今度は、テスト用にテーブルを作成する必要がある。今のところこれが正解。
$ bundle exec rake db:schema:load RAILS_ENV=test
「今のところ」と言っているのは、Rails のバージョンにより仕様が変わっているから。検索すると古い情報が多いので注意が必要。非推奨となった方法は以下の通り。
例えば、これができたのは Rails 4.0 系だけ。4.1 で deprecate された。
— Ruby on Rails 4.1 Release Notes — Ruby on Rails Guides
$ bundle exec rake test:prepare
rake aborted!
Don't know how to build task 'test:prepare'
また、以下の方法は Rails 3 系では使えたが 4.1 で deprecate された。現時点ではまだ動くけど WARN がでる。
— Ruby on Rails 4.1 Release Notes — Ruby on Rails Guides
$ bundle exec rake db:test:prepare
WARNING: db:test:prepare is deprecated. The Rails test helper now maintains your test schema automatically, see the release notes for details.
rspec の実行
全てのテストを実行
$ bundle exec rake spec:requests
特定のスペックだけ実行
$ bundle exec rspec spec/requests/users_spec.rb
特定のテストケースだけ実行
$ bundle exec rspec spec/requests/users_spec.rb:50