ruby-on-rails 由于SQLite3::ConstraintException:FOREIGN KEY约束失败(ActiveRecord::InvalidForeignKey)错误,无法删除用户

kxe2p93d  于 2023-11-20  发布在  Ruby
关注(0)|答案(2)|浏览(163)

我是一个Ruby on Rails应用程序的初学者,我想确保删除用户也会删除其关联的消息、参与者和房间。我已经建立了关联,但我面临删除过程的问题。这是一个具有聊天功能的业务目录,在构建它之后(遵循一些教程),我发现我无法删除用户
我有以下型号:用户

class User < ApplicationRecord
  # ... (other code)
  has_many :messages, dependent: :destroy
  has_many :participants, dependent: :destroy
  has_many :rooms, through: :participants, dependent: :destroy
  # ... (other code)
end

字符串

参加者

class Participant < ApplicationRecord
  belongs_to :user
  belongs_to :room
end

房间

class Room < ApplicationRecord
  has_many :messages, dependent: :destroy
  has_many :participants, dependent: :destroy
end

留言内容

class Message < ApplicationRecord
  belongs_to :user
  belongs_to :room
  after_create_commit { broadcast_append_to room }
  before_create :confirm_participant
end

我的架构

ctiveRecord::Schema[7.0].define(version: 2023_11_17_214308) do
  create_table "active_admin_comments", force: :cascade do |t|
    t.string "namespace"
    t.text "body"
    t.string "resource_type"
    t.integer "resource_id"
    t.string "author_type"
    t.integer "author_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author"
    t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
    t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource"
  end

  create_table "admin_users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_admin_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true
  end

  create_table "messages", force: :cascade do |t|
    t.integer "user_id", null: false
    t.integer "room_id", null: false
    t.text "body"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["room_id"], name: "index_messages_on_room_id"
    t.index ["user_id"], name: "index_messages_on_user_id"
  end

  create_table "participants", force: :cascade do |t|
    t.integer "user_id", null: false
    t.integer "room_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["room_id"], name: "index_participants_on_room_id"
    t.index ["user_id"], name: "index_participants_on_user_id"
  end

  create_table "rooms", force: :cascade do |t|
    t.string "name"
    t.boolean "is_private", default: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "username"
    t.string "email", default: "", null: false
    t.string "password_digest"
    t.string "profession"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "role", default: 0
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.string "firstname"
    t.string "lastname"
    t.string "phone_number"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

  add_foreign_key "messages", "rooms", on_delete: :cascade
  add_foreign_key "messages", "users", on_delete: :cascade
  add_foreign_key "participants", "rooms"
  add_foreign_key "participants", "users"
  add_foreign_key "services", "locations"
end


我试着在关系中乱加乱删,以至于我担心我可能把事情弄得更糟。

sczxawaw

sczxawaw1#

首先,几点注意事项:

has_many :participants, dependent: :destroy
has_many :rooms, through: :participants, dependent: :destroy
# this `dependent: :destroy` is redundant ^

# so is this one    v
has_many :messages, dependent: :destroy
# because you have sqlite deleting it  v
add_foreign_key "messages", "users", on_delete: :cascade

# messages should probably belong to Participant in this set up
class Message < ApplicationRecord
  belongs_to :participant
end

字符串
你展示的代码可以工作,我假设你没有展示所有内容。这是我知道的唯一调试方法:

User.last.destroy
#=> FOREIGN KEY constraint failed (SQLite3::ConstraintException) ¯\_(ツ)_/¯

# disable foreign key constraints
ActiveRecord::Base.connection.execute("PRAGMA foreign_keys = OFF")

# this should work now
User.last.destroy

# check foreign keys manually to get a helpful error
ActiveRecord::Base.connection.execute("PRAGMA foreign_key_check")
#=> [{"table"=>"payments", "rowid"=>1, "parent"=>"users", "fkid"=>0}]
# now you know where ^

# turn it back on
ActiveRecord::Base.connection.execute("PRAGMA foreign_keys = ON")

t3irkdon

t3irkdon2#

我也是Rails的新手,但据我所知,它与has_tobelongs_to关联有关。
而不是使用

has_many :messages, dependent: :destroy
#You could try this
has_many :messages, dependent: :delete_all

字符串
这对我很有效,基本上你需要在删除用户之前删除依赖数据。我还发现它详细解释了in this other postthis other解释了Rails中的级联删除过程,非常有帮助。

相关问题