module ActiveRecord::DatabaseValidations::Rescues

Constants

FOREIGN_KEY_PATTERNS_BY_COLUMN
FOREIGN_KEY_PATTERNS_BY_FOREIGN_KEY
NOT_NULL_PATTERNS
PRIMARY_INDEXES
UNIQUE_PATTERNS_BY_COLUMN
UNIQUE_PATTERNS_BY_INDEX

Public Class Methods

included(base) click to toggle source
# File lib/activerecord/database_validations/rescues.rb, line 2
def self.included(base)
  base.around_save :rescue_database_not_null
  base.around_save :rescue_database_unique
  base.around_save :rescue_database_foreign_key
end

Public Instance Methods

rescue_database_foreign_key() { || ... } click to toggle source
# File lib/activerecord/database_validations/rescues.rb, line 65
def rescue_database_foreign_key
  self.class.foreign_keys if FOREIGN_KEY_PATTERNS_BY_FOREIGN_KEY.any? # load he foreign keys not inside a failing transaction (eg. PG::InFailedSqlTransaction)
  begin
    yield
  rescue ActiveRecord::InvalidForeignKey => e
    column_name = if FOREIGN_KEY_PATTERNS_BY_COLUMN.any? { |p| e.message =~ p }
                    $1
                  elsif FOREIGN_KEY_PATTERNS_BY_FOREIGN_KEY.any? { |p| e.message =~ p }
                    foreign_key = self.class.foreign_keys.find { |i| i.name == $1 }
                    raise if foreign_key.nil?
                    foreign_key.column
                  else
                    raise
                  end
    errors.add(column_name, :inclusion)
    raise ActiveRecord::RecordInvalid.new(self)
  end
end
rescue_database_not_null() { || ... } click to toggle source
# File lib/activerecord/database_validations/rescues.rb, line 13
def rescue_database_not_null
  begin
    yield
  rescue ActiveRecord::StatementInvalid => e
    if NOT_NULL_PATTERNS.any? { |p| e.message =~ p }
      column_name = $1
      errors.add(column_name, :blank)
      raise ActiveRecord::RecordInvalid.new(self)
    else
      raise
    end
  end
end
rescue_database_unique() { || ... } click to toggle source
# File lib/activerecord/database_validations/rescues.rb, line 36
def rescue_database_unique
  self.class.indexes if UNIQUE_PATTERNS_BY_INDEX.any? # load the indexes not inside a failed transaction (eg. PG::InFailedSqlTransaction)
  begin
    yield
  rescue ActiveRecord::RecordNotUnique => e
    column_name = if UNIQUE_PATTERNS_BY_COLUMN.any? { |p| e.message =~ p }
                    $1
                  elsif UNIQUE_PATTERNS_BY_INDEX.any? { |p| e.message =~ p }
                    if PRIMARY_INDEXES.include?($1)
                      self.class.primary_key
                    else
                      index = self.class.indexes.find { |i| i.name == $1 }
                      raise if index.nil?
                      index.columns[-1]
                    end
                  else
                    raise
                  end
    errors.add(column_name, :taken)
    raise ActiveRecord::RecordInvalid.new(self)
  end
end