Module: ConcernsOnRails::Support::ColumnGuard
- Included in:
- Models::Addressable::ClassMethods, Models::Aliasable::ClassMethods, Models::Auditable::ClassMethods, Models::CounterCacheable::ClassMethods, Models::Encryptable::ClassMethods, Models::Lockable::ClassMethods, Models::SoftDeletable::ClassMethods, Models::Sortable::ClassMethods, Models::Stateable::ClassMethods, Models::Storable::ClassMethods, Models::Taggable::ClassMethods
- Defined in:
- lib/concerns_on_rails/support/column_guard.rb
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
- #ensure_columns!(concern, *fields) ⇒ Object
-
#ensure_columns_on!(concern, klass, *fields) ⇒ Object
Same contract, validated against another class (e.g. CounterCacheable checks the counter column on the parent model).
-
#schema_reachable?(klass = self) ⇒ Boolean
True when the class's table can actually be inspected.
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.
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 |