module Sequel::Plugins::PgAutoConstraintValidations::ClassMethods
Attributes
Hash
of metadata checked when an instance attempts to convert a constraint violation into a validation failure.
Hash
of error messages keyed by constraint type symbol to use in the generated validation failures.
Public Instance Methods
Dump the in-memory cached metadata to the cache file.
# File lib/sequel/plugins/pg_auto_constraint_validations.rb 132 def dump_pg_auto_constraint_validations_cache 133 raise Error, "No pg_auto_constraint_validations setup" unless file = @pg_auto_constraint_validations_cache_file 134 File.open(file, 'wb'){|f| f.write(Marshal.dump(@pg_auto_constraint_validations_cache))} 135 nil 136 end
Override the constraint validation columns and message for a given constraint
# File lib/sequel/plugins/pg_auto_constraint_validations.rb 139 def pg_auto_constraint_validation_override(constraint, columns, message) 140 pgacv = Hash[@pg_auto_constraint_validations] 141 overrides = pgacv[:overrides] = Hash[pgacv[:overrides]] 142 overrides[constraint] = [Array(columns), message].freeze 143 overrides.freeze 144 @pg_auto_constraint_validations = pgacv.freeze 145 nil 146 end
Private Instance Methods
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 157 def setup_pg_auto_constraint_validations 158 return unless @dataset 159 160 case @dataset.first_source_table 161 when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier 162 convert_errors = db.respond_to?(:error_info) 163 end 164 165 unless convert_errors 166 # Might be a table returning function or subquery, skip handling those. 167 # Might have db not support error_info, skip handling that. 168 @pg_auto_constraint_validations = nil 169 return 170 end 171 172 cache = @pg_auto_constraint_validations_cache 173 literal_table_name = dataset.literal(table_name) 174 unless cache && (metadata = cache[literal_table_name]) 175 checks = {} 176 indexes = {} 177 foreign_keys = {} 178 referenced_by = {} 179 180 db.check_constraints(table_name).each do |k, v| 181 checks[k] = v[:columns].dup.freeze unless v[:columns].empty? 182 end 183 db.indexes(table_name, :include_partial=>true).each do |k, v| 184 if v[:unique] 185 indexes[k] = v[:columns].dup.freeze 186 end 187 end 188 db.foreign_key_list(table_name, :schema=>false).each do |fk| 189 foreign_keys[fk[:name]] = fk[:columns].dup.freeze 190 end 191 db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk| 192 referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze 193 end 194 195 schema, table = db[:pg_class]. 196 join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid). 197 get([:nspname, :relname]) 198 199 metadata = { 200 :schema=>schema, 201 :table=>table, 202 :check=>checks, 203 :unique=>indexes, 204 :foreign_key=>foreign_keys, 205 :referenced_by=>referenced_by, 206 :overrides=>OPTS 207 }.freeze 208 metadata.each_value(&:freeze) 209 210 if cache 211 cache[literal_table_name] = metadata 212 end 213 end 214 215 @pg_auto_constraint_validations = metadata 216 nil 217 end