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!

外部キーを持ってる投稿の外部キー元のデータを削除した際にも参照データが消えないようにする方法はありますか?

解決したいこと

プログラミング歴1ヶ月の初学者です。
現在railsを使ってタスクを追加し、ツイートの際に登録したタスクを選択、学習時間を入力し投稿する機能を作っています。学習時間は別テーブルで記録するようにしています。
今の設計だと、タスクを削除すると、タスクから外部キーをもらっているツイートのタスクも一緒に削除されてしまいます。
タスクは削除できるようにしたいけど、ツイートからタスクは消したくありません。
色々考えてみたのですが、改善策が見つかりません。
ここまで、作成するのもかなり時間をかけたので、諦めるのは気が引けてしまいます。
もし良い案やテーブル設計があればご教授お願いします!!
もしこのような機能が不可能であれば潔く諦めようと思います。

分かりにくいと思いますので、動画とER図を載せておきます↓

①タスクの追加
https://gyazo.com/cf08b4b914092552a3cc574d9d19eaf0
②ツイートの投稿
https://gyazo.com/f813c5e4c52727f4c2c6f4dc960c9091
③タスクの削除→ ツイートのタスクが消えてしまう
https://gyazo.com/7b3d8da69f26686b0340b20943d06372

ER図
https://gyazo.com/a25a5025c17e64f82394bb971ce751a6

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

タスクを削除するとツイートに表示されているタスクも削除されてしまう。

または、問題・エラーが起きている画像をここにドラッグアンドドロップ。

該当コード

app/views/tweets/_main_view.html.erb

<div class="top-contents">
  <div class="tweets-contents">
    <% @tweets.each do |tweet| %>
      <ul class="tweets-list">
        <li><%= tweet.user.nickname %>
        <% if tweet.category.present? %>
        <li><%= tweet.category.task %>
        <% end %>
        <li><%=  %></li>
        <li><%= tweet.text %></li>
      </ul>
    <% end %>
  </div>
</div>

自分で試したこと

色々なテーブル設計を考えましたがなかなか良い案が見つかりませんでした。
まだまだ未熟者ですが、皆様の知恵をお貸し下さい!よろしくお願いします!!

 追記

色々試して論理削除のgemのparanoiaを導入してタスクを削除し、無事論理削除は成功したのですが、画面に表示されているタスクは消えてしまいます。もちろんDB上にはデータが残っています。
外部キーをもらっているテーブル (tweetsテーブル)で論理削除したデータを含めた全データを画面に表示するにはどのように記述したら良いでしょうか??

tweetsコントローラーに @tweets = Tweet.with_deleted
のような記述をし、ビューに@tweetsを引っ張り、なんとか論理削除したデータごと取り出そうとしたのですが、ダメでした。

論理削除を導入後の挙動
https://gyazo.com/e5592c90a74b07ce23614086d0dd0beb
tweetsテーブルのレコード(category_idは削除されてない)
https://gyazo.com/33faabcc61103cae0b934e947cf27922
categoriesテーブルのレコード(論理削除が成功している)
https://gyazo.com/794fa4809c012bb4633e26a9b4ed4a6d

なかなか進めず苦戦しています
ご教授頂けると幸いです。

 追記

paranoiaというgemを使いタスクを削除してもツイートから消えないようにできました。
たくさんのご回答ありがとうございました!!

0

3Answer

外部キー制約のついたカラムを削除するとそういうもんなので、
削除フラグ をたてるのはいかがでしょうか?

削除フラグ でググるとわかるかと思います

1Like

Comments

  1. ご回答ありがとうございます!!
    削除フラグ調べてみました!
    こんな使い方もできるのですね!
    色々DBをいじってダメだったら最後の砦として使ってみます!

タスクから外部キーをもらっているツイート

タスクというのはER図のどれに該当します?
名称が違うと他の人からは分からないので、名称や表現は統一してあると分かりやすいです。

タスクは削除できるようにしたいけど、ツイートからタスクは消したくありません。

まず外部キーを参照しているカラムにNULLを許可します。

それから外部キーにNULLをセットしてから削除するようにします。
もしくは、MySQLを使用しているなら外部キー制約のふるまいを設定します。
MySQLの外部キーに外部キーには削除・変更された時のふるまいをそれぞれ設定できます。

  • RESTRICT
  • CASCADE
  • SET NULL
  • NO ACTION
  • SET DEFAULT

このようなオプションがあり、デフォルトでは削除や更新を行うとエラーになるRESTRICTが設定されています。
一緒に削除される、ということはCASCADEになっているのかもしれません。
SET NULLにすると削除や更新をした時にNULLがセットされます。

外部キーに関する詳しい説明はこちらなどを参照してください。
FOREIGN KEY制約(外部キー制約を設定する)

1Like

Comments

  1. 丁寧なご回答ありがとうございます!
    SET NULLの設定を改めてマイグレーションファイルに追記し、試した所、削除された外部キー部分にNULLがセットされたのですが、表記としては、やはり消えてしまいます。
    何か工程が抜けていたのでしょうか?
    tweetsテーブルのマイグレーションファイル
    https://gyazo.com/c4dabb7cc0201ea0c94bbd2f40990803
  2. データが想定どおりになっているのならデータ取得のSQLが問題ではないでしょうか?
    データ取得の処理が分からないのでなんとも言えないですが、
    予想としてはINNER JOINをしているのではないかと思います。

    JOINについてはこちらなどで調べてみてください。

    SQL素人でも分かるテーブル結合(inner joinとouter join)
    https://zenn.dev/naoki_mochizuki/articles/60603b2cdc273cd51c59

たくさんのコメントありがとうございます!!
paranoiaを導入しタスクを削除した事にした事で、ツイートの表示が消えなくなりました!!
皆様本当にありがとうございました!

0Like

Your answer might help someone💌