J. Green
J. Green

Reputation: 49

Ruby on Rails: ActiveRecord::NotNullViolation: SQLite3::ConstraintException: NOT NULL constraint failed: error when trying to run unit tests

I am trying to run unit tests on my application, and my original error was "table xx has no column named yy", so in my yml file I changed the fields to id. However, now it gives me this error:

CarsControllerTest#test_should_destroy_car: ActiveRecord::NotNullViolation: SQLite3::ConstraintException: NOT NULL constraint failed How do I fix this and run my tests?

Upvotes: 4

Views: 4159

Answers (2)

trueinViso
trueinViso

Reputation: 1394

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

You have a not null constraint on created_at in cars_parts.

In the error you can see that it says created_at can't be Null:

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

So in your yml file you need to set 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

EDIT:

As Sebastian pointed out, this is not an ideal solution, AR should automatically be adding these timestamps.

The real problem is that you named your model CarParts so it's not finding the model. You should rename the file to cars_part.rb and the model name to CarsPart.

Other people having this problem were attributing the cause to the model not being found:

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

Upvotes: 2

arieljuod
arieljuod

Reputation: 15838

When you use has_and_belongs_to_many, the join table shouldn't have created/updated_at timestamps and you don't need the CarsParts model (only the table is required, not the model). If you want a CarsParts model, you have to use has_many and has_many :through associations so ActiveRecord handles the join model as an actual model and sets the timestamps

So, you have to options:

1- remove the timestamps on the join table and remove the CarsParts model

or

2- add the right associations and fix the model's table and name:

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

Upvotes: 0

Related Questions