'FOREIGN KEY ON DELETE SET NULL in rails

I'm working with two models in rails

    class Student < ApplicationRecord
      belongs_to :school
      has_many :lessons
    end

and

    class Lesson < ApplicationRecord
      belongs_to :student, optional: true
    end

I was really hoping this would result in what Oracle does with FOREIGN KEY ON DELETE SET NULL

after I do rails db:migrate:reset I get a generated db/schema.rb with the line

      add_foreign_key "lessons", "students"

Which is not what I was expecting given my models, so I modified it by hand to

   add_foreign_key "lessons", "students", on_delete: :nullify

No matter what I do, I get a foreign key violation every time I try to delete a student who has lessons.

Why doesn't the schema.rb reflect the models in the first place?

Why don't the tables reflect the changes I made to schema.rb by hand?

How do I delete a student without deleting all the lessons?



Solution 1:[1]

Why doesn't the schema.rb reflect the models in the first place?

because rails db:migrate:reset uses the files in db/migrate to generate the database, not the app/models files

either figure out the correct 'rails generate' command to create the correct

db/migrate/timestamp_do_this_or_that.rb

file or pick an existing (later) db/migrate/timestamp_do_this_or_that.rb file and add this line between 'def change' and 'end':

add_foreign_key "lessons", "students", on_delete: :nullify

rails db:migrate:reset

rails db:seed

and any student can be deleted even if he/she has lessons and where their id used to be in the lesson table is now 'nil'

Why don't the tables reflect the changes I made to schema.rb by hand?

I can't say for sure, but perhaps the autogenerated schema.rb file is just for reference. It does say in the comments at the top of the file:

    # Instead
    # of editing this file, please use the migrations feature of Active Record to
    # incrementally modify your database, and then regenerate this schema definition

Solution 2:[2]

if you don't want to reset the whole db you can also specify it in the model with dependent option

class Student < ApplicationRecord
  belongs_to :school
  has_many :lessons, dependent: :nullify
end

class Lesson < ApplicationRecord
  belongs_to :student, optional: true
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 elMatador