【问题标题】:Ruby on Rails: ActiveRecord::NotNullViolation: SQLite3::ConstraintException: NOT NULL constraint failed: error when trying to run unit testsRuby on Rails:ActiveRecord::NotNullViolation: SQLite3::ConstraintException: NOT NULL 约束失败:尝试运行单元测试时出错
【发布时间】:2019-10-07 00:36:55
【问题描述】:

我正在尝试在我的应用程序上运行单元测试,我最初的错误是“表 xx 没有名为 yy 的列”,所以在我的 yml 文件中我将字段更改为 id。但是,现在它给了我这个错误:

CarsControllerTest#test_should_destroy_car: ActiveRecord::NotNullViolation: SQLite3::ConstraintException: NOT NULL 约束失败 我该如何解决这个问题并运行我的测试?

【问题讨论】:

  • 什么是失败的测试?
  • @SebastianPalma 当我运行 rails 测试时,它没有运行任何测试并给我上面的错误。
  • @SebastianPalma 是的,我刚刚在上面的汽车和零件的 yml 文件中进行了编辑。
  • Make 对 makecountry 进行了验证,它们是否在其夹具文件中定义?
  • @SebastianPalma 是的,我也为 make 添加了 yml 文件。

标签: ruby-on-rails ruby


【解决方案1】:
create_table "cars_parts", force: :cascade do |t|
    t.integer "car_id"
    t.integer "part_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["car_id"], name: "index_cars_parts_on_car_id"
    t.index ["part_id"], name: "index_cars_parts_on_part_id"
  end

cars_parts 中的 created_at 有一个非空约束。

在错误中您可以看到它说created_at 不能为 Null:

SQLite3::ConstraintException: NOT NULL constraint failed: cars_parts.created_at

所以在你的 yml 文件中你需要设置 created_at:

one:
  car_id: 1
  part_id: 1
  created_at: Time.current
  updated_at: Time.current

two:
  car_id: 2
  part_id: 2
  created_at: Time.current
  updated_at: Time.current

编辑:

正如 Sebastian 指出的,这不是一个理想的解决方案,AR 应该自动添加这些时间戳。

真正的问题是您将模型命名为CarParts,所以它没有找到模型。您应该将文件重命名为cars_part.rb,将模型名称重命名为CarsPart

遇到此问题的其他人将原因归因于找不到模型:

https://github.com/rails/rails/issues/23316

【讨论】:

  • 这可以解释错误,但确实这是 FixtureSet 的一个文档功能 如果您的表/模型指定了任何 Active Record 的标准时间戳列(created_at、created_on、updated_at、updated_on) ,它们将自动设置为 Time.now。如果这解决了错误,那么使用时间戳的模型的每个固定装置都需要它。
  • 是的,我意识到在我发布答案后,我认为实际的问题是他将他的模型命名为CarParts,而不是CarPart。我阅读了一个 github 问题线程,当找不到模型时,人们会收到此错误。
  • 不错的收获!所以这可以通过适当的变形来解决。
  • @SebastianPalma 谢谢!我更改了我的模型名称以遵循惯例,它现在可以工作了。
【解决方案2】:

当您使用 has_and_belongs_to_many 时,连接表不应该有 created/updated_at 时间戳,并且您不需要 CarsParts 模型(只需要表,而不需要模型)。如果您想要 CarsParts 模型,则必须使用 has_many 和 has_many :through 关联,以便 ActiveRecord 将连接模型作为实际模型处理并设置时间戳

所以,你必须选择:

1- 移除连接表上的时间戳并移除 CarsParts 模型

2- 添加正确的关联并修复模型的表和名称:

CarPart #not CarsParts
  belongs_to :car
  belongs_to :part
  self.table_name = 'cars_parts' # the actual plural would be car_parts, not cars_parts

Part
  has_many :car_parts
  has_many :cars, through: :cars_parts

Car
  has_many :car_parts
  has_many :parts, through: :cars_parts

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 2022-08-10
    • 2018-06-10
    相关资源
    最近更新 更多