uepon0227
@uepon0227 (O Y)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

外部キーが保存できない

解決したいこと

Ruby on RailsでWebアプリをつくっています。
タグを追加する機能の実装中にエラーが発生しました。
解決方法を教えて下さい。

発生している問題・エラー

eventテーブルとtagテーブルは入れ子構造の関係で、tagテーブルに外部キーevent_idを保存したいのですが保存できません。

エラーメッセージ

ActiveRecord::RecordInvalid in TagsController#create
Validation failed: Event must exist
ruby '2.6.5'

'rails', '~> 6.0.0'

tags_controller.rb

class TagsController < ApplicationController

  def index
    @tags = Tag.all
  end


  def new
    @tag = Tag.new
  end

  def create
   if Tag.create(tag_params)
    redirect_to tags_path
    else
      render :new
    end
  end

private
  def tag_params
    params.require(:tag).permit(:tag_name).merge(event_id: params[:event_id])
  end

end

tag.rb

class Tag < ApplicationRecord

  validates :tag_name, presence: true

  belongs_to :event
end

event.rb

class Event < ApplicationRecord
  validates :event_name, presence: true

  belongs_to :user
  has_many :tags
end

routes.rb

Rails.application.routes.draw do
  devise_for :users
  root to: 'events#index'
  resources :users, only: :show
  resources :tags, only: [:index, :new, :create, :edit, :destroy]

  resources :events do
    resources :tags, only: [:index, :new, :create, :edit, :destroy]
end
end

event_controller

class EventsController < ApplicationController


  before_action :move_to_index, except: [:index]

  def index
    @events = Event.includes(:user)
  end

  def new
    @event = Event.new
  end

  def create
    if Event.create(event_params)
      redirect_to events_path
      else
        render :new
    end
  end

  def destroy
    event = Event.find(params[:id])
    event.destroy
  end
  

  private
  def event_params
    params.require(:event).permit(:event_name).merge(user_id: current_user.id)
  end

  def move_to_index
    unless user_signed_in?
      redirect_to action: :index
    end
  end
  
end

自分で試したこと

外部キーの保存といいうことで、モデルに関連づけをして入れ子構造の再確認をしました。paramsのevent_idがnillのままで変化はありませんでした。。。

わかる方いましたらご教示お願いいたします🙇‍♀️

0

2Answer

Tagを保存する際にbelongs_toで関連付けしているeventの存在チェックが行われ、関連するeventが存在しないためエラーとなっています。

以下のエラーメッセージからもその内容が読み取れると思います。

Validation failed: Event must exist

tagにeventが紐づかない状態を許容するのであればbelongs_tooptional: trueのオプションを付与することで解決できます。

belongs_to :event, optional: true

eventが紐付くことが必須であれば事前にeventを作成しておくとかtagの作成時に合わせてeventも作成するとか適切な方法を考えていただければと思います。

optionalの指定については以下を参考にしてください。

1Like

Comments

  1. @uepon0227

    Questioner

    回答ありがとうございます。tagテーブルに保存する際に、event_idも紐づけることが必須でして、optional :trueも以前してみましたが、やはりevent_idの取得ができませんでした。eventコントローラーのcreateアクションでevent_idはSeaquel Proで保存されているのは確認したので紐付けがうまくいっていないのかと思いました。belongs_toや入れ子構造以外にtagコントローラーにそのevent_idと紐づける何かしらの追記が必要なのですかね?😅
  2. event_idの紐づけが必須ということですね。そうするとoptional指定は適切ではありませんでした、質問の意図を理解できておらず失礼しました。

    event_idがパラメータとしてコントローラに適切に渡されていることは確認済でしょうか?
    もしまだでしたらログやWebコンソールで確認することができます。
    event_idがパラメータで渡されていない場合はviewファイル側に原因がないか確認してみてください。
    パラメータで渡されている場合はその後の処理でevent_idが失われたりnilに書き変わっていないか、Tagをcreateする際のパラメータの渡し方が適切かを確認すると良いと思います。
  3. @uepon0227

    Questioner

    はい、パラメータで渡されるtag_paramsの中にevent_idがnilになっていて、コントローラーに上手く渡せていない状態です。パラメータの渡し方かルーティングのネストがうまくいっていないような気がします。
  4. そこまでわかっているのであればあと一歩のように思えます。
    以下の観点で確認されてはいかがでしょうか。
    ・rails routesコマンドを実行した結果はどのようになりますか?
    ・POSTしているURLは/events/:event_id/tagsのようにURLにevent_idを含む形式になっていますか?

内部処理の移り変わりが激しいので
RailsとRubyのバージョンを正確に記載した方が
回答が得やすいと思います。

0Like

Comments

  1. @uepon0227

    Questioner

    コメントありがとうございます。参考になりました。追記してみます!
    ありがとうございます!

Your answer might help someone💌