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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PostgreSQL

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

5824閲覧

Ruby on Rails 外部キー制約によりデータが削除できません。

riamk

総合スコア47

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PostgreSQL

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2017/06/17 13:32

編集2017/06/18 00:16

###前提・実現したいこと
Rails4 PostgreSQL

現在、railsでdeviseを使用しログイン機能を実装し、ログインユーザーがユーザー同士、個別にメッセージのやり取りができるようにしました。

具体的なテーブル構成は

usersテーブル(ユーザ情報を格納する) conversationsテーブル(会話情報を格納する) messagesテーブル(会話の個々のメッセージを格納する)

このようにしました。

現在のコードではメッセージをやり取りしたユーザーが退会すると外部キー制約によりデータが削除できないというエラーが発生してしまいます。

どこを修正すればいいかアドバイスをお願いします。

###発生している問題・エラーメッセージ

メッセージのやり取りをしたユーザーが退会(ユーザーの削除)しようとすると以下のようなエラーが出てユーザーを削除することができません。

PG::ForeignKeyViolation at /users ERROR: update or delete on table "users" violates foreign key constraint "fk_rails_273a25a7a6" on table "messages"

###該当のソースコード
message.rb

ruby

1class Message < ActiveRecord::Base 2 belongs_to :conversation 3 belongs_to :user, dependent: :destroy 4 5 validates_presence_of :body, :conversation_id, :user_id 6 def message_time 7 created_at.try(:strftime,"%m/%d %R") 8 end 9end

conversation.rb

ruby

1class Conversation < ActiveRecord::Base 2 belongs_to :sender, foreign_key: :sender_id, class_name: 'User' 3 belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User' 4 has_many :messages, dependent: :destroy 5 validates_uniqueness_of :sender_id, scope: :recipient_id 6 scope :between, -> (sender_id,recipient_id) do 7 where("(conversations.sender_id = ? AND conversations.recipient_id =?) OR (conversations.sender_id = ? AND conversations.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id) 8 end 9 10 def target_user(current_user) 11 if sender_id == current_user.id 12 User.find(recipient_id) 13 elsif recipient_id == current_user.id 14 User.find(sender_id) 15 end 16 end 17end

今はこのようにコードを書いています。
他に必要なコードがあれば記載しますので、ご教授よろしくお願いします。

###補足・追記
Messagesテーブルのマイグレーションファイル

class CreateMessages < ActiveRecord::Migration def change create_table :messages do |t| t.text :body t.references :conversation, index: true, foreign_key: true t.references :user, index: true, foreign_key: true t.boolean :read, default: false t.timestamps null: false end end end

Conversationsテーブルのマイグレーションファイル

class CreateConversations < ActiveRecord::Migration def change create_table :conversations do |t| t.integer :sender_id t.integer :recipient_id t.timestamps null: false end end end

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

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

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

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

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

guest

回答2

0

messagesテーブルの対象データを先にDELETEするか、FOREIGN KEYにON DELETE CASCADE付きで外部制約を付け直されては?

実務としてはユーザーが退会したらすぐDELETEして良いものか?悪質なユーザーの再入会の回避するために、論理削除としてDELETE_FLAGを立てたり、退会済み用のテーブルに情報を残すことが多いです。

投稿2017/06/17 23:34

Orlofsky

総合スコア16415

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

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

riamk

2017/06/18 00:21

ご回答ありがとうございます。 実務としてのご意見は勉強している中で触れることがない部分で、「退会済み用のテーブルに情報を残す」とかとても参考になります。 外部制約の付け方について調べてみながら、再度トライしてみます!
guest

0

ベストアンサー

モデルの記述が問題と言うよりは、DBレベルでの問題な気がします。
マイグレーションファイルで、foreign_key制約はつけていますか?
どこに付けているかにも依りますが、そのあたり見せて頂けると原因が分かると思います。

投稿2017/06/17 17:16

Miracle

総合スコア54

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

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

riamk

2017/06/18 00:18

ご回答ありがとうございます。 私のそもそもの視点が間違っていたのですね。 マイグレーションファイルの中身を追記しましたので、何かアドバイス頂けると嬉しいです。 よろしくお願いします。
Miracle

2017/06/18 02:37

`t.references :user, index: true, foreign_key: true` この記述が、ユーザーを削除出来ない原因かと思います。 messagesテーブルのuser_idカラムにかけているforeign_keys制約が、ユーザーの削除を防いでいる感じですね。 userモデルに、user has many messagesというリレーションが定義されていると思いますが、そこでdependent のオプションに delete_allとかを付けたら、解決できるかもです。 http://blog.sanojimaru.com/post/18426241191/activerecordhasmany%E3%81%AEdependent%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3 ただ、データの整合性を保つのがforeign_keyをつける目的なので、その意味ではOrlofskyさんが仰られているような実装方法のほうが良いかと思います。 また、別の話になりますが、messageモデルに書かれている `belongs_to :user, dependent: :destroy` のdependent destroyオプションは付ける必要が無さそうですね。
riamk

2017/06/18 06:04

ご教授ありがとうございます。 Miracleさんのアドバイスを参考にもう一度foreign_keyについて学習し直してチャレンジしてみようと思います。 messageモデルのdependentオプションは色々と試していてそのままになってしまっていました。 ご指摘ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問