質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

1回答

1047閲覧

PostgreSQL がアソシエーションのないテーブルを参照する(Rails, 多対多)

okutamatanuki

総合スコア8

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2020/08/13 14:06

動作環境

  • Rails 5.2.4.2
  • PostgreSQL 12.2

前提

従業員の活動を記録するデータベースにおいて、従業員(employees) は 活動(activities)と多対多の関係にあります。

下記のようなUIで一気に活動に参加した従業員を記録したく、

イメージ説明

次のようにコードを書きました。

作成したコード

Model
activitiesとemployeesで多対多の関係を定義し、中間テーブルをactivity_employeesとしています。

Ruby

1class Employee < ApplicationRecord 2 has_many :activity_employees, dependent: :destroy 3 has_many :activities, through: :activity_employees 4end

ruby

1class Activity < ApplicationRecord 2 has_many :activity_employees, dependent: :destroy 3 has_many :employees, through: :activity_employees 4 accepts_nested_attributes_for :activity_employees, allow_destroy: true 5 6 # 今回のエラーに関係ありそうなので入れています 7 has_many :activity_logs, dependent: :destroy 8 has_many :staffs, through: :activity_logs 9 accepts_nested_attributes_for :activity_logs 10end

ruby

1class ActivityEmployee < ApplicationRecord 2 belongs_to :activity 3 belongs_to :employee 4end

Controller
一気にデータを受け取れるよう、{employee_ids: []}をstrong paramaterに入れています。

ruby

1class ActivitiesController < ApplicationController 2 # 略 3 def create 4 @activity = @facility.activities.build(activity_params) 5 if @activity.save 6 # 処理 7 else 8 # 処理 9 end 10 end 11 12 private 13 def activity_params 14 params.require(:activity).permit( 15 :activity_type, 16 # 略, 17 {employee_ids: []}, 18 activity_logs_attributes: [:staff_id, :carried_out, :got_appointment]) 19 end 20end

View

ruby

1= form_with model: [@facility, @activity], class: "p-input-form", local: true do |f| 2 3 = f.collection_check_boxes :employee_ids, @employees, :id, :name, include_hidden: false do |t| 4 = t.label(class: "c-check-box__label mr-4") { t.check_box(class: "c-check-box") + t.text }

起こっている問題

上記のコードでデータを保存しようとすると、下記のエラーが出ます。
イメージ説明
staffsテーブルにデータを保存しようとはしていないのに、なぜ、staffsテーブルの参照整合性を崩すというエラーが出るのかわかりません。

調べたこと

activity_paramsとして送っているデータの中身を調べました。

[1] pry(#<ActivitiesController>)> activity_params => <ActionController::Parameters { "activity_type"=>"event", # 中略 "employee_ids"=>["33"],  "activity_logs_attributes"=><ActionController::Parameters { "0"=><ActionController::Parameters { "staff_id"=>"1", "carried_out"=>"false", "got_appointment"=>"false" } permitted: true> } permitted: true> } permitted: true>

特にネストがおかしいところはなさそうです。
なぜ、アソシエーションがないはずのstaffsテーブルの参照性を崩すというエラーが出いるのでしょうか?考えられる点だけでもアドバイスいただけると嬉しいです。

どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

databaseの方にfkの定義がされているような気がします。
rails db:schema:dump
して現在のDBの状況を取り出し、db/schema.rbを見せてください。

投稿2020/08/13 23:39

winterboum

総合スコア23567

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okutamatanuki

2020/08/14 00:50 編集

ありがとうございます! 昨晩、自分でもFKがstaff_idになっているのでは、と気づき調べておりました。 `rails db:schema:dump` を実施した後の、schemaファイルはこちらです。 ```Ruby create_table "activity_employees", force: :cascade do |t| t.bigint "activity_id" t.bigint "employee_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["activity_id"], name: "index_activity_employees_on_activity_id" t.index ["employee_id"], name: "index_activity_employees_on_employee_id" end ``` マイグレーションファイルをさかのぼって調べたところ、過去にこのようなファイルを作成しており、 ```ruby class CreateActivityEmployees < ActiveRecord::Migration[5.2] def change create_table :activity_employees do |t| t.references :staff, foreign_key: true t.references :facility_employee, foreign_key: true t.timestamps end end end ``` その後、このように変更していました。 ```ruby class RenameStaffIdColumnToActivityEmployees < ActiveRecord::Migration[5.2] def change rename_column :activity_employees, :staff_id, :activity_id end end ``` この時に、参照する外部キーを変更していなかったので、引き続き`staffs`テーブルを参照し続けているのかと思い、以下のマイグレーションを実行したのですが ```ruby class ChangeReferencesOfActivityEmployeesTable < ActiveRecord::Migration[5.2] def change remove_reference :activity_employees, :staff, foreign_key: true add_reference :activity_employees, :activity, foreign_key: true end end ``` 現在このようなエラーが出て解決に苦しんでいます。 ```ruby == 20200814003145 ChangeReferencesOfActivityEmployeesTable: migrating ========= -- remove_reference(:activity_employees, :staff, {:foreign_key=>true}) rails aborted! StandardError: An error has occurred, this and all later migrations canceled: Table 'activity_employees' has no foreign key for {:to_table=>"staffs", :column=>"staff_id"} ``` まずは外部キーを削除してから、再び追加する、というようなマイグレーションにしてみようと思います。
okutamatanuki

2020/08/14 01:04

こちら、マークダウンが使えないのですね。。。失礼いたしました。 下記のようなマイグレーションを書いたら解決しました! =============== class ChangeReferencesOfActivityEmployeesTable < ActiveRecord::Migration[5.2] def change remove_foreign_key :activity_employees, :staffs add_foreign_key :activity_employees, :activities end end =============== おかげさまで、こうかな?と思っていたことに確証を持てたので、ベストアンサーにさせてください。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問