![](/img/trans.png)
[英]ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table violates foreign key constraint
[英]Custom name foreign key in Rails causing 'ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation' error
我有一Book
model,我有一個User
model。 我正在嘗試在books
表中創建一個名為author_id
的新列,它實際上是users
表的外鍵。
我關注了 Joshua Frankel 的這篇文章。 但我收到以下錯誤
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR`
我正在使用 Rails4.2
db/migrate/20191112111409_add_author_to_books.rb:
class AddAuthorToBooks < ActiveRecord::Migration
def up
add_reference :books, :author, references: :users, index: false
commit_db_transaction
add_index :books, :author_id, algorithm: :concurrently
add_foreign_key :books, :users, column: :author_id
end
def down
remove_column :books, :author_id
end
end
應用程序/模型/book.rb:
class Book < ActiveRecord::Base
belongs_to :author, class_name: :User, foreign_key: :author_id
end
應用程序/模型/user.rb:
class User < ActiveRecord::Base
has_many :books, foreign_key: :author_id
end
Rails 控制台中的錯誤:
> user = FactoryBot.create(:user)
> book = FactoryBot.create(:book)
> book.author = user
> book.save
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "books" violates foreign key constraint "fk_rails_13be98de92"
DETAIL: Key (author_id)=(1) is not present in table "users".
: UPDATE "books" SET "author_id" = $1, "updated_at" = $2 WHERE "books"."id" = $3
from ~/.ruby-gemset/ruby/2.3.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `exec_prepared'
Caused by PG::ForeignKeyViolation: ERROR: insert or update on table "books" violates foreign key constraint "fk_rails_13be98de92"
DETAIL: Key (author_id)=(1) is not present in table "users".
from ~/.ruby-gemset/ruby/2.3.0/gems/activerecord-4.2.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `exec_prepared'
>
在數據庫級別檢查數據庫 [外鍵] 完整性。 當您嘗試保存一book
時,數據庫中沒有這樣的user
。
因此,在保存鏈接到他們的book
之前,將user
保存到數據庫。
user = FactoryBot.create(:user)
user.save # this
book = FactoryBot.create(:book)
book.author = user
book.save
我在 Postgres 數據庫中使用 Apartment gem 進行租賃。 就我而言, books
是租用的。 但是, users
表沒有被租用——它們是通用的。 意思是, user
存在於public
模式中,但book
存在於(比方說) Malaysia
模式中。
所以,當我們試圖保存book.save!
, books
表(在Malaysia
模式中)在相同模式(即Malaysia
模式)的users
表中檢查 id 為 1 的用戶。 但是,由於我的用戶實際上存在於public
模式中,它認為沒有 id 為 1 的用戶(因為它只在Malaysia
模式中尋找它)。
author_id
列來恢復我的更改。add_foreign_key
語句,這樣 Postgres 表就不會創建任何 db 級別的外鍵關聯。 所以現在,我確實有一個名為author_id
的新列(它也被索引),但它沒有users
表的數據庫級外鍵。 然后規范優雅地通過了。
因此,它不再是真正的一流 db 級外鍵。 它只是依賴於 model 中定義的 Rails 關聯來實現我們想要的“外鍵”行為 - 效果很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.