Created
March 22, 2025 16:55
-
-
Save jbranchaud/12813a0558f9cd06bcc24b7d8706550c to your computer and use it in GitHub Desktop.
Idea for a fail-fast Rails initializer to check that database check constraints are in-sync with app code constants
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/validate_constraints.rb | |
Rails.application.config.after_initialize do | |
if Rails.env.development? || Rails.env.test? | |
# Get the check constraint from the database schema | |
connection = ActiveRecord::Base.connection | |
constraint_sql = nil | |
# Try to extract the constraint SQL | |
begin | |
# For PostgreSQL, you can query the information_schema | |
result = connection.execute(<<~SQL) | |
SELECT pg_get_constraintdef(oid) AS def | |
FROM pg_constraint | |
WHERE conname = 'reading_statuses_valid_status_check' | |
AND conrelid = 'reading_statuses'::regclass; | |
SQL | |
constraint_sql = result.first["def"] if result.any? | |
rescue => e | |
Rails.logger.error("Failed to check constraints: #{e.message}") | |
end | |
if constraint_sql | |
# Extract the values from the constraint SQL | |
# This is a simplistic approach and may need adjustment based on exact SQL format | |
db_values = constraint_sql.scan(/'([^']+)'/).flatten.sort | |
# Get the values from the constants | |
model_values = ReadingStatusConstants::VALID_STATUSES.sort | |
# Compare the values | |
unless db_values == model_values | |
message = <<~MSG | |
ERROR: Database constraint and model validation for ReadingStatus.status are out of sync! | |
Database constraint values: #{db_values.inspect} | |
Model validation values: #{model_values.inspect} | |
This can lead to inconsistent behavior where the application accepts values that the database rejects. | |
Please update the constraint or the model validation to ensure they are in sync. | |
MSG | |
Rails.logger.error(message) | |
raise message if Rails.env.development? # Optional: crash in development | |
end | |
else | |
Rails.logger.warn("Could not find reading_statuses_valid_status_check constraint") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment