Rails Ambassador

Modelとマイグレーション

こちらのLessonではモデルとマイグレーションファイル、マイグレーションの仕組みについて学習します。マイグレーションの概念は難しいですが、しっかり理解することで安全にアプリケーションを開発することができます。

MVCアーキテクチャ

RailsではMVCアーキテクチャ(設計思想)を採用しています。
MVCはModel 、View、Controllerの頭文字から来ています。
このLessonではModelについて学習していきましょう。

Modelとは何か

Model(モデル)とは操作する対象(resource)です。Railsアプリでデータベースに登録したり、データベースの内容を変更したり、削除するのはモデルを使って操作していきます。
モデルはオブジェクト指向のClassになります。今回は投稿のモデルPostを作り、データベースを操作していきます。
ではboardのディレクトリにいることを確認してPostモデルを作成していきましょう。
Postモデルは投稿を保存するためのcontentというstring(文字列)型のフィールド(属性)をもつようにします。
構文は以下のようになります。

$ rails g model モデル名 属性1:カラム型 , 属性2:カラム型, 属性3:カラム型…

尚、カラム型がstringの場合、省略することができることも覚えておきましょう。以下コマンドを実行してモデルを作成してください。

$ pwd
/xxx/xxxx/xxx/board
$ rails g model Post content

「g」 は 「generate」の省略形です。以下コマンドも同じ動作になります。

$ rails genelate model Post content

さらに以下も同じです。

$ rails genelate model Post content:string

以下のようになりましたでしょうか?

      invoke  active_record
      create    db/migrate/20221208001031_create_posts.rb
      create    app/models/post.rb

createの行が自動で生成されたファイルです。以下2つのファイルが作られていることがわかりますね。

  • db/migrate/xxxxxxxxxxx_create_posts.rb
  • app/models/post.rb

もしモデルの名称などを間違ってしまった場合は自動生成されたものを削除してくれる以下コマンドを使いましょう。


$ rails d model Post

「d」 は 「destroy」の省略形です。以下コマンドも同じ動作になります。

$ rails destroy model Post

こちらのコマンドを実行すると自動生成されたファイルが全て削除されます。

Modelと命名規則

ではapp/models/post.rbファイルを見てみましょう。

class Post < ApplicationRecord
end

これはPostというクラスになっています。このPostクラスこそがModelになるのです。ここで必ず覚えてほしい注意点があります。それは

  • Modelは単数形で、先頭が大文字。
  • Modelはclassです。

ということです。これはルールとして必ず覚えてください。オブジェクト指向を学んだ方はわかると思いますが、クラスということはクラスメソッドやインスタンスメソッドを記載し使用することができるということになります。

rubyではクラスは必ず先頭が大文字になります。厳密に言いますとアッパーキャメルケース(UpperCamelCase)という記法になります。これは単語の先頭が大文字になる記法です。また、必ず単数形でなければいけません。

Tips!Railsは単数・複数形を区別しています。

モデルは単数形且つUpperCamelCaseということを学習しました。
以下3つのコマンドはいずれも同じPostモデルを作成する挙動になります。確認しておくと良いでしょう。
$ rails g model post content
$ rails g model Post content
$ rails g model posts content
複数形でモデルを作成しようとしても自動的に単数形になります(一般的な単語の場合)。
また、モデル名をすべて小文字にしてrails gを行っても、クラスは自動的にアッパーキャメル記法になります。

マイグレーションファイル

次にdb/migrate/xxxxxxxxxxx_create_posts.rbファイルを見ていきましょう。xxxxxxxxxxx部分は作成した日時になっていると思います。このファイルはマイグレーションファイルと呼ばれます。
このマイグレーションファイルは各SQL-DATABASEのSchemaを変更するためのdb/schema.rbを書き換えるファイルです。マイグレーションファイルを作成しただけではDBの変更は行われません。マイグレーションの実行をするとschema.rbが変更され、データベースのschemaも変更されます。

Schema(スキーマ)とは

Schema(スキーマ)とはデータベースの構造を表したファイルの事を言います。SQL-Databaseには必ずこの構造を示したSchemaがあります。railsアプリには 「db/schema.rb」ファイルが後述する最初のマイグレーションの実行時に作成され、その後マイグレーションファイルを実行するたびにこのファイルが書き換わります。 schema.rbは使用するDatabaseに対応するGemによってDatabaseサーバのSchemaを書き換えます。マイグレーションの実行によってデータベースの構造を書き換えることができるのです。
データベースによって自動的に適切なスキーマを生成するので、プログラミングする際にデータベースの違いを意識することはほとんどありません。

マイグレーションファイルの確認と実行

ではマイグレーションファイルを確認してみましょう。db/migrate/xxxxxxxxxxx_create_posts.rbファイルを開いてください。

class CreatePosts < ActiveRecord::Migration[7.0]
  def change
    create_table :posts do |t|
      t.string :content

      t.timestamps
    end
  end
end

create_table :posts の行がpostsテーブルを作成する記述です。
t.string :contentではcontentカラムをstring型(文字列型)で作成します。
最後にt.timestampsの行でcreated_at(作成日)カラムと(update_at)カラムを作成しています。
また、Railsアプリでは自動的に必ずidカラムが主キー(PrimaryKey)として作成されるルールになっています。

それではマイグレーションファイルを実行しましょう。

$ rails db:migrate

マイグレーションファイルに問題が無いと以下のようなメッセージが出ます。


== xxxxxxxxxxxx CreatePosts: migrating ======================================
-- create_table(:posts)
   -> 0.0130s
== xxxxxxxxxxxx CreatePosts: migrated (0.0130s) =============================

xxxxxxxxxxxxの部分はマイグレーションファイルの日付になります。皆さんの作成したファイルと同じ日時になっているはずです。
「create_table(:posts)」のところでpostsテーブルを作成しているのがわかります。
そして CreatePosts: migrated のように 「migrated」が出たらマイグレーションの実行が無事完了です。

PostgreSQLクライアントに接続して正しくDBが作成されているかを確認しましょう。

$ psql board_development       


board_development=> \d posts

                                          Table "public.posts"
   Column   |              Type              | Collation | Nullable |              Default   

------------+--------------------------------+-----------+----------+-----------------------------------
 id         | bigint                         |           | not null | nextval('posts_id_seq'::regclass)
 content    | character varying              |           |          |
 created_at | timestamp(6) without time zone |           | not null |
 updated_at | timestamp(6) without time zone |           | not null |
Indexes:
    "posts_pkey" PRIMARY KEY, btree (id)

board_development=> quit

上述していましたが、マイグレーションファイルには特に見当たらなかったidカラムがPrimarykeyとして作成されていますね。
そしてstringを指定していたcontentカラムは varchar(255)の型になっています。
timestampの記載によってcreatd_atカラムとupdated_atカラムがdatetime型で作成されました。

慣れるまではこのようにPostgreSQLクライアントで確認してどのようなカラムができてるかを確認していくと良いです。

scema.rbの確認

以前、マイグレーションの実行はschema.rbを書き換えるものだと説明しました。こちらも確認しておきましょう。db/schema.rbファイルを開いてください。(コメントアウト部分は省いています。)

ActiveRecord::Schema[7.0].define(version: 20yy_mm_dd_xxxxxx) do

  enable_extension "plpgsql"

  create_table "posts", force: :cascade do |t|
    t.string "content"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

このようにDBの構造が記されています。
schema.rbでも確認できるようになっておくと良いでしょう。

db/schema.rb ファイルはマイグレーションの実行によって書き換わるため、こちらのファイルを編集しても意味がありません。Railsではデータベースの構造を変えるには全てマイグレーションファイルで行います。

Modelの複数形のテーブルが作成される

このLessonではここまでModelを作成し、マイグレーションファイルを実行しました。
モデルとテーブルは密接な関係にあります。
ここでぜひ覚えておいてほしい事は 「テーブルの名前はモデルの複数形、全て小文字」であることです。
Fooというモデルに関連するのはFoosテーブルになります。この命名ルールに則るとコードを短く読みやすい状態(可読性の高いコード)にすることができます。

マイグレーションをやり直したい時は

マイグレーションの実行を行うと、その実行済みのマイグレーションファイルは編集しても無視されてしまいます。とても重要なことなので必ず覚えておきましょう。
ではマイグレーションを実行した後に間違いに気づき、マイグレーションファイルを修正したいといったときはどうすれば良いでしょう。
そういった時にはこのチャプターを参考にしてください。
ただし、マイグレーションをやり直すという事はそのマイグレーションファイルで作成したテーブルやカラムのレコードは消えてしまいます。データが消えてしまっては困る本番環境では特に慎重に行う必要がありますし、サービス提供後は極力するべきではありません。

マイグレーションの状態の確認

まずマイグレーションが実行されているかどうかを確認しましょう。

$ rails db:migrate:status
database: board_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20xx0101111111   Create posts

statusが up になっているのは実行済みのマイグレーションファイルです。 IDとNameでどのファイルか特定できますね。もし複数のマイグレーションファイルがあった場合は実行順に表示されます。実行順番は日付の古い順になります。日付順に実行されるということも重要なポイントです。

では20xx0101111111_create_posts.rbは実行済みなので、実行前に戻して編集しましょう。以下コマンドでマイグレーションの実行をひとつ前に戻すことができます。

$ rails db:rollback

以下のようになりましたか?

== 20xx0101111111 CreatePosts: reverting ======================================
-- drop_table(:posts)
   -> 0.0392s
== 20xx0101111111 CreatePosts: reverted (0.0555s) =============================

create_postsの内容はpostsテーブルを作成するものだったので、これを打ち消す操作が自動的に行われます。テーブルの削除ですね。「drop_table(:posts)」の表示が出ているのを確認しておきましょう。

ではここでもう一度ステータスを確認しましょう。

$rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
  down    20yymmddxxxxxx  Create posts

statusがdownになりましたね!マイグレーションが実行前だという事を示しています。

ではPostgreSQLクライアントでも確認してみてください。

$ psql -d board_development 
board_development=> \dt

postsテーブルがなくなっているのが確認できましたか?これでマイグレーションファイルの編集ができます。間違っていた部分を修正し、修正ができたらマイグレーションの実行を行ってください。


$ rails db:migrate

エラーなく実行できましたか?
PostgreSQLクライアントに接続して正しく変更ができたことも確認しておきましょう。

Tips!マイグレーションをn回ロールバックする

ロールバックのコマンドは一段階前に戻すものでした「n回前」に戻す場合には以下コマンドを実行しましょう。

$ rails db:rollback STEP=n

モデルとマイグレーションまとめ

ここまでモデルとマイグレーションファイルについて学習してきました。

  • モデルは単数形で作成する。
  • モデルを作成するとモデルの小文字複数形のテーブルが作成される。
  • マイグレーションファイルは日付の古い順に実行される。
  • 実行済みのマイグレーションファイル(statusがupになっているもの)は編集しても無視されてしまう。(編集してはいけない)
  • マイグレーションファイルの編集はstatusがdownにしてから行う。

マイグレーションファイルの役割と概要を確認しておきましょう。

主なコマンド
コマンド 意味
rails db:create データベース作成
rails db:drop データベースの削除
rails db:migrate マイグレーションの実行
rails db:migrate:status マイグレーション実行状況の確認
rails db:rollback マイグレーションを1段階前に戻す