module Sack::Database::Model::Validation::ClassMethods

Class Methods: Collection of methods to be injected into anything that includes this module.

Public Instance Methods

is_uniq?(db, data, name, val, scope) click to toggle source

Is Unique: Verifies the unicity of a given field (name) value (val) on an entity (data), possibly within a given scope. @param [Database] db Database instance (Sack::Database) @param [Hash] data Entity data @param [Symbol] name Field name @param [Object] val Field value @param [Object] scope Either True (if absolute - no scope) or an Array of field names defining the scope

# File lib/sack/database/model/validation.rb, line 121
def is_uniq? db, data, name, val, scope

        # Fetch all other rows with field [name] equal to [val]
        others = db.fetch_by table_name, name, val
        others.reject! { |o| o[:id] == data[:id] } if data[:id]

        # If scopeless (absolutely unique), check empty set and return
        return others.empty? unless scope.is_a? Array

        # Check Unique throughout Scope
        scope.each { |f| others.reject! { |o| o[f] != data[f] } }
        others.empty?
end
is_valid?(db, data, errors = []) click to toggle source

Is Valid: Verifies the validity of a given entity (data) against this Model. @param [Database] db Database instance (Sack::Database) @param [Hash] data Entity data

# File lib/sack/database/model/validation.rb, line 47
def is_valid? db, data, errors = []

        # Run through Model's Field Schema
        fields.inject(true) do |a, e|

                # Acquire Field Info
                name = e[0]
                info = e[1]
                ftype = info[:ftype]
                rules = info[:rules]
                val = data[name]

                # Handle Required
                if rules[:required]
                        r = val.try :is_a?, FTYPES_CLASSES[ftype.first]
                        a &&= r
                        errors << "Required field [#{name}] is missing" unless r
                end

                # Handle Unique
                if rules[:unique]
                        r = is_uniq? db, data, name, val, rules[:unique]
                        a &&= r
                        errors << "Field [#{name}] has non-unique value [#{val}]#{rules[:unique].is_a?(Array) ? " in scope [#{rules[:unique].join ', '}]" : ''}" unless r
                end

                # Handle Set Length
                if rules[:length]
                        r = val.try(:length).try :==, rules[:length]
                        a &&= r
                        errors << "Field [#{name}] has invalid length (#{val.try(:length)} / #{rules[:length]})" unless r
                end

                # Handle Minimum Length
                if rules[:min_length]
                        r = val.try(:length).try :>=, rules[:min_length]
                        a &&= r
                        errors << "Field [#{name}] has invalid length (#{val.try(:length)} / Min: #{rules[:min_length]})" unless r
                end

                # Handle Maximum Length
                if rules[:max_length]
                        r = val.try(:length).try :<=, rules[:max_length]
                        a &&= r
                        errors << "Field [#{name}] has invalid length (#{val.try(:length)} / Max: #{rules[:max_length]})" unless r
                end

                # Handle Regex
                if rules[:regex]
                        r = rules[:regex] =~ val
                        a &&= r
                        errors << "Field [#{name}] doesn't match allowed pattern (#{rules[:regex].inspect})" unless r
                end

                # Handle Custom
                if rules[:validate]
                        size = errors.size
                        r = send rules[:validate], db, data, name, val, rules, errors
                        a &&= r
                        errors << "Field [#{name}] is invalid" unless r || (size != errors.size)
                end

                # Don't leak shit
                !!a
        end
end