validy 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []