Skip to content

Commit

Permalink
Merge pull request #27 from ontoportal-lirmm/feature/implement-new-va…
Browse files Browse the repository at this point in the history
…lidators

Feature: Implement new validators
  • Loading branch information
syphax-bouazzouni committed Sep 5, 2023
1 parent e1cdf2b commit b5ddfa3
Show file tree
Hide file tree
Showing 12 changed files with 405 additions and 30 deletions.
8 changes: 8 additions & 0 deletions lib/goo/validators/enforce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ def enforce(inst,attr,value)
check Goo::Validators::DataType, inst, attr, value, opt, DateTime
when :float, Float
check Goo::Validators::DataType, inst, attr, value, opt, Float
when :symmetric
check Goo::Validators::Symmetric, inst, attr, value, opt
when /^distinct_of_/
check Goo::Validators::DistinctOf, inst, attr, value, opt, opt
when /^superior_equal_to_/
check Goo::Validators::SuperiorEqualTo, inst, attr, value, opt, opt
when /^inverse_of_/
check Goo::Validators::InverseOf, inst, attr, value, opt, opt
when Proc
call_proc(opt, inst, attr)
when /^max_/, /^min_/
Expand Down
10 changes: 5 additions & 5 deletions lib/goo/validators/implementations/data_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class DataType < ValidatorBase
}

validity_check -> (obj) do
self.class.enforce_type(@type, @value)
self.enforce_type(@type, @value)
end

def initialize(inst, attr, value, type)
Expand All @@ -25,7 +25,7 @@ def initialize(inst, attr, value, type)



def self.enforce_type(type, value)
def enforce_type(type, value)
return true if value.nil?

if type == :boolean
Expand All @@ -44,21 +44,21 @@ def self.enforce_type(type, value)

end

def self.enforce_type_uri(value)
def enforce_type_uri(value)
return true if value.nil?

value.is_a?(RDF::URI) && value.valid?
end

def self.enforce_type_boolean(value)
def enforce_type_boolean(value)
if value.kind_of? Array
return value.select { |x| !is_a_boolean?(x) }.empty?
else
return is_a_boolean?(value)
end
end

def self.is_a_boolean?(value)
def is_a_boolean?(value)
return (value.class == TrueClass) || (value.class == FalseClass)
end
end
Expand Down
34 changes: 34 additions & 0 deletions lib/goo/validators/implementations/distinct_of.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Goo
module Validators
class DistinctOf < ValidatorBase
include Validator

key :distinct_of_

error_message ->(obj) { "`#{@attr}` must be distinct of `#{@property}`"}

validity_check -> (obj) do
return true if self.class.empty_value?(@value)

self.distinct?(@inst, @property, @value)
end

def initialize(inst, attr, value, key)
super(inst, attr, value)
@property = self.class.property(key)
end



def distinct?(inst, property, value)
target_values = self.class.attr_value(property, inst)
current_values = Array(value)

!current_values.any?{ |x| self.find_any?(target_values, x)}
end
def find_any?(array, value)
array.any?{ |x| self.class.equivalent_value?(value, x)}
end
end
end
end
15 changes: 1 addition & 14 deletions lib/goo/validators/implementations/existence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,10 @@ class Existence < ValidatorBase
error_message ->(obj) { "`#{@value}` value cannot be nil"}

validity_check -> (obj) do
not (@value.nil? || self.class.empty?(@value) || self.class.empty_array?(@value))
not self.class.empty_value?(@value)
end

def self.empty?(value)
empty_string?(value) || empty_to_s?(value)
end
def self.empty_string?(string)
string.is_a?(String) && string.strip.empty?
end

def self.empty_to_s?(object)
object && object.to_s&.strip.empty?
end

def self.empty_array?(array)
array.is_a?(Array) && array && array.reject{|x| x.nil? || empty?(x)}.empty?
end
end
end
end
35 changes: 35 additions & 0 deletions lib/goo/validators/implementations/inverse_of.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Goo
module Validators
class InverseOf < ValidatorBase
include Validator

key :inverse_of_

error_message ->(obj) {
"`#{@attr}` must be the inverse of ``#{@property}``"
}

validity_check -> (obj) do
return true if self.class.empty_value?(@value)

return Array(@value).select{|x| not inverse?(@property,x, @inst)}.empty?
end

def initialize(inst, attr, value, key)
super(inst, attr, value)
@property = self.class.property(key)
end

def inverse?(attr, value, source_object)
if self.class.respond_to?(attr, value)
target_values = self.class.attr_value(attr, value)
return target_values.any?{ |target_object| self.class.equivalent_value?(target_object, source_object)}
end

false
end


end
end
end
8 changes: 4 additions & 4 deletions lib/goo/validators/implementations/object_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class ObjectType < ValidatorBase
validity_check -> (obj) do
values = Array(@value)

unless values.select { |v| !self.class.is_a_model?(v, @model_range) }.empty?
unless values.select { |v| !self.is_a_model?(v, @model_range) }.empty?
@error = :no_range
return false
end

unless values.select { |v| !self.class.persistent?(v) }.empty?
unless values.select { |v| !self.persistent?(v) }.empty?
@error = :persistence
return false
end
Expand All @@ -34,11 +34,11 @@ def initialize(inst, attr, value, model_range)
@model_range = model_range
end

def self.is_a_model?(value, model_range)
def is_a_model?(value, model_range)
value.is_a?(model_range) || (value.respond_to?(:klass) && value[:klass] == model_range)
end

def self.persistent?(value)
def persistent?(value)
value.respond_to?(:klass) || value.persistent?
end
end
Expand Down
26 changes: 26 additions & 0 deletions lib/goo/validators/implementations/superior_equal_to.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Goo
module Validators
class SuperiorEqualTo < ValidatorBase
include Validator

key :superior_equal_to_

error_message ->(obj) {
"`#{@attr}` must be superior or equal to `#{@property}`"
}

validity_check -> (obj) do
target_values = self.class.attr_value(@property, @inst)

return true if target_values.empty?

return @value >= target_values.first
end

def initialize(inst, attr, value, key)
super(inst, attr, value)
@property = self.class.property(key)
end
end
end
end
33 changes: 33 additions & 0 deletions lib/goo/validators/implementations/symmetric.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Goo
module Validators
class Symmetric < ValidatorBase
include Validator

key :symmetric

error_message ->(obj) {
"`#{@attr}` must be symmetric"
}

validity_check -> (obj) do
return true if self.class.empty_value?(@value)

return Array(@value).select{|x| not symmetric?(@attr,x, @inst)}.empty?
end

def symmetric?(attr, value, source_object)
if respond_to?(attr, value)
target_values = self.class.attr_value(attr, value)
return target_values.any?{ |target_object| self.class.equivalent_value?(target_object, source_object)}
end

return false
end

def respond_to?(attr, object)
object && object.respond_to?(attr)
end

end
end
end
12 changes: 6 additions & 6 deletions lib/goo/validators/implementations/value_range.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ValueRange < ValidatorBase
keys [:min_, :max_]

error_message ->(obj) {
value = self.class.value_length(@value)
value = self.value_length(@value)
if @type == :min
"#{@attr} value has length `#{value}` and the min length is `#{@range}`"
else
Expand All @@ -15,27 +15,27 @@ class ValueRange < ValidatorBase
}

validity_check -> (obj) do
self.class.enforce_range_length(@type, @range, @value)
self.enforce_range_length(@type, @range, @value)
end

def initialize(inst, attr, value, type)
super(inst, attr, value)
@type = type.index("max_") ? :max : :min
@range = self.class.range(type)
@range = self.range(type)
end

def self.enforce_range_length(type_range, range, value)
def enforce_range_length(type_range, range, value)
return false if value.nil?
value_length = self.value_length(value)

(type_range.eql?(:min) && (value_length >= range)) || (type_range.eql?(:max) && (value_length <= range))
end

def self.range(opt)
def range(opt)
opt[4..opt.length].to_i
end

def self.value_length(value)
def value_length(value)
return 0 if value.nil?

if value.is_a?(String) || value.is_a?(Array)
Expand Down
45 changes: 45 additions & 0 deletions lib/goo/validators/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,55 @@ def error_message(message)
def validator_settings
@validator_settings ||= {}
end

def ids
Array(validator_settings[:id])
end

def property(key)
key[ids.first.size..key.size].to_sym
end

def respond_to?(attr, object)
object && object.respond_to?(attr)
end


def equivalent_value?(object1, object2)
if object1.respond_to?(:id) && object2.respond_to?(:id)
object1.id.eql?(object2.id)
else
object2 == object1
end
end

def attr_value(attr, object)
Array(object.send(attr))
end

def empty_value?(value)
value.nil? || empty?(value) || empty_array?(value)
end
def empty?(value)
empty_string?(value) || empty_to_s?(value)
end
def empty_string?(string)
string.is_a?(String) && string.strip.empty?
end

def empty_to_s?(object)
object && object.to_s&.strip.empty?
end

def empty_array?(array)
array.is_a?(Array) && array && array.reject{|x| x.nil? || empty?(x)}.empty?
end
end





end
end
end
Expand Down
5 changes: 4 additions & 1 deletion test/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ def self.create_test_case_data
end

def self.delete_test_case_data
objects = [Student, University, Program, Category, Address]
delete_all [Student, University, Program, Category, Address]
end

def self.delete_all(objects)
objects.each do |obj|
obj.where.include(obj.attributes).each do |i|
i.delete
Expand Down
Loading

0 comments on commit b5ddfa3

Please sign in to comment.