Railsで既存のデータベース(MariDB)を利用する

PHPで作成していたシステムをRailsに置き換えようと色々調べているのですが、移行にあたって最大の問題は「既存のデータベースをRailsでどのように利用するか」ですね。RailsではCoC(Convention over Configuration:設定より規約)の精神が貫かれており、それはデータベースの設計にも徹底されています。例えば、以下はRailsで作成される典型的なテーブルです。

> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| email      | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

Railsではデータベースのテーブルに以下の規約があります。

  • テーブル名が小文字で且つ複数形であること。
  • 「id」というプライマリキーで、auto_incrementなカラムを必ずもつこと。
  • 「created_at」と「updated_at」というカラムを必ずもつこと。

当然Railsを利用しない環境で、上記規約に沿ったテーブル設計なんてしているはずないですから、そのままのデータベースを利用するのであれば、Rails側でいくつかの設定変更が必要となります。

設定変更の方法が用意されているとはいえ、Railsの規約を無視してまで既存データベースを利用して開発をすべきであるかは、大いに議論すべきところだと思います。個人的には、ちょっとしたデータを参照する程度であれば既存データベースでも問題ないと思いますが、がっつり開発しようというのであれば、データベースを作り直す方がいいと感じています。そうでないのであれば、あえてRailsを利用する意味がないのでは、と。

とはいえ、既存データベースを利用する方法も調べたので、以下に記載しておきます。Railsのバージョンは「5.0.1」です。

既存のデータベースへの接続設定をする

database.ymlファイルを編集して、既存データベースへの接続できるようにします。設定方法については、以前の投稿を参照。

RailsでMariadbを利用する - goodbyegangsterのブログ

既存テーブル用のモデルを作成する

既存の以下定義のテーブルにアクセスできるようにします。

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| Code         | int(5)       | NO   | PRI | NULL    |       |
| Meigara_Name | varchar(255) | NO   |     | NULL    |       |
| Market_No    | int(2)       | NO   | MUL | NULL    |       |
| Industry_No  | int(2)       | NO   | MUL | NULL    |       |
| List_flg     | tinyint(1)   | NO   |     | 1       |       |
| Check_flg    | tinyint(1)   | NO   |     | 0       |       |
| Update_day   | date         | NO   |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

とりあえず、railsコマンドでモデルを作成します。この時にマイグレーションは不要なので、「–skip-migration」オプションをつけて実行します。モデル名(というかテーブル名)だけ指定してあげればOKで、カラムの情報は不要です。テーブル内にある全カラムを引っ張てきてくれます。

$ rails generate model Meigara --skip-migration
      invoke  active_record
      create    app/models/meigara.rb
      invoke    test_unit
      create      test/models/meigara_test.rb
      create      test/fixtures/meigaras.yml

このままでは、Railsの規約により「meigaras」という複数形のテーブルを探しにいってしまうので、探しにいってほしいテーブル名を指定してあげます。モデルの定義ファイルのなかに、以下を追加します。

self.table_name = “(テーブル名)”

利用するActiveRecode部分についての説明。

ActiveRecord::ModelSchema::ClassMethods

またプライマリキーもidとは異なるので、以下を追加してあげます。

self.primary_key = “(プライマリキー名)”

利用するActiveRecode部分についての説明。

ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods

実際はこんな感じになります。

「app/models/meigara.rb」
class Meigara < ApplicationRecord
  self.table_name = "meigara"
  self.primary_key = "Code"
end

確認

これでmeigaraテーブル内のデータをモデルとして利用できるようになりました。コンソールから確認してみます。

$ rails console
Running via Spring preloader in process 7522
Loading development environment (Rails 5.0.1)
irb(main):001:0> Meigara.find(65020)
  Meigara Load (0.1ms)  SELECT  `meigara`.* FROM `meigara` WHERE `meigara`.`Code` = 65020 LIMIT 1
=> #<Meigara Code: 65020, Meigara_Name: "東芝", Market_No: 1, Industry_No: 3650, List_flg: true, Check_flg: false, Update_day: "2016-10-27">

もうモデルなので、ビューでも利用できるようになっています。

しかしながら、参照ならまだしもRails側から更新をしていくのはかなり怖いですね。めんどくさい何かが起こりそうな気配です。ぷんぷんします。