脱・Rails初心者!子モデルのインスタンス生成と同時に親モデルに紐付ける方法

はじめに

こんにちは、TECH DRIVEのTedです。

今回はRuby、Ruby on Railsを学習されている初学者へ向けた、初学者から1歩レベルアップするためのコードの書き方をご紹介します。開発現場でよく使われる書き方の1つでもあるのでぜひ習得してみてください!

本題

親子関係のテーブルで親テーブルに紐づいた子テーブルのインスタンスを作るときに親のテーブルのidを簡単に持たせることができます。結果的にコントローラーやモデルに書く処理を少なくすることができます。

例えばユーザーの情報を持つusersテーブルとユーザーの投稿の内容を持つpostsテーブルがあったとします。下記のような感じ

f:id:travy:20190320151608p:plain

class User < ApplicationRecord
  has_many :posts
end

class Post < ApplicationRecord
  belongs_to :user
end

userspostsの親になります。そして、サービスの中でユーザーが入力した内容をpostsテーブルのデータとして保存する処理があるとします。

ツイッターをイメージすればわかりやすいと思います。ユーザー(users)とツイート(posts)のような関係です。

ここで子テーブルと親テーブルを紐づけるときにいくつか方法がありますが普通に書くと下記のようになると思います。

class PostsController < ApplicationController
  before_action :set_user
  # 他のアクション
  def new
    @post = Post.new
  end
  
  def create
    @post = Post.new(post_params)
    @post.user_id = @user.id
    if @post.save
    # 保存が成功した時の処理
    else
    # 失敗したときの処理
    end
  end
  
  private
  def set_user
    @user = User.find(params[:user_id])
  end
  
  def post_params
    params.require(:post).permit(:title, :body)
  end
end

上記は特に問題はないのですが、さらに下記のように書くこともできます。

class PostsController < ApplicationController
  before_action :set_user
  # 他のアクション
  def new
    # ここがポイント!↓
    @post = @user.posts.new
  end
  
  def create
    # ここがポイント!↓
    @post = @user.posts.new(post_params)
    if @post.save
    # 保存が成功した時の処理
    else
    # 失敗したときの処理
    end
  end
  
  private
  def set_user
    @user = User.find(params[:user_id])
  end
  
  def post_params
    params.require(:post).permit(:title, :body)
  end
end

2つのコードの違いはnewcreateアクション の中にあります。
Postモデルのインスタンスをnewするときに親であるUserモデルに紐づけてnewしているかどうかです。
こうすることで新しく作られたPostモデルのインスタンスは親であるUserモデルのid、つまりuser_idを最初から持っている状態になります。
逆にPost.newで作るとuser_idはあとでセットしなくてはなりません。

# これが
@post = Post.new(post_params)
@post.user_id = @user.id
# こうなる
@post = @user.posts.new(post_params)

これで少ないコードで実装できて投稿される内容はユーザーに紐づいていることがすぐにわかりそうです。

おしまいに

今回はコントローラーに処理を書いてご紹介しましたが、親子関係の子にあたるモデルのインスタンスを作るときは他の場所でも同じことができます。(例:モデルのメソッド内とか)

こういったコードが書けるだけで他の初学者と1歩差をつけることができますし、現場のエンジニアが見ても「こいつ、わかってるな」とアピールすることができます。

私もよく自作のサービスで前者のようなコードをよく書いていました。 しかし、同じ動作が期待できるコードでも書き方によってあとで見る人やあとで自分で見たときに「これは何か意味があるのだろうか?」と迷ってしまうこともあります。

ご自分でサービスやコードを書かれている方は、本記事の内容を踏まえてもう1度自分のコードを眺めて見るのも良いかもしれません。
このような細かい配慮の積み重ねが読みやすいコードに繋がります!

PR

TECH DRIVE協賛企業のサークルアラウンド株式会社では、プログラマーの成長を加速させるためのトレーニングを行なっています。フロントエンド/バックエンド問わず各種バリエーションがございますので、ご興味がある方は是非以下のリンクより詳細をご覧ください。

Ruby Climbing

週1からはじめられる「Ruby」でWEB開発の基礎が習得できる塾です。現役のプログラミング講師&Rubyエンジニアがプログラミング入門からフレームワーク(Sinatra/Ruby on Rails)を使用した本格的なWEB開発の学習までをしっかりとサポートします。

ruby climbing

個別トレーニング

短期間でぐっと成長したい方は弊社主催の個別トレーニングがおすすめです。 トレーニング内容は、受講者の方の課題/要望をお伺いした上で、フルオーダメイドで作成させていただきます。 詳細は以下のリンクよりご確認ください。(応募者多数の場合には時間を別途ご用意する予定です)。

WEBプログラミング個別トレーニング

TECH DRIVEについて

TECH DRIVEは「技術者の成長を加速させる」をキーワードに都内で活動をしているコミュニティです。
TwitterやFacebookにて技術ネタやイベント情報の発信を行っていますので、ご興味があれば、いいねやフォローをお願いいたします。