LoginSignup
5
4

More than 3 years have passed since last update.

has-oneとhas_manyの違いについて、まとめてみる

Last updated at Posted at 2020-06-01

はじめに

railsしっかり勉強し始めて、半年くらいたちます。(多分)
最近学んだこと多いので、アウトプットしていきますー。
ちょっと説明下手だったり、間違ってたりする部分あるかもしれないので、ご了承ください!!

has_oneとhas_manyって?

両方とも、モデルの関係定義に使われるものです。

has_oneとは、1つのモデル(親)に対して、1つのモデル(子)を持つこと(1対1の関係を持つ)ができるということを定義する場合に使います。
例:)1つの投稿に対して、画像を1枚添付することができる。

has_manyとは1つのモデル(親)に対して、たくさんの同じモデル(子)を持つこと(1対多の関係を持つ)ができることを定義する場合に使います。
例:)1つの投稿に対して、画像を複数枚添付することができる。

違いについて

has_onehas_manyで関連づけられたモデルを親と関連づけて作成したい場合、それぞれ作成方法が異なるので、気をつけましょう!

実際のコードを見てみる

画像.rb
class Image < ApplicationRecord
  mount_uploader :image, ImageUploader
  belongs_to :tweet_image, foreign_key: :tweet_id, optional: true  #optional: trueをつけることによって、外部キーがなくても、保存できる
end
モデル.rb
class TweetImage < Tweet
  validates :content, presence: true, length: { maximum: 140 }
  belongs_to :user
  has_one :image, foreign_key: :tweet_id
  accepts_nested_attributes_for :image, allow_destroy: true
end

ここのコードだと、accepts_nested_attributes_for :imageを使って、TweetImageを保存する時、同時に子モデルのImageを保存するので、Imageモデルのファイルにoptional: trueをつけて、外部キーが存在しなくても保存できるようにしておくことが必要です。

class TweetsController < ApplicationController
  before_action :authenticate_user!
  def new
    @tweet = TweetImage.new
    @tweet.build_image #has_oneの関係の場合
  end
class TweetsController < ApplicationController
  before_action :authenticate_user!
  def new
    @tweet = TweetImage.new
    @tweet.images.build #has_manyの関係の場合
  end

上記は私が、制作物を作った際につかっているコードです。
関係性を図で表すとこんな感じです。

image.png

TweetとTweetImageはSTIを使った継承関係で、
TweetImageはhas_oneで画像(Imageモデル)を持っています。
コントローラはTweetのコントローラのみで管理しているので、画像を添付する場合のために必ずはじめはTweetImageである必要がありました。(accepts_nested_attributes_forを利用しているため、Formの部分に画像添付の部分を出せなくなってしまうため。)

newでモデルを作ることもできますが、IDを1回ごとに渡さないといけないので、少し面倒です。buildを使うと、自動でIDを入れてくれるので、簡潔にコードを書くことができます。

buildとnewの違い参考ページ

最後に

説明が物足りてないところがありますが、ここで終わります!
ここ違うよってとこありましたら、コメントでご指摘お願いします!!

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4