Model validations should have corresponding database constraints
Follow-up from gitlab-com/www-gitlab-com#6556 (comment 303081482):
Database-level constraints help to prevent data inconsistencies, that would otherwise not be caught by application-level validations. In order to improve this throughout the application, we would like to devise a method to make sure we have the appropriate database-level constraints in place for existing model validations.
As a summary of the internal Slack thread with @smcgivern , one approach is to replace validates :foo, presence: true
with validates_with_constraint :foo, presence: true, schema: { foo_id: { null: false } }
and thereby annotating the constraint with what should be present on the database-side. We'd be able to check for this (rubocop?) statically.
We've also discussed keeping the standard Rails validations and derive the required schema information from them. This might be tricky to do in all cases (partial constraints, inheritance).
Perhaps a good way to start this effort is to implement:
- checking
presence: true
validations correspond toNOT NULL
constraints - checking
length: { maximum: ... }
validations correspond toCHECK ((char_length(field) <= X)
constraints
in the database schema.