見出し画像

Ruby on Rails アソシエーションの基礎について🎉

はじめに〜

目 的
この記事は10月から約1ヶ月の間、私が学んだことを
 1.OUTPUTする
 2.思考の整理
 3.これから取り組まれる方への共有
以上3つの目的から投稿しています。

Ruby on Railsを選んだ理由〜

結論
・高速にアプリケーションを実装できる

こいうとこがいい
・便利なライブラリが豊富
・検索ヒット数が多い(エラーの時役立つ)
・パターン化されている
・少ないロジックですむ

この記事の内容〜📗

結論
・モデルのアソシエーション(関連付け)の内容(13-14章)。

理由 
・Ruby on Railsチュートリアルの中で一番苦労した部分だから
・モデルを理解できていないと正しく設計できないから
※ここが理解できていないと...カオスなテーブルの完成....😱
作成したwebアプリケーション
・いいね機能(ファボ)がない簡易版twitterです
イメージ下記に添付します。

この記事で扱ってない内容〜🙅‍♂️

・そもそもモデル(model)ってなんぞや??🤔
・MVC(model|view|controller)について
・Railsってなに?
・FW(フレームワーク)の説明
・Ruby言語のロジックの解説
・クラスだったりオブジェクト指向とか 

MVCモデルに関しては参考になりそうなQittaの記事(LGTM300以上)
を埋め込んでおきます。

Ruby on Railsチュートリアルのリンクも埋め込んでおきます。
興味がある方は覗かれみてください。

こんな人に読んでほしい〜👀

・駆け出しエンジニア
・これからRuby on Railsに取り組まれる方
・現在取り組んでいる方
・モデルの関連付けがあやしい方
・個人開発をこれからしたい方

注意点〜⚠️

・間違ってる内容が含まれているかもしれません
・現場での内容は網羅できていません
 →Railsの実務経験がない為

それでは早速、はじめて行きまっしょうかっ✈️

登場人物(モデル)の整理〜 親子👨‍👩‍👧‍👦

大きくモデルは3つのクラスしか作成しません、以下の構成です。
この3つのモデルがRailsで用意されている、ActiveRecordによってDB上のテーブルと紐づいています。
----------------------------
親:User -利用者の管理
子:Micropost - ツイートを管理
子:Relationship -フォロー、フォロワーの管理をする
----------------------------
関連付けをすることにより、
・誰がツイートをしたのか
・フォローする、フォローされる関係
が分かるようになります。

このように関連付けをする際にモデル同士の親子関係がどうなってるのか
を整理することが大事です。うーん、難しいですね(・・;)

1対多の関係(one-to-many) UserとMicropost🍎

関係
親子関係です
Mciropost(ツイート)はUserがいないと生まれない!!
→Micropostは誰か一人のUserに従属している関係です
 一人一人のUserは沢山のMicropost(ツイート)を持つことができる

モデル同士の関連付けを行う為には、外部キー(foreign_key)を設定します。
イメージはこのようになります。
この関連付けを行うことで誰がツイートを投稿したのかが紐付きます〜
下記画像は
Micropostからみた👀User、Userから見た👀Micropostの関係です🤝

Railsチュートリアル 引用

このような関係を1対多(one-to-many)と言われています
実際にコードで書いてみます⌨️

利用者の管理
バリデーション、属性は今回は割愛
class User < ApplicationRecord
    ユーザーから見てマイクロポストは複数ある
    has_many :microposts, dependent: :destroy

end

解説
>has_many :モデル名(複数形)
>dependent: :destroy > ユーザーが削除された時にユーザーに紐付いた投稿も削除する
これで変なデータが残る心配もなさそうです
ツイートの管理
class Micropost < ApplicationRecord
    マイクロポストから見てユーザーは一人
    belongs_to :user

end

解説
>belongs_to :モデル名(単数形)

これでUserを介してmicroposts(配列データ)を取得できようになりました✨

多対多の関係(many-to-many) UserとRelationship🍇

超大事‼️
Userモデルが一つしかない為、フォローする側・フォローされる側に切り分ける必要があります!!
今からやること Userの自己結合を行います
ここで一旦Userモデルを忘れてfollowingモデル(仮)follower(仮)モデルがあるとして考えていきます。
多対多の関係の場合、必ず中間モデルが必要となる為
このfollowingモデルとfollowerモデルの主キーを管理する為のRelationshipモデルを作成します。

このようになりましたっ

さらにもう一歩、これまのでリレーションも合わせUserに置き換えると🙋‍♂️

段々それっぽくなってきましたねー(^_^;)
ですが、「Userモデル」の呼び方だとどっちかわからない為、
followingモデル、followerモデル名に変更したいです。。。
でもUserモデルは一つしかありません(T ^ T)?どうすればええんや。。。。
class_nameというオプションを使ってモデル名を変更します!!

実際にコードを書いていきます!

Relationshipモデルの設定

中間テーブル
class Relationship <&nbsp;ApplicationRecord
    belongs_to :user
    belongs_to :followed,  class_name: "User"
    belongs_to :follower,  class_name: "User"

end

解説
belongs_to :変更したい親モデル名, class_name: "元々の親モデル名"

Relationshipモデルへ「Userモデル名」を
following、followerモデル名へ変更しましたので、続いてUserモデルへも関連付けを行います。

Userモデルの設定 以下のように定義します
フォローする側のUserからみたRelationshipをactive_relationshipフォローされる側のUserからみたRelationshipをpassive_relationshipとする
また、親モデルの外部キーも忘れずに追加するようにしていきます〜

利用者の管理
バリデーション、属性は今回は割愛
class User < ApplicationRecord
    ユーザーから見てマイクロポストは複数ある
    has_many :microposts, dependent: :destroy
    
    フォローする側
    has_many :active_relationships,  class_name: "Relationship",
                                     foreign_key: :follower_id,
                                     dependent: :destroy
    
    
    フォローされる側
    has_many :passive_relationships, class_name: "Relationship",
                                     foreign_key: :followed_id,
                                     dependent: :destroy
    
    中間テーブルを介して「follower」モデルのUser(フォローされた側)を集めることを「followings」と定義
    has_many :followings, through: :active_relationships, source: :followed                                      
    
    
    
    中間テーブルを介して「following」モデルのUser(フォローする側)を集めることを「followers」と定義
    has_many :followers,  through: :passive_relationships, source: :follower

end

解説
foreign_key: :外部キー(主キー)を保存する為のキー
dependent: :destroy > ユーザーを削除したら ユーザーのリレーションシップも同時に削除される必要がある
source: :参照モデル

これでフォローする、される側の関係ができました🤝 
いやー慣れるまで結構癖がありますね〜
あとは実際にアプリケーションを作りながら覚えていきたいと思います。

多 対 多の時に意識すること下記に記載します〜
---------------------------------------
Userモデルが一つのため、名前が重複しないようにclass_nameオプションを使用し、名称を変更する
foreign_keyを忘れずに記述する→親のテーブルのPK(主キー)を保存する為のキー
foreign_keyを管理する為の中間テーブルを設ける
---------------------------------------

まとめ〜🥂

学んだことをこのように形に残すことができました!
今後はアニメレビューサイトの作成に入りたいと思います。
その際に必ず、登場人物やモデルの関連付けが必要になりますので
今回の経験を活かしたいと思います☆
ここまでお付き合いいただき本当にありがとうございました✨

では また🖐

この記事が参加している募集

スキしてみて

やりたいことしかできない病 アニメが大好きです。 2年未満ITエンジニアで正社員で働いていました。 主にAndroidアプリの機能改修や追加、保守担当 現在はやりたいことを模索中☆ 言語 Java/VB/PHP/SQLなど....現在Rails学習中 Pythonも少しかじる