【初級編】Modelの実装手順～Ruby on Rails～

# RailsのModelの書き方まとめ

どうもはじめまして。Tyo_Doと申します。

以前、[【完全保存版】5万円でエンジニア転職してみた。未経験から自社開発エンジニアに転職するまでのロードマップ。](https://qiita.com/Tyo_Do/items/72778ef60103a5c05d51)という記事を書かせていただき、非常に好評だったので調子に乗ってもう1本書いてみました。

本記事は、私がプログラミング学習において一番躓いたといっても過言ではない**MVC**のModelについて解説した記事です。

**少しでも数か月前の私のように躓いている方の助けになればと思います。**

また、私自身春からエンジニアとして働かせていただく身です。執筆時点ではエンジニアではないため間違えている箇所があるかもしれません。もし間違えている箇所がありましたらコメントで教えていただけると助かります。

## 対象読者

本記事の対象者は以下のような方です。

- 教科書などを見ながらRailsでアプリケーションを開発したことがある方。
- 一度MVCについて学習した方
- MVCがなんとなくわかった気がするという方
- MVCがなんとなくしかわかっていないという方

## 参考
※一部引用させていただいております。著作権等には十分注意しておりますが、問題がありましたら速やかに対応いたしますのでコメントにてお知らせください。

[Rails をはじめよう -Railsガイド](https://railsguides.jp/getting_started.html)
[【Ruby on Rails 6】Instagram風簡易SNSアプリを作ってみよう！](https://www.techpit.jp/courses/2)

## 【Model】情報の型を定義するための仕組み
**Model**を一言で表すと、情報を定義することです。
教科書などではオブジェクトといったような用語が使われているかと思います。

ここではTwitterの投稿を例にして考えてみましょう。

早速ですが、Twitterの投稿に含まれている情報を考えてみてください。

「..........」

あくまで一例ですが、以下のような情報がTwitterの投稿には含まれているかと思います。

- 投稿者
- 本文
- 画像

![image](https://i.gyazo.com/bf8ef00c5cd23331f91c0c1250b1112b.png)

リツイートやいいね、リプライなどもありますが、ややこしくなるのでここは一旦上記の3点で進めましょう。

Modelはこの情報を定義するための場所です。

### ER図
上記のツイートを例にすると、**1ツイートに複数枚の写真が存在する**ことがわかります。これを1対多の関係と呼びます。

ER図に表すと以下のようになります。
![image](https://i.gyazo.com/58876b72945da656a31362b4a7e69513.png)

### 実際のコード
では実際にRuby on Railsではどのように定義しているのかを確認していきます。

モデルを作成するためのコマンドは以下のようなコマンドです。
Model名にする1文字目は**大文字＆単数形**であることに注意してください。

ちなみに、`g`は`generate`の略です。

```bash
$ rails g model <Model名>
```

#### `Tweet`モデルの作成
ここでは`Tweet`というモデルを作成していきます。

```
$ rails g model Tweet
```

上記のコマンドを実行すると、モデルファイルとマイグレーションファイルが生成されます。

- `app/models/tweet.rb`
- `db/migrate/××××××××××××_create_tweets.rb`

実際にマイグレーションファイルの中身を見ていきましょう。

```ruby:db/migrate/××××××××××××_create_tweets.rb
class CreateTweets < ActiveRecord::Migration[6.0]
  def change
    create_table :tweets do |t|

      t.timestamps
    end
  end
end
```

それではマイグレーションファイルの中身をいじってみます。

```ruby:db/migrate/××××××××××××_create_tweets.rb
class CreateTweets < ActiveRecord::Migration[6.0]
  def change
    create_table :tweets do |t|
      t.string :name
      t.string :body, null: false, length: { maximum: 140 }
      t.timestamps
    end
  end
end
```

編集した部分がわかるでしょうか？
エンジニアの方が見たら外部キーは！！一意性は！！などと言われそうですが、そこは目をつぶってください。

ここでは`Tweet`を構成する情報を定義しています。
先程の

- 投稿者
- 本文

を記載しています。

Railsでは、以下のようにデータを表現します。

```ruby
t.<型> :<カラム名>　
```
また、カラム名のあとにはその**特性**をつけることもできます。
ここでは、`body`が`null`ではない、文字数が140字以内であることを定義しています。

それでは以下のコマンドを実行します。意味は覚えなくでも結構です。

```
$ rails db:migrate
```

以上でTweetモデルは完成です。

#### `Photo`モデルの作成

それでは`Photo`モデルを作成していきましょう。

![image](https://i.gyazo.com/58876b72945da656a31362b4a7e69513.png)

モデルを作成します。

```
$ rails g model Photo image:string tweet_id:references
```
上記のように、コマンドからカラムの設定を行うこともできます。

```
$ rails g model <モデル名> <カラム名>:<型>
```

`db/migrate/××××××××××××_create_photos.rb`と`app/models/photos.rb`を確認してみましょう。

```ruby:db/migrate/××××××××××××_create_photos.rb
class CreatePhotos < ActiveRecord::Migration[6.0]
  def change
    create_table :photos do |t|
      t.string :image
      t.references :tweet_id, null: false, foreign_key: true

      t.timestamps
    end
  end
end

```

```ruby:app/models/photos.rb
class Photo < ApplicationRecord
  belongs_to :tweet_id
end
```

予めカラムが設定されていることがわかると思います。

**【補足】**
外部キーのカラムの型は`references`にします。こうすることで自動でリレーションを定義してくれます。

それでは、migrateしましょう。

```
$ rails db:migrate
```


最後に`app/models/tweets.rb`を修正して1対多の関係を完成させます。

```ruby:app/models/tweets.rb
class Tweet < ApplicationRecord
    has_many :photos, dependent: :destroy
end
```

`dependent: :destroy`は、親モデルを削除したとき、子モデルも削除するかどうかを表しています。
要するに、ツイートを削除したときにはそのツイートに紐づく写真も削除されるようになります。

### まとめ
- モデルは情報の型を定義するための仕組み
- マイグレーションファイルにモデルの基本情報を記載する
- モデルファイルには他のモデルとの関係を書く
    - 多の関係：`has_many`
    - 1の関係 : `belongs_to`
    - `dependent: :destroy`で親モデルの削除に連動して子モデルも削除