module Sequel::Plugins::ConstraintValidations::ClassMethods

Attributes

constraint_validation_reflections[R]

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.

constraint_validations[R]

An array of validation method call arrays. Each array is an array that is splatted to send to perform a validation via validation_helpers.

constraint_validations_table[R]

The name of the table containing the constraint validations metadata.

Public Instance Methods

freeze() click to toggle source

Freeze constraint validations data when freezing model class.

Calls superclass method
    # 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

constraint_validation_array(r, reflections, allow_missing_columns=EMPTY_ARRAY) click to toggle source

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
constraint_validation_int_range(arg) click to toggle source

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
constraint_validation_like_to_regexp(arg, case_insensitive) click to toggle source

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
parse_constraint_validations() click to toggle source

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