12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】アソシエーションで紐づいたレコードを自動保存

Posted at

概要

中級者は知ってて当然なので、初心者向けです🔰

アソシエーションで関連付けられたモデルを保存する時に、片方のレコードに外部キーが設定されているせいで、「保存処理を2回に分けなきゃ」と思ったことはないですか?(保存するまでidが確定しないので)

そんなときどうするのというお話です

※ 自分もかつて良くないコードを書いていたので、同じような初心者の参考になってもらえれば幸いです

具体例

例えば本のモデル(Book)と著者のモデル(Author)があると想定します
book has_many authorsの関係)

Bookモデル📕

カラム 補足
id integer
title string

Authorモデル:man_tone1:

カラム 補足
id integer
book_id integer 外部キー
name string

このとき初心者がやりがちなのが以下の書き方

books_controller
# createアクション

book = Book.new(book_params)
if book.save
  author = Author.new(book_id: book.id, name: author_params[:name])
    if author.save
      # 保存後の処理
    else
      # 失敗時の処理
    end
else
  # 失敗時の処理
end

# book_params, author_paramsの定義は省略してます

これだと以下のようにデメリットが大きいです

  • if文の階層が深くなる
  • bookだけ保存されてauthorが保存されない場合が出てしまう

早期リターンやtransactionでこれらを回避することもできますが、わざわざそんな面倒なことをしなくて済む方法があるのです✨(以下)

books_controller
# createアクション

book = Book.new(book_params)
author = book.build_author(author_params)
return ['保存成功時の処理'] if book.save

# 失敗時の処理

この場合bookの保存が成功した場合はauthorの保存も保証してくれます(片方だけ保存されることはない)

当然外部キーは関連付けられて保存されます
すっきりしていて見やすく、ファットコントローラ対策にもなります😍
※ 早期リターンでリファクタもしてます

モデルの関係性が、belongs_tohas_manyとで書き方が変わるので注意が必要です(以下参照)

belongs_toで関連付けられたモデルのbuild

book.build_author

has_oneでの関連付けもこちらになります

has_manyで関連付けられたモデルのbuild

author.books.build

  • 1つだけ紐づくモデル
    => build_[モデル名の単数形]

  • 複数紐づくモデル
    => [モデル名の複数形].build

と覚えとけば良さそうです😇
build_複数形にするとインスタンスが複数buildされるイメージがつくからこのように分けたんですかね🤔)

参考

12
10
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
12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?