はじめに
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
今回のモデルを再確認してみると、
User
はPost
を複数所有し、Post
はUser
に所有されています。
つまり、User
対Post
は一対多の関係です。
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_many
とbelongs_to
の他、
一対一のアソシエーションにはhas_one
を、
結合モデルが介在する場合はhas_many :through
, has_one :through
、
多対多の場合にはhas_and_belongs_to_many
を使用しアソシエーションの定義が可能です。
詳しくは、Rails GuideのActive Record の関連付け (アソシエーション)を御覧ください。