validy 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/validy.rb +142 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9c0d9fbaa3151e0a5e75e19287e7a363cf75f3eec4066c9a28f8c866b9d966fa
4
+ data.tar.gz: 2c92ccdad681600fe8b781701b157c7fbd2f5512a19b8bdc4cb704fc7ef097df
5
+ SHA512:
6
+ metadata.gz: 49e7c5f233d034b1ff5988500ce9163fe0994856720fb2159d09435f9538383b0c0ca2ca6408278288b8d3ed1af19842a585d6ca5728d51be4fcf05e5dacd8be
7
+ data.tar.gz: 6d296b8cf23575424c5015586ddc910dc2e4402f09f1439acc1f3433f5efe04d2b25a538a83d1d70b1245358c1aedf5d4bf1edcfeaa47ccf4ae0022aa8e35d3b
data/lib/validy.rb ADDED
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Validy
4
+ Error = Class.new(StandardError)
5
+ NotImplementedError = Class.new(StandardError)
6
+ OverImplemented = Class.new(StandardError)
7
+
8
+ def self.included(base)
9
+ base.send(:extend, ClassMethods)
10
+ base.send(:include, InstanceMethods)
11
+ base.prepend(Initializer)
12
+ end
13
+
14
+ module Initializer
15
+ def initialize(*)
16
+ @errors = {}
17
+ @valid = true
18
+ @evaluating_attribute = nil
19
+
20
+ super
21
+
22
+ if method_presented?(method_without_bang)
23
+ send(method_without_bang)
24
+ elsif method_presented?(method_with_bang)
25
+ send(method_with_bang)
26
+ else
27
+ raise NotImplementedError, 'validy method given from validy_on method: argument, must be implemented!'
28
+ end
29
+ end
30
+ end
31
+
32
+ module ClassMethods
33
+ def validy_on(method:)
34
+ method_with_bang_name = (method[-1] == '!' ? method.to_s : "#{method}!")
35
+ method_without_bang_name = method_with_bang_name.gsub('!', '')
36
+
37
+ define_method :method_with_bang do
38
+ method_with_bang_name
39
+ end
40
+
41
+ define_method :method_without_bang do
42
+ method_without_bang_name
43
+ end
44
+
45
+ hooks = Module.new do
46
+ method_with_bang_name = (method[-1] == '!' ? method.to_s : "#{method}!")
47
+ method_without_bang_name = method_with_bang_name.gsub('!', '')
48
+ define_method method_with_bang_name do |*args, &block|
49
+ if method_presented?(method_without_bang_name)
50
+ send(method_without_bang_name, *args, &block)
51
+ else
52
+ super(*args, &block)
53
+ end
54
+ raise ::Validy::Error, stringified_error unless valid?
55
+ end
56
+ end
57
+ prepend hooks
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+ # "add_error" adds an error and set valid state to false
63
+ # @return [FalseClass]
64
+ def add_error(args = {})
65
+ @errors.merge!(args)
66
+ @valid = false
67
+ end
68
+
69
+ # "valid?" returns inner valid state
70
+ # @return [Boolean]
71
+ def valid?
72
+ @valid
73
+ end
74
+
75
+ # "errors" returns errors hash
76
+ # @return [Hash]
77
+ def errors
78
+ @errors
79
+ end
80
+
81
+ # "condition" evaluates either passed block or instance method represented in the instance
82
+ def condition(method, error = nil, &block)
83
+ return self unless valid?
84
+
85
+ condition = method.respond_to?(:call) ? method.call : send(method)
86
+ validate_condition(condition, error, &block)
87
+ self
88
+ end
89
+
90
+ # "required" checks presence of the variable
91
+ def required(attribute, error = nil, &block)
92
+ return self unless valid?
93
+
94
+ @evaluating_attribute = instance_variable_get("@#{attribute}")
95
+ validate_condition(@evaluating_attribute, error || "#{attribute} required!", &block)
96
+ self
97
+ end
98
+
99
+ # "optional" starts void validation for the given attribute
100
+ def optional(attribute)
101
+ return self unless valid?
102
+
103
+ @evaluating_attribute = instance_variable_get("@#{attribute}")
104
+ self
105
+ end
106
+
107
+ # "type" validates type of the instance variable
108
+ def type(clazz, error = nil, &block)
109
+ return self unless valid?
110
+
111
+ validate_condition(@evaluating_attribute&.is_a?(clazz),
112
+ error || "#{@evaluating_attribute} is not a type #{clazz}", &block)
113
+ self
114
+ end
115
+
116
+ private
117
+
118
+ def method_presented?(method)
119
+ method_to_symed = method.to_sym
120
+ methods.any? { |m| m == method_to_symed }
121
+ end
122
+
123
+ def stringified_error
124
+ errors.inject(String.new) { |s, h| s << "#{h[0]}: #{h[1]}" }
125
+ end
126
+
127
+ def error_hash(error)
128
+ return error if error.is_a?(Hash)
129
+
130
+ { error: error }
131
+ end
132
+
133
+ def validate_condition(condition, error = nil, &block)
134
+ return if condition
135
+
136
+ error_hash = error_hash(error)
137
+ add_error(error_hash)
138
+
139
+ block.call if block_given?
140
+ end
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: validy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Oleg Saltykov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-01-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/validy.rb
20
+ homepage: https://github.com/nucleom42/validy
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubygems_version: 3.3.7
40
+ signing_key:
41
+ specification_version: 4
42
+ summary: Validy - simple way to turn ruby instance(object) into validateable object
43
+ with useful validity helpers
44
+ test_files: []