ARCHIVED 2026-05-01 — Preserved for historical context. See current docs for current state.
Purpose: Prevent future schema-serialization mismatches
When to Use: Before deploying schema changes, when adding new serializers
# Verify migration runs cleanly
rails db:migrate:status
rails db:migrate
rails db:rollback STEP=1
rails db:migrate# Verify all model attributes exist in database
rails runner "
[User, Account, Plan, Subscription, Invoice, Payment, PaymentMethod].each do |model|
puts \"#{model.name}: #{model.column_names.sort}\"
end
"# Test all factories can create records
rails runner "
FactoryBot.factories.map(&:name).each do |factory_name|
begin
FactoryBot.create(factory_name)
puts \"✅ #{factory_name}\"
rescue => e
puts \"❌ #{factory_name}: #{e.message}\"
end
end
"# Test serializers don't reference missing columns
rails runner "
# Test Page serialization
page = Page.first || FactoryBot.create(:page)
puts 'Page serialization: ' + (page.rendered_content ? '✅' : '❌')
# Test RevenueSnapshot serialization
snapshot = RevenueSnapshot.first || FactoryBot.create(:revenue_snapshot)
puts 'Analytics serialization: ' + (snapshot.total_customers_count ? '✅' : '❌')
# Test Invoice serialization
invoice = Invoice.first || FactoryBot.create(:invoice)
puts 'Invoice serialization: ' + (invoice.tax_rate ? '✅' : '❌')
"When adding new serializers, verify:
- All referenced columns exist in database
- Column types match expected usage
- Foreign key relationships properly defined
-
belongs_toassociations have corresponding foreign key columns -
has_manyassociations reference existing tables - Association names match actual column names
- Custom serializer methods don't reference missing columns
- Computed fields have all required source columns
- Conditional serialization has proper null checks
# Always create migration first
rails generate migration AddColumnToModel column_name:type
# Then update model
class Model < ApplicationRecord
# Add validations, associations, etc.
end
# Finally update factories
FactoryBot.define do
factory :model do
column_name { "value" }
end
end# Safe: Check for column existence
def serialized_field
object.respond_to?(:field) ? object.field : nil
end
# Safe: Use try for optional associations
def related_data
object.association&.some_field
end
# Unsafe: Direct reference without checks
def unsafe_field
object.missing_field # Will raise NoMethodError
end# Safe: Optional attributes
factory :model do
required_field { "value" }
trait :with_optional do
optional_field { "optional_value" }
end
end
# Safe: Association creation
factory :model do
association :parent, factory: :parent_model
end
# Unsafe: Setting non-existent attributes
factory :model do
non_existent_field { "value" } # Will raise error
end# Search for potential missing column references
grep -r "object\." app/serializers/
grep -r "\.column_name" spec/factories/# Check all constraints are valid
rails runner "
ActiveRecord::Base.connection.execute('
SELECT conname, pg_get_constraintdef(oid)
FROM pg_constraint
WHERE contype = \"c\"
').each { |row| puts \"#{row['conname']}: #{row['pg_get_constraintdef']}\" }
"# Quick test suite sampling
bundle exec rspec spec/models/ --format progress | tail -1
bundle exec rspec spec/controllers/ --format progress | tail -1
bundle exec rspec spec/requests/ --format progress | tail -1If schema issues are discovered in production:
# Check for missing columns in logs
grep "NoMethodError.*undefined method" production.log
# Identify affected serializers
grep -r "missing_column" app/serializers/# Temporary serializer fix
def safe_field
object.respond_to?(:field) ? object.field : "default_value"
end- Create migration for missing columns
- Update models and factories
- Test thoroughly in staging
- Deploy with proper rollback plan
Monitor these metrics to ensure schema health:
- API Error Rate: Should be minimal for serialization errors
- Test Suite Stability: Consistent pass rates without schema-related failures
- Factory Reliability: All factories should create valid records
- Migration Success: All migrations should run without constraint violations
Remember: Schema changes are infrastructure changes. Treat them with the same care as production deployments.