ユーザと紐付けしたモデルから投稿を保存するのに躓いたので。備忘録として


はじめに

Qiita初投稿の初心者です。
間違いやもっとこうした方がいいなどツッコミ等お気軽に入れて頂ければと思います。
※冷やかしっぽいの普通に傷つくのでご勘弁下さい。

開発環境

・Ruby 2.5.5
・Rails 5.2.3
・エディタ VSCode

前提

・deviseを使ってUserモデルを作成ユーザ登録、ログイン機能実装済みです。
・UserProfileモデルを作ってUserモデルと1:1で紐付けを行っています。
(登録したユーザのプロフィール情報を保存します。)
・更にPostモデルを作って1:nでUserProfileモデルと紐付けを行っています。
(登録したユーザの投稿を保存します。)

※モデル設計が正しいかどうかは初心者なのでご了承下さい。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise  :database_authenticatable, :registerable,
          :recoverable, :rememberable, :validatable

  # user_profleモデルと1:1の紐付け
  has_one :user_profile, dependent: :destroy
end

※UserProfileモデルとPostモデル共にバリデーションなどは実装してません。

user_profile.rb
class UserProfile < ApplicationRecord
    # userモデルと1:1の紐付け
    belongs_to :user
    # postモデルと1:nの紐付け
    has_many :posts, dependent: :destroy
end
Post.rb
class Post < ApplicationRecord
    # user_profileと1:nの紐付け
    belongs_to :user_profile
end

今回の本題

・PostControllerのcreateアクションで保存しようとすると。

posts_controller.rb
  def create
    @post = Post.new(post_params)
    if @post.save!
      redirect_to user_profiles_path
    else
      redirect_to new_post_path
    end
  end

この様に保存しようとすると保存できませんでした。

ActiveRecord::RecordInvalid (バリデーションに失敗しました: User profileを入力してください):

app/controllers/posts_controller.rb:20:in `create'

因みにsave!の『!』はちゃんと何かあった際にスルーせず例外を発生させてくれます。
詳しくは他の方のブログ等にお任せします。

・エラーを見るとPostモデルと紐付けているUserProfileがない。と言われました。

解決

・Userモデルに紐ついているUserProfileモデルを呼び
それを@post.user_profileに代入する事でPostモデルに入っているuser_profile_idに値が入りちゃんと保存されました。

posts_controller.rb
  def create
    @post = Post.new(post_params)
    @post.user_profile = current_user.user_profile
    logger.debug(@post.inspect)
    if @post.save
      redirect_to user_profiles_path
    else
      redirect_to new_post_path
    end
  end

(logger.debug(調べたい変数.inspect)とするとログで変数に何が入っているか確認できます。)

・UserProfileControllerも同様でした。

user_profiles_controller
  def create
    @user_profile = UserProfile.new(user_profile_params)
    @user_profile.user = current_user
    if @user_profile.save!
      redirect_to user_profiles_path
    else
      redirect_to new_user_profile_path
    end
  end

以上です。

・初投稿で慣れてないので変な感じになっていたら言ってください。
・初心者が書いているコードなので参考になるかはわかりませんが誰かの参考になれたら幸せです。