わかったつもりになってない?

わかったつもり防止のために、日常で学んだことをもう少し深堀したいブログ

【Ruby on Rails】DBのテーブル間でアソシエーション(関連付け)する手順まとめ

ども。あけましておめでとうございます。

2018年はprogateのおかげでWebプログラミングに目覚めて、2019年くらいには自前のWebサービスを3つくらい運営している想定でしたが、一つ公開はしたものの理想には程遠い出来なので作りこんでいる昨今です。なかなかままなりませんね。

ブログは約3か月ぶりくらいの更新になりますが、まったりプログラミングは続けており、progateのRuby on Railsレッスンでは出てこなかったDBの関連付けについて学んだので記事にしたいと思います。手順にすると簡単に見えますが、色々参考にしながら成功するまでメッチャ時間かかったんですよ…。

0.前提

当環境はAWSの「Code Star」、「Cloud9」を利用して作成しています。バージョンは以下の通り。

Ruby on Rails 5.2.0
Ruby 2.4
 
環境作成の手順は以下を参照してください。
gattsu09.hatenadiary.com

1.ER図を作る

まずはDBの設計図ことER図(Entity Relationship Diagram)を作成します。今回作る程度だったら別に脳内でも間に合いますが、Webサービス作ってみると、どんどんDBに変更が入ってきて訳が分からなくなるので、どこかのタイミングで図に落とし込んでおくと脳内整理や備忘録にもなって良いと思います。

というわけで、今回はERDPlusというWebサービスを使って作ってみました。かなり簡易的ですが、シンプルに作れて備忘録には十分だと思います。

f:id:gattsu09:20190103193925p:plain
ER図

2.Userテーブルを作る

Userテーブルを以下のコマンドで作っていきます。ここらへんはprogateさんのレッスンが分かりやすいので細かい説明を端折ります。

rails g model User name:string

3.Commentテーブルを作る

次に以下のコマンドでCommentテーブルを作ります。「user:references」の箇所がミソなのですが、こう指定すると「user」テーブルの「id」を参照する外部キー「user_id」カラムを生成します。

rails g model Comment user:references comment:string

コマンドを実行すると「<プロジェクトフォルダ>/db/migrate」配下に以下内容のmigrateファイルが作成されます。

class CreateComments < ActiveRecord::Migration[5.2]
  def change
    create_table :comments do |t|
      t.references :user, foreign_key: true
      t.string :comment

      t.timestamps
    end
  end
end

また、「<プロジェクトフォルダ>/app/model」配下に「comment.rb」というmodelファイルが作成されます。ファイル内には指定したテーブルに従属するという意味の「belonges_to:<テーブル名>」が自動で挿入されています。

class Comment < ApplicationRecord
  belongs_to :user
end

4.Userテーブルのmodelファイルを修正する

続いて、「<プロジェクトフォルダ>/app/model」配下にできる「user.rb」ファイルに以下を追加します。

class User < ApplicationRecord
    has_many :comment, dependent: :destroy
end

「has_meny:<テーブル>」で、従属されるテーブルを指定します。なお、テーブル間の関係が1対1の場合は「has_one:<テーブル>」を指定し、1対多の場合は「has_meny:<テーブル>」を指定します。今回は1ユーザに対し、コメントが多数ある想定なので「has_meny」を指定しました。

また、「dependent: :destroy」を指定すると、Userテーブルのレコードを削除した際に、関連するCommentテーブルのレコードがすべて削除されます。「gattsu09」ユーザを削除すると、「gattsu09」ユーザが書き込んだコメントが全て削除されるという具合になります。便利ですね。

5.migrateする

ようやく準備が整ったので、以下コマンドを実行してmigrateして関連付したテーブルの作成完了となります。

rails db:migrate

6.関連付けしたテーブルの活用方法

というわけで、テーブル間の関連付けが完了したので具体的に活用していきたいと思います。ここらへんはもう少し詳しく書こうと思いますが、疲れてきたので今日のところは簡単に…。

Userテーブルに「id:1」で、「name:gattsu09」のユーザが登録されており、Commentテーブルにgattsu09ユーザのコメントである「user_id:1」のレコードが複数あるとします。その場合、以下のように指定するだけでgattsu09ユーザのコメントを全て表示できます。

◆コントローラファイル
def top
  @user = User.find_by(id:1)
end
◆ビューファイル
<% @user.comment.each do | comment | %>
    <%= comment.comment %><br>
<% end %>

コントローラファイルでUserテーブルのみ指定すると関連するCommentテーブルの情報も取り出し可能になります。わざわざCommentテーブルをコントローラファイルで定義せずに済むのでメンテナンスしやすいです。

また、ユーザを削除するとき以下のように指定すると、gattsu09ユーザのコメントもCommentテーブルからすべて削除されます。便利ですね。

◆コントローラファイル

def user_destroy
    @user = User.find_by(id:1)
    @user.destroy
end

7.最後に

新年初の記事はDB関連となりました。独学なので色々参考にしながら試行錯誤しながら進めているのですが、やっぱり誰かに伝える体でブログにまとめると頭の中が整理されて良いですね。引き続き学んだ内容は、このブログにまとめていきたいと思うので2019年もよろしくお願いします。