Rails:delete_all 引发 PG::NotNullViolation

Posted

技术标签:

【中文标题】Rails:delete_all 引发 PG::NotNullViolation【英文标题】:Rails: delete_all raises PG::NotNullViolation 【发布时间】:2017-11-23 15:54:36 【问题描述】:

我正在将一个包含数百行的 CSV 导入我的 rails 数据库。

有时用户想强制覆盖数据,所以我认为最好销毁所有数据并重新开始。

类似:

account.catalog_listings.delete_all if should_refresh

CSV.foreach(file, options) do |row|
  account.catalog_listings.create!(...rowstuff)

问题是delete_all 行引发了 PG 错误

ActiveRecord::StatementInvalid (PG::NotNullViolation: ERROR:  null value in column "account_id" violates not-null constraint
DETAIL:  Failing row contains (1, null, ... ... ).
: UPDATE "catalog_listings" SET "account_id" = NULL WHERE "catalog_listings"."account_id" = $1):
  app/models/catalog_listing.rb:41:in `import_catalog_listings'
  app/controllers/accounts_controller.rb:20:in `catalog'

确实在几个外键字段上有一个null: false,但我不明白为什么delete_all 试图删除外键而不是删除整个记录?

更新 - 我更改后一切正常:

account.catalog_listings.delete_all if should_refresh

到:

account.catalog_listings.destroy_all if should_refresh

除了destroy 遍历每一项并逐一删除:

  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 957]]
  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 958]]
  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 959]]
  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 960]]
  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 961]]
  SQL (0.1ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 962]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 963]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 964]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 965]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 966]]
  SQL (0.3ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 967]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 968]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 969]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 970]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 971]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 972]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 973]]
  SQL (0.3ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 974]]
  SQL (0.2ms)  DELETE FROM "catalog_listings" WHERE "catalog_listings"."id" = $1  [["id", 975]]

不酷...有人知道更好的方法吗?

【问题讨论】:

您的模型中有before_destroy 过滤器吗? 没有。我有belongs_to :accountvalidates_presence_of :account_id` 导致问题的原因,主要是在数据库级别...您必须在迁移期间设置约束,对吧? 迁移是t.integer account_id, null: false,仅此而已。真正的问题是为什么 rails 会删除 account_id 而不是删除对象。 【参考方案1】:

尝试在Account 模型的catalog_listings 关联中添加dependent: :destroy

https://apidock.com/rails/ActiveRecord/Associations/CollectionProxy/delete_all

【讨论】:

以上是关于Rails:delete_all 引发 PG::NotNullViolation的主要内容,如果未能解决你的问题,请参考以下文章

rails清除模型的所有关系依赖关系?

如何在 Rails 中引发异常,使其表现得像其他 Rails 异常?

如何在 Rails/RSpec 中测试异常引发?

Rails ActiveSupport:如何断言引发了错误?

delete_all vs destroy_all?

Rails 4.2 - url helper 引发“ArgumentError:错误数量的参数(3 for 1..2)”