Progateでは教えてくれなかったRuby on Railsのリレーションを調べてみた


はじめに

30歳のフリーランスのエンジニア ゆっけ(@prg_yukke)です。
生粋のPHPerでしたが、クライアントからRuby on Railsの案件の打診があっため、最近はやっているらしいProgateのRubyとRuby on Railsコースを学習してみました。
が、本当に初心者用の内容だったのか、リレーションの説明がないまま終わってしまったため、もやもやしていたので調べてみました。
つたない文章なので30歳のエンジニアがなんか言ってたなくらい覚えていてください。

読者想定

  • 私と同様に、ProgateにてRoRを学習を終了した人

RoRのリレーションについて

まず、RoRではリレーションとは言わず、アソシエーションと言います。
Laravelerな私にはあまり言い慣れませんが、CakePHPでもアソシエーションでした。

という事で改めて、

RoRのアソシエーションについて

Progateにおけるモデルの関連付け

ProgateのRoRレッスンでは、
Userモデルが所有するPostモデルの取得については、Userモデル内のwhereで、
Postモデルを所有しているUserモデルの取得については、Postモデル内のfind_byで定義しています。

Userモデル

class User < ApplicationRecord
  has_secure_password

  validates :name, {presence: true}
  validates :email, {presence: true, uniqueness: true}

  def posts
    return Post.where(user_id: self.id)
  end

end

Postモデル

class Post < ApplicationRecord
  validates :content, {presence: true, length: {maximum: 140}}
  validates :user_id, {presence: true}

  def user
    return User.find_by(id: self.user_id)
  end

end

アソシエーションへの書き換え

RoRでは、このようなモデル同士の関連付けをするのに便利な機能があります。
それがアソシエーションです。
モデルの定義に下記の6種類を使用することで、モデル同士の関連付けを簡単に行なえます。
- belongs_to
- has_one
- has_many
- has_many :through
- has_one :through
- has_and_belongs_to_many

今回のモデルを再確認してみると、
UserPostを複数所有し、PostUserに所有されています。
つまり、UserPostは一対多の関係です。

has_many : 他モデルを複数所有している場合

他モデルを複数所有している際のアソシエーションには、has_manyを使用し、
has_many :モデル名の複数形の形で記載します。

このため、Userモデルは下記の形に書き換えられます。

  • Userモデル
class User < ApplicationRecord
  has_secure_password

  validates :name, {presence: true}
  validates :email, {presence: true, uniqueness: true}

  has_many :posts

end

belongs_to : 他モデルに所有されている場合

逆に今回のPostモデルの様に他モデルから所有されている場合、
belongs_toを使用し、belongs_to :モデル名の単数形の形で記載します。

belongs_toを使用したPostモデルは下記のとおりです。

  • Postモデル
class Post < ApplicationRecord
  validates :content, {presence: true, length: {maximum: 140}}
  validates :user_id, {presence: true}

  belongs_to :user

end

まとめ

LaravelやCakePHPがRoRを参考にしただけあり、言語仕様による書き方の際はありますが、リレーションの形はほぼ変わらずでした。

アソシエーションを使用することで、モデル内にクエリビルダを記載せずに他モデルとの関連付けが可能になりますので積極的に使用してみてください。

has_manybelongs_toの他、
一対一のアソシエーションにはhas_oneを、
結合モデルが介在する場合はhas_many :through, has_one :through
多対多の場合にはhas_and_belongs_to_manyを使用しアソシエーションの定義が可能です。

詳しくは、Rails GuideのActive Record の関連付け (アソシエーション)を御覧ください。