Module: Sack::Database::Model::Validation::ClassMethods

Defined in:
lib/sack/database/model/validation.rb

Overview

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

Instance Method Summary collapse

Instance Method Details

#is_uniq?(db, data, name, val, scope) ⇒ Boolean

Is Unique: Verifies the unicity of a given field (name) value (val) on an entity (data), possibly within a given scope.

Parameters:

  • db (Database)

    Database instance (Sack::Database)

  • data (Hash)

    Entity data

  • name (Symbol)

    Field name

  • val (Object)

    Field value

  • scope (Object)

    Either True (if absolute - no scope) or an Array of field names defining the scope

Returns:

  • (Boolean)


121
122
123
124
125
126
127
128
129
130
131
132
133
# 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 = []) ⇒ Boolean

Is Valid: Verifies the validity of a given entity (data) against this Model.

Parameters:

  • db (Database)

    Database instance (Sack::Database)

  • data (Hash)

    Entity data

Returns:

  • (Boolean)


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 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