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