Maintaining database integrity through database le

2019-08-04 11:07发布

问题:

Being new to rails, I'm a little surprised that the rails migration/ActiveRecord does not create database level foreign keys for has_many, has_one and other relations. It is clear from searching on the topic, that this is the rails way.

I hit upon an example in the book Agile Web Development with Rails 4 which uses the following example on page 110.

class Product < ActiveRecord::Base
  has_many :line_items
  before_destroy :ensure_not_referenced_by_any_line_item
  ...
  private

    # ensure that there are no line items referencing this product
    def ensure_not_referenced_by_any_line_item
      if line_items.empty?
        return true
      else
        errors.add(:base, 'Line Items present')
        return false
      end
    end
end

This example made me cringe because ensure_not_referenced_by_any_line_item is exactly the kind of thing a programmer would forget to add. Also, in my opinion, it requires more lines of code meaning more bugs, etc.

I've found this thread which is more than five years old on the same topic. I've also become aware of the Foreigner Gem.

My question is regarding the current state of affairs in rails. Are database level foreign keys supported yet? Are there other options like the Foreigner Gem? I'm interested in Sqlite3 and MySQL backends.

回答1:

There is also a cleaner solution for this

has_many :line_items, :dependent => :restrict # raises ActiveRecord::DeleteRestrictionError

This will raise an error that you can catch.

In any case, you need to specify the dependent option to avoid having orphans left in your database. It is the developers responsibility to remember these things and set the proper conditions in Rails.

has_many :line_items, :dependent => :delete # Will remove all child records

I never used any additional gems to deal with Foreign keys.