module Sequel::Plugins::PgAutoConstraintValidations::ClassMethods

Attributes

pg_auto_constraint_validations[R]

Hash of metadata checked when an instance attempts to convert a constraint violation into a validation failure.

pg_auto_constraint_validations_messages[R]

Hash of error messages keyed by constraint type symbol to use in the generated validation failures.

Public Instance Methods

pg_auto_constraint_validation_override(constraint, columns, message) click to toggle source

Override the constraint validation columns and message for a given constraint

   # File lib/sequel/plugins/pg_auto_constraint_validations.rb
92 def pg_auto_constraint_validation_override(constraint, columns, message)
93   pgacv = Hash[@pg_auto_constraint_validations]
94   overrides = pgacv[:overrides] = Hash[pgacv[:overrides]]
95   overrides[constraint] = [Array(columns), message].freeze
96   overrides.freeze
97   @pg_auto_constraint_validations = pgacv.freeze
98   nil
99 end

Private Instance Methods

setup_pg_auto_constraint_validations() click to toggle source

Get the list of constraints, unique indexes, foreign keys in the current table, and keys in the current table referenced by foreign keys in other tables. Store this information so that if a constraint violation occurs, all necessary metadata is already available in the model, so a query is not required at runtime. This is both for performance and because in general after the constraint violation failure you will be inside a failed transaction and not able to execute queries.

    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
110 def setup_pg_auto_constraint_validations
111   return unless @dataset
112 
113   case @dataset.first_source_table
114   when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
115    convert_errors = db.respond_to?(:error_info)
116   end
117 
118   unless convert_errors
119     # Might be a table returning function or subquery, skip handling those.
120     # Might have db not support error_info, skip handling that.
121     @pg_auto_constraint_validations = nil
122     return
123   end
124 
125   checks = {}
126   indexes = {}
127   foreign_keys = {}
128   referenced_by = {}
129 
130   db.check_constraints(table_name).each do |k, v|
131     checks[k] = v[:columns].dup.freeze unless v[:columns].empty?
132   end
133   db.indexes(table_name, :include_partial=>true).each do |k, v|
134     if v[:unique]
135       indexes[k] = v[:columns].dup.freeze
136     end
137   end
138   db.foreign_key_list(table_name, :schema=>false).each do |fk|
139     foreign_keys[fk[:name]] = fk[:columns].dup.freeze
140   end
141   db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk|
142     referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze
143   end
144 
145   schema, table = db[:pg_class].
146     join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid).
147     get([:nspname, :relname])
148 
149   (@pg_auto_constraint_validations = {
150     :schema=>schema,
151     :table=>table,
152     :check=>checks,
153     :unique=>indexes,
154     :foreign_key=>foreign_keys,
155     :referenced_by=>referenced_by,
156     :overrides=>OPTS
157   }.freeze).each_value(&:freeze)
158 end