module Sequel::Plugins::ConstraintValidations::ClassMethods
Attributes
A hash of reflections of constraint validations. Keys are type name symbols. Each value is an array of pairs, with the first element being the validation type symbol (e.g. :presence) and the second element being options for the validation. If the validation takes an argument, it appears as the :argument entry in the validation option hash.
An array of validation method call arrays. Each array is an array that is splatted to send to perform a validation via validation_helpers.
The name of the table containing the constraint validations metadata.
Public Instance Methods
Freeze constraint validations data when freezing model class.
# File lib/sequel/plugins/constraint_validations.rb 94 def freeze 95 @constraint_validations.freeze.each(&:freeze) 96 @constraint_validation_reflections.freeze.each_value do |v| 97 v.freeze 98 v.each(&:freeze) 99 end 100 @constraint_validation_options.freeze.each_value(&:freeze) 101 102 super 103 end
Private Instance Methods
Given a specific database constraint validation metadata row hash, transform it in an validation method call array suitable for splatting to send.
# File lib/sequel/plugins/constraint_validations.rb 136 def constraint_validation_array(r, reflections, allow_missing_columns=EMPTY_ARRAY) 137 opts = {} 138 opts[:message] = r[:message] if r[:message] 139 opts[:allow_nil] = true if db.typecast_value(:boolean, r[:allow_nil]) 140 type = r[:validation_type].to_sym 141 arg = r[:argument] 142 column = r[:column] 143 144 case type 145 when :like, :ilike 146 arg = constraint_validation_like_to_regexp(arg, type == :ilike) 147 type = :format 148 when :exact_length, :min_length, :max_length 149 arg = arg.to_i 150 when :length_range 151 arg = constraint_validation_int_range(arg) 152 when :format 153 arg = Regexp.new(arg) 154 when :iformat 155 arg = Regexp.new(arg, Regexp::IGNORECASE) 156 type = :format 157 when :includes_str_array 158 arg = arg.split(',') 159 type = :includes 160 when :includes_int_array 161 arg = arg.split(',').map(&:to_i) 162 type = :includes 163 when :includes_int_range 164 arg = constraint_validation_int_range(arg) 165 type = :includes 166 when *OPERATOR_MAP.keys 167 arg = arg.to_i if type.to_s =~ /\Aint_/ 168 operator = OPERATOR_MAP[type] 169 type = :operator 170 end 171 172 column = if type == :unique 173 column.split(',').map(&:to_sym) 174 else 175 column.to_sym 176 end 177 178 if type_opts = @constraint_validation_options[type] 179 opts.merge!(type_opts) 180 end 181 182 reflection_opts = opts.dup 183 a = [:"validates_#{type}"] 184 185 if operator 186 a << operator 187 reflection_opts[:operator] = operator 188 end 189 190 if arg 191 a << arg 192 reflection_opts[:argument] = arg 193 end 194 195 opts[:from] = :values 196 if column.is_a?(Symbol) && allow_missing_columns.include?(column) 197 opts[:allow_missing] = true 198 end 199 200 a << column << opts 201 202 if column.is_a?(Array) && column.length == 1 203 column = column.first 204 end 205 (reflections[column] ||= []) << [type, reflection_opts] 206 207 a 208 end
Return a range of integers assuming the argument is in 1..2 or 1…2 format.
# File lib/sequel/plugins/constraint_validations.rb 212 def constraint_validation_int_range(arg) 213 arg =~ /(\d+)\.\.(\.)?(\d+)/ 214 Range.new($1.to_i, $3.to_i, $2 == '.') 215 end
Transform the LIKE pattern string argument into a Regexp argument suitable for use with validates_format.
# File lib/sequel/plugins/constraint_validations.rb 219 def constraint_validation_like_to_regexp(arg, case_insensitive) 220 arg = Regexp.escape(arg).gsub(/%%|%|_/) do |s| 221 case s 222 when '%%' 223 '%' 224 when '%' 225 '.*' 226 else 227 #when '_' 228 '.' 229 end 230 end 231 arg = "\\A#{arg}\\z" 232 233 if case_insensitive 234 Regexp.new(arg, Regexp::IGNORECASE) 235 else 236 Regexp.new(arg) 237 end 238 end
If the database has not already parsed constraint validation metadata, then run a query to get the metadata data and transform it into arrays of validation method calls.
If this model has associated dataset, use the model’s table name to get the validations for just this model.
# File lib/sequel/plugins/constraint_validations.rb 113 def parse_constraint_validations 114 db.extension(:_model_constraint_validations) 115 116 unless hash = Sequel.synchronize{db.constraint_validations} 117 hash = {} 118 db.from(constraint_validations_table).each do |r| 119 (hash[r[:table]] ||= []) << r 120 end 121 Sequel.synchronize{db.constraint_validations = hash} 122 end 123 124 if @dataset 125 ds = @dataset.with_quote_identifiers(false) 126 table_name = ds.literal(ds.first_source_table) 127 reflections = {} 128 allow_missing_columns = db_schema.select{|col, sch| sch[:allow_null] == false && nil != sch[:default]}.map(&:first) 129 @constraint_validations = (Sequel.synchronize{hash[table_name]} || []).map{|r| constraint_validation_array(r, reflections, allow_missing_columns)} 130 @constraint_validation_reflections = reflections 131 end 132 end