Module: Sequel::Plugins::PgAutoConstraintValidations
- Defined in:
- lib/sequel/plugins/pg_auto_constraint_validations.rb
Overview
The pg_auto_constraint_validations plugin automatically converts some constraint violation exceptions that are raised by INSERT/UPDATE queries into validation failures. This can allow for using the same error handling code for both regular validation errors (checked before attempting the INSERT/UPDATE), and constraint violations (raised during the INSERT/UPDATE).
This handles the following constraint violations:
-
NOT NULL
-
CHECK
-
UNIQUE (except expression/functional indexes)
-
FOREIGN KEY (both referencing and referenced by)
If the plugin cannot convert the constraint violation error to a validation error, it just reraises the initial exception, so this should not cause problems if the plugin doesn’t know how to convert the exception.
This plugin is not intended as a replacement for other validations, it is intended as a last resort. The purpose of validations is to provide nice error messages for the user, and the error messages generated by this plugin are fairly generic by default. The error messages can be customized per constraint type using the :messages plugin option, and individually per constraint using pg_auto_constraint_validation_override
(see below).
This plugin only works on the postgres adapter when using the pg 0.16+ driver, PostgreSQL 9.3+ server, and PostgreSQL 9.3+ client library (libpq). In other cases it will be a no-op. Additionally, the plugin only handles models that select from tables. It does not handle models that select from subqueries, such as subclasses of models using the class_table_inheritance plugin.
Example:
album = Album.new(artist_id: 1) # Assume no such artist exists
begin
album.save
rescue Sequel::ValidationFailed
album.errors.on(:artist_id) # ['is invalid']
end
While the database usually provides enough information to correctly associated constraint violations with model columns, there are cases where it does not. In those cases, you can override the handling of specific constraint violations to be associated to particular column(s), and use a specific error message:
Album.pg_auto_constraint_validation_override(:constraint_name, [:column1], "validation error message")
Using the pg_auto_constraint_validations plugin requires 5 queries per model at load time in order to gather the necessary metadata. For applications with a large number of models, this can result in a noticeable delay during model initialization. To mitigate this issue, you can cache the necessary metadata in a file with the :cache_file option:
Sequel::Model.plugin :pg_auto_constraint_validations, cache_file: 'db/pgacv.cache'
The file does not have to exist when loading the plugin. If it exists, the plugin will load the cache and use the cached results instead of issuing queries if there is an entry in the cache. If there is no entry in the cache, it will update the in-memory cache with the metadata results. To save the in in-memory cache back to the cache file, run:
Sequel::Model.dump_pg_auto_constraint_validations_cache
Note that when using the :cache_file option, it is up to the application to ensure that the dumped cached metadata reflects the current state of the database. Sequel does no checking to ensure this, as checking would take time and the purpose of this code is to take a shortcut.
The cached schema is dumped in Marshal format, since it is the fastest and it handles all ruby objects used in the metadata. Because of this, you should not attempt to load the metadata from a untrusted file.
Usage:
# Make all model subclasses automatically convert constraint violations
# to validation failures (called before loading subclasses)
Sequel::Model.plugin :pg_auto_constraint_validations
# Make the Album class automatically convert constraint violations
# to validation failures
Album.plugin :pg_auto_constraint_validations
Defined Under Namespace
Modules: ClassMethods, InstanceMethods
Class Method Summary collapse
-
.configure(model, opts = OPTS) ⇒ Object
Setup the constraint violation metadata.
Class Method Details
.configure(model, opts = OPTS) ⇒ Object
Setup the constraint violation metadata. Options:
- :cache_file
-
File storing cached metadata, to avoid queries for each model
- :messages
-
Override the default error messages for each constraint violation type (:not_null, :check, :unique, :foreign_key, :referenced_by)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/sequel/plugins/pg_auto_constraint_validations.rb', line 100 def self.configure(model, opts=OPTS) model.instance_exec do if @pg_auto_constraint_validations_cache_file = opts[:cache_file] @pg_auto_constraint_validations_cache = if ::File.file?(@pg_auto_constraint_validations_cache_file) cache = Marshal.load(File.read(@pg_auto_constraint_validations_cache_file)) cache.each_value do |hash| hash.freeze.each_value(&:freeze) end else {} end else @pg_auto_constraint_validations_cache = nil end setup_pg_auto_constraint_validations @pg_auto_constraint_validations_messages = (@pg_auto_constraint_validations_messages || DEFAULT_ERROR_MESSAGES).merge(opts[:messages] || OPTS).freeze end nil end |