Created
December 31, 2018 11:15
-
-
Save isubas/a935319bc56b6d450eb791b595adaaad to your computer and use it in GitHub Desktop.
Basit Validasyon Modulü ve Örnekleri
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module VirtualPos | |
# TypeCheckError | |
class TypeCheckerError < StandardError | |
attr_reader :attribute, :object | |
def initialize(attribute: nil, message: nil, object: nil) | |
@attribute = attribute | |
@object = object | |
super(message || "Type in not valid for #{attribute}") | |
end | |
end | |
# RuleCheckError | |
class RuleCheckerError < StandardError | |
attr_reader :attribute, :object | |
def initialize(attribute: nil, message: nil, object: nil) | |
@attribute = attribute | |
@object = object | |
super(message || "Rule failed for #{attribute}") | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Test | |
include VirtualPos::SimpleValidation | |
validate :foo, type: :string, rule: ->(value) { value.length > 3 } | |
validate :bar, type: :integer, rule: ->(value) { value >= 1 } | |
attr_reader :foo, :bar | |
def initialize(foo, bar) | |
@foo = foo | |
@bar = bar | |
end | |
end | |
# Examples | |
Test.validations | |
test = Test.new('ABC', 0) | |
test.valid? # => false | |
test.errors # => {:foo=>[#<VirtualPos::RuleCheckerError: Rule failed for foo>], :bar=>[#<VirtualPos::RuleCheckerError: Rule failed for bar>]} | |
test = Test.new('ABCD', '1') | |
test.valid? # => false | |
test.errors # => {:bar=>[#<VirtualPos::TypeCheckerError: Type in not valid for bar>, #<VirtualPos::RuleCheckerError: Rule failed for bar>]} | |
test.valid! # raise VirtualPos::TypeCheckerError: Type in not valid for bar | |
test = Test.new('ABCD', 1) | |
test.valid? # => true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ProcSafeCall | |
refine Proc do | |
def safe_call(args) | |
call(args) | |
rescue ArgumentError, NoMethodError | |
nil | |
end | |
end | |
end | |
module VirtualPos | |
# SimpleValidation | |
module SimpleValidation | |
# InvalidRule | |
class InvalidRule < StandardError | |
def initialize(attribute) | |
@attribute = attribute | |
end | |
def message | |
"Rule invalid for #{@attribute}" | |
end | |
end | |
# Validator | |
class Validator | |
using ProcSafeCall | |
TYPES = { | |
string: [String], | |
hash: [Hash], | |
integer: [Integer, Fixnum, Float], | |
bolean: [TrueClass, FalseClass] | |
}.freeze | |
attr_reader :attribute, :type, :rule, :object, :strict | |
def initialize(attribute, type: nil, rule: -> { true }) | |
raise InvalidRule, attribute unless rule.class == Proc || rule.nil? | |
@attribute = attribute | |
@type = type | |
@rule = rule | |
end | |
def valid?(object, strict: false) | |
type_check(object) | |
rule_check(object) | |
error_for_object = errors(object, init: false) | |
return true if error_for_object.empty? | |
raise error_for_object.first if strict | |
end | |
private | |
def type_check(object) | |
return true if TYPES.fetch(type, [type]).include?( | |
object.public_send(attribute).class | |
) | |
errors(object) << TypeCheckerError.new(attribute: attribute, object: object) | |
end | |
def rule_check(object) | |
return true if rule.nil? || rule.safe_call(object.public_send(attribute)) | |
errors(object) << RuleCheckerError.new(attribute: attribute, object: object) | |
end | |
def errors(object, init: true) | |
object.errors[attribute] = [] if !object.errors.key?(attribute) && init | |
object.errors[attribute] || [] | |
end | |
end | |
def self.included(base) | |
base.send :include, InstanceMethods | |
base.extend ClassMethods | |
end | |
# ClassMethods | |
module ClassMethods | |
attr_reader :validations | |
def validate(attribute, type: nil, rule: nil) | |
@validations ||= [] | |
@validations << Validator.new(attribute, type: type, rule: rule) | |
end | |
end | |
# InstanceMethods | |
module InstanceMethods | |
attr_reader :errors | |
def valid! | |
return true if valid?(strict: true) | |
end | |
def valid?(strict: false) | |
@errors = {} | |
self.class.validations.each { |validator| validator.valid?(self, strict: strict) } | |
errors.empty? | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment