Module: ConcernsOnRails::Support::ColumnGuard

Overview

Shared schema-validation helper mixed into a concern's ClassMethods. Runs in class context, so column_names / table_name resolve against the including model. Centralizes the column-existence check that every model concern used to re-implement, and keeps the error wording uniform.

class_methods do
include ConcernsOnRails::Support::ColumnGuard

def activatable_by(field = :active)
  self.activatable_field = field.to_sym
  ensure_columns!("ConcernsOnRails::Models::Activatable", activatable_field)
end
end

When the schema is unreachable — no database yet (db:create, a fresh db:migrate, assets:precompile, CI bootstrap) or the table not yet migrated — the check is skipped and false is returned instead of raising, so model classes stay loadable. A missing column with a reachable schema still raises: the rescue is scoped to ActiveRecord::ActiveRecordError precisely so real bugs (NameError from a typo etc.) keep surfacing. Skipping is self-healing: once the migration runs and classes reload, validation happens for real — and a genuinely missing column still fails loudly on first query.

The phrase "does not exist" is preserved so existing specs that match /does not exist/ keep passing.

Instance Method Summary collapse

Instance Method Details

#ensure_columns!(concern, *fields) ⇒ Object



30
31
32
# File 'lib/concerns_on_rails/support/column_guard.rb', line 30

def ensure_columns!(concern, *fields)
  ensure_columns_on!(concern, self, *fields)
end

#ensure_columns_on!(concern, klass, *fields) ⇒ Object

Same contract, validated against another class (e.g. CounterCacheable checks the counter column on the parent model).



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/concerns_on_rails/support/column_guard.rb', line 36

def ensure_columns_on!(concern, klass, *fields)
  return false unless schema_reachable?(klass)

  fields.flatten.compact.each do |field|
    next if klass.column_names.include?(field.to_s)

    raise ArgumentError,
          "#{concern}: '#{field}' does not exist in the database (table: #{klass.table_name})"
  end
  true
end

#schema_reachable?(klass = self) ⇒ Boolean

True when the class's table can actually be inspected. Connection errors (ConnectionNotEstablished, NoDatabaseError, adapter errors) all inherit from ActiveRecord::ActiveRecordError.

Returns:

  • (Boolean)


51
52
53
54
55
# File 'lib/concerns_on_rails/support/column_guard.rb', line 51

def schema_reachable?(klass = self)
  klass.table_exists?
rescue ActiveRecord::ActiveRecordError
  false
end