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.

Private Instance Methods

constraint_validation_array(r, reflections) 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, line 125
def constraint_validation_array(r, reflections)
  opts = {}
  opts[:message] = r[:message] if r[:message]
  opts[:allow_nil] = true if db.typecast_value(:boolean, r[:allow_nil])
  type = r[:validation_type].to_sym
  arg = r[:argument]
  column = r[:column]

  case type
  when :like, :ilike
    arg = constraint_validation_like_to_regexp(arg, type == :ilike)
    type = :format
  when :exact_length, :min_length, :max_length
    arg = arg.to_i
  when :length_range
    arg = constraint_validation_int_range(arg)
  when :format
    arg = Regexp.new(arg)
  when :iformat
    arg = Regexp.new(arg, Regexp::IGNORECASE)
    type = :format
  when :includes_str_array
    arg = arg.split(',')
    type = :includes
  when :includes_int_array
    arg = arg.split(',').map{|x| x.to_i}
    type = :includes
  when :includes_int_range
    arg = constraint_validation_int_range(arg)
    type = :includes
  end

  column = if type == :unique
    column.split(',').map{|c| c.to_sym}
  else
    column.to_sym
  end

  if type_opts = @constraint_validation_options[type]
    opts = opts.merge(type_opts)
  end

  reflection_opts = opts
  a = [:"validates_#{type}"]

  if arg
    a << arg
    reflection_opts = reflection_opts.merge(:argument=>arg)
  end 
  a << column
  unless opts.empty?
    a << opts
  end

  if column.is_a?(Array) && column.length == 1
    column = column.first
  end
  (reflections[column] ||= []) << [type, reflection_opts]

  a
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, line 189
def constraint_validation_int_range(arg)
  arg =~ /(\d+)\.\.(\.)?(\d+)/
  Range.new($1.to_i, $3.to_i, $2 == '.')
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, line 196
def constraint_validation_like_to_regexp(arg, case_insensitive)
  arg = Regexp.escape(arg).gsub(/%%|%|_/) do |s|
    case s
    when '%%'
      '%'
    when '%'
      '.*'
    when '_'
      '.'
    end
  end
  arg = "\\A#{arg}\\z"

  if case_insensitive
    Regexp.new(arg, Regexp::IGNORECASE)
  else
    Regexp.new(arg)
  end
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, line 102
def parse_constraint_validations
  db.extend(DatabaseMethods)

  unless hash = Sequel.synchronize{db.constraint_validations}
    hash = {}
    db.from(constraint_validations_table).each do |r|
      (hash[r[:table]] ||= []) << r
    end
    Sequel.synchronize{db.constraint_validations = hash}
  end

  if @dataset
    ds = @dataset.clone
    ds.quote_identifiers = false
    table_name = ds.literal(ds.first_source_table)
    reflections = {}
    @constraint_validations = (Sequel.synchronize{hash[table_name]} || []).map{|r| constraint_validation_array(r, reflections)}
    @constraint_validation_reflections = reflections
  end
end