Rails中的自定义名称外键导致“ ActiveRecord :: InvalidForeignKey:PG :: ForeignKeyViolation”错误

我有一个Book模型,我有一个User模型。我正在尝试在author_id表中创建一个名为books的新列,该列实际上是users表的外键。

我关注了this article by Joshua Frankel。但是我遇到了以下错误

  

activeRecord :: InvalidForeignKey:PG :: ForeignKeyViolation:错误`

我正在使用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

app / models / book.rb:

class Book < activeRecord::Base
  belongs_to :author,class_name: :User,foreign_key: :author_id
end

app / models / 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'
>
g6228560 回答:Rails中的自定义名称外键导致“ ActiveRecord :: InvalidForeignKey:PG :: ForeignKeyViolation”错误

我找到了问题。它与Postgres中的模式有关。

我在Postgres数据库中使用Apartment gem进行租赁。在我的情况下,books表是租户的。但是,users表不是租户的,它们是通用的。意思是,user存在于public模式中,但是book存在于Malaysia模式中。

因此,当我们尝试保存book.save!时,books表(在Malaysia模式中)将在以下用户的users表中检查ID为1的用户相同的架构(即Malaysia架构)。但是,由于我的用户实际上存在于public模式中,因此它认为没有ID为1的用户(因为它仅在Malaysia模式中寻找它)。

然后,我遇到了有关跨模式外键的known issue in Apartment


我如何解决?

  • 我回退了数据库迁移“第一步”,基本上是通过删除新的author_id列来还原更改。
  • 然后从迁移文件中删除add_foreign_key语句,以便Postgres表不会创建任何数据库级外键关联。
  • 然后再次运行迁移。

因此,现在,我确实有一个名为author_id的新列(该列也已建立索引),但是它没有users表的数据库级外键。然后规格通过了。

因此,它实际上不再是一流的数据库级外键。它只是依靠模型中定义的Rails关联来实现我们所希望的“外来钥匙式” 行为-效果很好。

本文链接:https://www.f2er.com/3112886.html

大家都在问