ruby-on-rails - Rails 中的自定义名称外键导致 'ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation' 错误

标签 ruby-on-rails ruby postgresql activerecord foreign-keys

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

我关注了this article by 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'
>

最佳答案

我发现了问题。它与 Postgres 中的模式有关。

我在 Postgres 数据库中使用 Apartment gem 进行租赁。在我的例子中,books 表是租用的。但是,users 表不是租用的——它们是通用的。意思是,user 存在于 public 模式中,而 book 存在于(比方说)Malaysia 模式中。

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

然后我遇到了这个 known issue in Apartment关于跨架构的外键。


我是如何解决的?

  • 我通过删除新的 author_id 列回滚了我的数据库迁移一步,基本上恢复了我的更改。
  • 然后从迁移文件中删除了 add_foreign_key 语句,这样 Postgres 表就不会创建任何数据库级外键关联。
  • 然后再次运行迁移。

所以现在,我确实有一个名为 author_id 的新列(它也被编入索引)但它没有 users 表的数据库级外键.然后规范顺利通过。

因此,它不再是一流的数据库级外键。它仅依赖于模型中定义的 Rails 关联来实现我们期望的“foreign-key-sque”行为 - 效果很好。

关于ruby-on-rails - Rails 中的自定义名称外键导致 'ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58830224/

相关文章:

javascript - 使用 javascript 通过 iframe 传递表单参数安全吗?

ruby-on-rails - 如何使用 token 验证用户销毁 session ("logout")

ruby-on-rails - Rails has_many :through and Setting Property on Join model

键中的 ruby​​ to_yaml 冒号

ruby-on-rails - Rails:如何修复 ActiveRecord::Irreversible Order Error

postgresql - Postgres,RHEL和Docker

ruby-on-rails - 清除 Rails 中单元测试和功能测试之间的测试数据库 (factory_girl)

ruby - Ruby解析器的原理是什么?

ruby-on-rails - Docker未安装yarn

PostgreSQL:将字符串从特定位置替换为字符串末尾