anodator 1.0.0.pre1 → 1.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +3 -0
- data/.gitignore +3 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -2
- data/README.md +9 -4
- data/Rakefile +3 -3
- data/anodator.gemspec +17 -14
- data/bin/console +3 -3
- data/bin/console-on-docker +4 -0
- data/bin/docker-console +2 -0
- data/bin/docker-prompt +2 -0
- data/bin/prompt-on-docker +4 -0
- data/bin/setup +0 -0
- data/example/example_01.rb +88 -61
- data/lib/anodator.rb +3 -2
- data/lib/anodator/anodator_error.rb +1 -1
- data/lib/anodator/check_result.rb +7 -7
- data/lib/anodator/checker.rb +33 -26
- data/lib/anodator/common.rb +15 -0
- data/lib/anodator/data_source.rb +87 -0
- data/lib/anodator/data_source_set.rb +36 -0
- data/lib/anodator/input_spec.rb +105 -111
- data/lib/anodator/input_spec_item.rb +8 -8
- data/lib/anodator/message.rb +14 -14
- data/lib/anodator/output_spec.rb +40 -43
- data/lib/anodator/rule.rb +26 -32
- data/lib/anodator/rule_set.rb +6 -12
- data/lib/anodator/utils.rb +36 -42
- data/lib/anodator/validator.rb +9 -9
- data/lib/anodator/validator/base.rb +44 -27
- data/lib/anodator/validator/blank_validator.rb +2 -2
- data/lib/anodator/validator/complex_validator.rb +12 -12
- data/lib/anodator/validator/configuration_error.rb +1 -2
- data/lib/anodator/validator/date_validator.rb +93 -103
- data/lib/anodator/validator/format_validator.rb +8 -11
- data/lib/anodator/validator/inclusion_validator.rb +3 -3
- data/lib/anodator/validator/length_validator.rb +6 -6
- data/lib/anodator/validator/numeric_validator.rb +13 -13
- data/lib/anodator/validator/presence_validator.rb +2 -2
- data/lib/anodator/validator/value_proxy.rb +31 -9
- data/lib/anodator/version.rb +1 -1
- metadata +41 -6
- data/VERSION +0 -1
data/lib/anodator/validator.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# load validators
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
2
|
+
require 'anodator/validator/base'
|
3
|
+
require 'anodator/validator/blank_validator'
|
4
|
+
require 'anodator/validator/complex_validator'
|
5
|
+
require 'anodator/validator/format_validator'
|
6
|
+
require 'anodator/validator/inclusion_validator'
|
7
|
+
require 'anodator/validator/length_validator'
|
8
|
+
require 'anodator/validator/numeric_validator'
|
9
|
+
require 'anodator/validator/presence_validator'
|
10
|
+
require 'anodator/validator/date_validator'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'anodator/validator/value_proxy'
|
2
2
|
|
3
3
|
module Anodator
|
4
4
|
module Validator
|
@@ -7,16 +7,19 @@ module Anodator
|
|
7
7
|
# value of target for validation
|
8
8
|
@@values = nil
|
9
9
|
|
10
|
+
# data source set
|
11
|
+
@@data_source_set = nil
|
12
|
+
|
10
13
|
# valid option keys
|
11
14
|
#
|
12
15
|
# :allow_blank options are all available options in Validator.
|
13
16
|
# In addition, Validator All you need to consider the case of the blank.
|
14
|
-
@valid_option_keys = [
|
17
|
+
@valid_option_keys = %i[allow_blank description]
|
15
18
|
|
16
19
|
# default options
|
17
20
|
#
|
18
21
|
# Is used as the initial value was not set when you create a new Validator.
|
19
|
-
@default_options = { :
|
22
|
+
@default_options = { allow_blank: false }
|
20
23
|
|
21
24
|
# target specify value
|
22
25
|
attr_reader :target
|
@@ -32,43 +35,41 @@ module Anodator
|
|
32
35
|
def valid_option_keys(*option_keys)
|
33
36
|
# initialize from superclass
|
34
37
|
if @valid_option_keys.nil?
|
35
|
-
@valid_option_keys =
|
38
|
+
@valid_option_keys = superclass.valid_option_keys
|
36
39
|
end
|
37
40
|
|
38
41
|
unless option_keys.size.zero?
|
39
42
|
option_keys.each do |key|
|
40
43
|
if @valid_option_keys.include?(key)
|
41
|
-
raise ArgumentError
|
44
|
+
raise ArgumentError, "Validator already has option for '#{key}'"
|
42
45
|
else
|
43
46
|
@valid_option_keys << key
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
|
-
|
51
|
+
@valid_option_keys.dup
|
49
52
|
end
|
50
53
|
|
51
54
|
# set and/or get default options
|
52
55
|
def default_options(options = nil)
|
53
56
|
# initialize from superclass
|
54
|
-
if @default_options.nil?
|
55
|
-
@default_options = self.superclass.default_options
|
56
|
-
end
|
57
|
+
@default_options = superclass.default_options if @default_options.nil?
|
57
58
|
|
58
59
|
unless options.nil?
|
59
60
|
unless options.is_a? Hash
|
60
|
-
raise ArgumentError
|
61
|
+
raise ArgumentError, 'default_options must call with Hash'
|
61
62
|
end
|
62
63
|
options.each do |option, default_value|
|
63
64
|
if @valid_option_keys.include?(option)
|
64
65
|
@default_options[option] = default_value
|
65
66
|
else
|
66
|
-
raise ArgumentError
|
67
|
+
raise ArgumentError, "Unknown option '#{option}'"
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
|
72
|
+
@default_options.dup
|
72
73
|
end
|
73
74
|
|
74
75
|
# Set the data to be checked.
|
@@ -78,13 +79,25 @@ module Anodator
|
|
78
79
|
if values.respond_to?(:[])
|
79
80
|
@@values = values
|
80
81
|
else
|
81
|
-
raise ArgumentError
|
82
|
+
raise ArgumentError, 'values must be respond to [] method for validations.'
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
85
86
|
# Get the data to be checked
|
86
87
|
def values
|
87
|
-
|
88
|
+
@@values
|
89
|
+
end
|
90
|
+
|
91
|
+
# Set the data source with check.
|
92
|
+
def data_source_set=(data_source_set)
|
93
|
+
msg = 'data_source_set must be Anodator::DataSourceSet'
|
94
|
+
raise ArgumentError, msg unless data_source_set.is_a? DataSourceSet
|
95
|
+
|
96
|
+
@@data_source_set = data_source_set
|
97
|
+
end
|
98
|
+
|
99
|
+
def data_source_set
|
100
|
+
@@data_source_set
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
@@ -97,13 +110,13 @@ module Anodator
|
|
97
110
|
# +valid_option_keys+.
|
98
111
|
# If necessary add additional parameters for the new validator is defined
|
99
112
|
# in the inherited class to add.
|
100
|
-
def initialize(target_expression, options = {
|
113
|
+
def initialize(target_expression, options = {})
|
101
114
|
if target_expression.to_s.length.zero?
|
102
|
-
raise ArgumentError
|
115
|
+
raise ArgumentError, 'target cannot be nil or blank'
|
103
116
|
else
|
104
117
|
@target = target_expression.to_s
|
105
118
|
end
|
106
|
-
@options = {
|
119
|
+
@options = {}
|
107
120
|
merge_options!(self.class.default_options)
|
108
121
|
merge_options!(options)
|
109
122
|
end
|
@@ -115,7 +128,7 @@ module Anodator
|
|
115
128
|
# Can be implemented to return a boolean value to the final,
|
116
129
|
# +valid?+ The method used is called.
|
117
130
|
def validate
|
118
|
-
raise NoMethodError
|
131
|
+
raise NoMethodError, "must define method 'validate'"
|
119
132
|
end
|
120
133
|
|
121
134
|
# Call the +validate+ method to return a boolean value accordingly
|
@@ -123,7 +136,7 @@ module Anodator
|
|
123
136
|
# If any exception occurs in the +validate+ method displays the contents
|
124
137
|
# to standard error. Then raise same error.
|
125
138
|
def valid?
|
126
|
-
|
139
|
+
validate
|
127
140
|
end
|
128
141
|
|
129
142
|
# merge options
|
@@ -134,7 +147,7 @@ module Anodator
|
|
134
147
|
if self.class.valid_option_keys.include?(key)
|
135
148
|
@options[key] = value
|
136
149
|
else
|
137
|
-
raise ArgumentError
|
150
|
+
raise ArgumentError, "Unknown option key '#{key}'."
|
138
151
|
end
|
139
152
|
end
|
140
153
|
end
|
@@ -145,19 +158,23 @@ module Anodator
|
|
145
158
|
#
|
146
159
|
# always return String object use to_s method
|
147
160
|
def target_value
|
148
|
-
|
161
|
+
@@values[target].to_s
|
149
162
|
end
|
150
163
|
|
151
164
|
def argument_value_at(name_or_index)
|
152
|
-
|
165
|
+
@@values[name_or_index].to_s
|
166
|
+
end
|
167
|
+
|
168
|
+
def data_source_at(identifier, key, column)
|
169
|
+
@@data_source_set.fetch(identifier, key, column)
|
153
170
|
end
|
154
171
|
|
155
172
|
def allow_blank?
|
156
|
-
|
173
|
+
@options[:allow_blank]
|
157
174
|
end
|
158
175
|
|
159
176
|
def description
|
160
|
-
|
177
|
+
@options[:description]
|
161
178
|
end
|
162
179
|
|
163
180
|
def proxy_value(target)
|
@@ -165,14 +182,14 @@ module Anodator
|
|
165
182
|
end
|
166
183
|
private :proxy_value
|
167
184
|
|
168
|
-
def to_s(level = 4,
|
169
|
-
(
|
185
|
+
def to_s(level = 4, _step = 2)
|
186
|
+
(' ' * level) + "- #{self.class}(#{description})"
|
170
187
|
end
|
171
188
|
|
172
189
|
def validate_configuration
|
173
190
|
@@values.spec_item_by_expression(@target)
|
174
191
|
rescue UnknownTargetExpressionError => e
|
175
|
-
raise InvalidConfiguration
|
192
|
+
raise InvalidConfiguration, e.to_s
|
176
193
|
end
|
177
194
|
end
|
178
195
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'anodator/validator/base'
|
2
2
|
|
3
3
|
module Anodator
|
4
4
|
module Validator
|
@@ -7,7 +7,7 @@ module Anodator
|
|
7
7
|
# This is the Validator to validate whether the value is not present.
|
8
8
|
class BlankValidator < Base
|
9
9
|
def validate
|
10
|
-
|
10
|
+
target_value.split(//).size.zero?
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'anodator/validator/configuration_error'
|
2
2
|
|
3
3
|
module Anodator
|
4
4
|
module Validator
|
@@ -6,20 +6,20 @@ module Anodator
|
|
6
6
|
# Validators.
|
7
7
|
class ComplexValidator < Base
|
8
8
|
# Combine logical OR of each Validators
|
9
|
-
LOGIC_OR =
|
9
|
+
LOGIC_OR = 'OR'.freeze
|
10
10
|
# Combine logical AND of each Validators
|
11
|
-
LOGIC_AND =
|
11
|
+
LOGIC_AND = 'AND'.freeze
|
12
12
|
|
13
13
|
valid_option_keys :validators, :logic
|
14
|
-
default_options :
|
14
|
+
default_options logic: LOGIC_AND
|
15
15
|
|
16
|
-
def initialize(options = {
|
17
|
-
super(
|
16
|
+
def initialize(options = {})
|
17
|
+
super('dummy', options)
|
18
18
|
end
|
19
19
|
|
20
20
|
def validate
|
21
21
|
if @options[:validators].nil?
|
22
|
-
raise ConfigurationError
|
22
|
+
raise ConfigurationError, 'ComplexValidator must have validators option'
|
23
23
|
end
|
24
24
|
case @options[:logic]
|
25
25
|
when LOGIC_OR
|
@@ -33,15 +33,15 @@ module Anodator
|
|
33
33
|
end
|
34
34
|
return true
|
35
35
|
else
|
36
|
-
raise ConfigurationError
|
36
|
+
raise ConfigurationError, "Unknown logic option '#{@options[:logic]}"
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
def logic_expression
|
41
41
|
if @options[:logic] == LOGIC_OR
|
42
|
-
|
42
|
+
'OR'
|
43
43
|
elsif @options[:logic] == LOGIC_AND
|
44
|
-
|
44
|
+
'AND'
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -51,9 +51,9 @@ module Anodator
|
|
51
51
|
|
52
52
|
def to_s(level = 2, step = 2)
|
53
53
|
buf = "#{super(level, step)} LOGIC: #{logic_expression}\n"
|
54
|
-
buf += @options[:validators].map
|
54
|
+
buf += @options[:validators].map do |validator|
|
55
55
|
validator.to_s(level + step, step)
|
56
|
-
|
56
|
+
end.join("\n")
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -1,148 +1,138 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'anodator/validator/base'
|
2
|
+
require 'date'
|
3
3
|
|
4
4
|
module Anodator
|
5
5
|
module Validator
|
6
|
+
# Validator for Date expression.
|
6
7
|
class DateValidator < Base
|
7
|
-
FORMAT_SCANNER_REGEXP =
|
8
|
+
FORMAT_SCANNER_REGEXP =
|
9
|
+
/((YY(?:YY)?)|(M(?![YMD]))|(MM)|(D(?![YMD]))|(DD))/
|
10
|
+
HOLDER_DEFS = {
|
11
|
+
'YYYY' => :year,
|
12
|
+
'YY' => :short_year,
|
13
|
+
'MM' => :month,
|
14
|
+
'M' => :month,
|
15
|
+
'DD' => :day,
|
16
|
+
'D' => :day
|
17
|
+
}.freeze
|
18
|
+
HOLDERS = %w[YYYY YY MM M DD D].freeze
|
19
|
+
REGEXPS = %w[(\d{4}) (\d{2}) (\d{2}) (\d{1,2}) (\d{2}) (\d{1,2})].freeze
|
8
20
|
|
9
21
|
valid_option_keys :from, :to, :format, :base_year
|
10
|
-
default_options :
|
22
|
+
default_options format: 'YYYY-MM-DD', base_year: 2000
|
11
23
|
|
12
|
-
def initialize(target_expression, options = {
|
24
|
+
def initialize(target_expression, options = {})
|
13
25
|
super(target_expression, options)
|
14
26
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
[:from, :to].each do |key|
|
19
|
-
if !@options[key].nil?
|
20
|
-
@options[key] = proxy_value(@options[key])
|
21
|
-
if @options[key].direct? && !@options[key].value.is_a?(Date)
|
22
|
-
date = parse_date(@options[key].value.to_s)
|
23
|
-
if date.nil?
|
24
|
-
raise ArgumentError.new("Invalid date expression '#{@options[key].value}'")
|
25
|
-
else
|
26
|
-
@options[key] = proxy_value(date)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
27
|
+
check_format
|
28
|
+
setup_period_options
|
31
29
|
end
|
32
30
|
|
33
31
|
def validate
|
34
|
-
if allow_blank?
|
35
|
-
|
36
|
-
|
32
|
+
return true if allow_blank? && target_value.split(//).size.zero?
|
33
|
+
date = parse_date(target_value)
|
34
|
+
return false unless date
|
37
35
|
|
36
|
+
validate_period(date)
|
37
|
+
rescue ArgumentError # invalid date expression
|
38
|
+
return false
|
39
|
+
end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@options.each do |option, configuration|
|
44
|
-
case option
|
45
|
-
when :from
|
46
|
-
return false if parse_date(configuration.value) > date
|
47
|
-
when :to
|
48
|
-
return false if parse_date(configuration.value) < date
|
49
|
-
end
|
50
|
-
end
|
41
|
+
def validate_period(date)
|
42
|
+
valid_from = from ? from_date <= date : true
|
43
|
+
valid_to = to ? to_date >= date : true
|
51
44
|
|
52
|
-
|
53
|
-
rescue ArgumentError
|
54
|
-
# invalid date expression
|
55
|
-
return false
|
56
|
-
end
|
45
|
+
valid_from && valid_to
|
57
46
|
end
|
58
47
|
|
59
48
|
def from
|
60
|
-
|
61
|
-
return @options[:from].dup
|
62
|
-
else
|
63
|
-
return nil
|
64
|
-
end
|
49
|
+
@options[:from].dup
|
65
50
|
end
|
66
51
|
|
67
52
|
def to
|
68
|
-
|
69
|
-
return @options[:to].dup
|
70
|
-
else
|
71
|
-
return nil
|
72
|
-
end
|
53
|
+
@options[:to].dup
|
73
54
|
end
|
74
55
|
|
75
56
|
def format
|
76
|
-
|
57
|
+
@options[:format].dup
|
77
58
|
end
|
78
59
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
60
|
+
def base_year
|
61
|
+
@options[:base_year].to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
def from_date
|
65
|
+
from ? parse_date(from.value) : nil
|
66
|
+
end
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
68
|
+
def to_date
|
69
|
+
to ? parse_date(to.value) : nil
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
90
73
|
|
91
|
-
|
74
|
+
def setup_period_options
|
75
|
+
%i[from to].each do |key|
|
76
|
+
setup_date_option(key) if @options.key?(key)
|
92
77
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
def setup_date_option(key)
|
81
|
+
option = proxy_value(@options[key])
|
82
|
+
if option.direct? && !option.value.is_a?(Date)
|
83
|
+
date = parse_date(option.value.to_s)
|
84
|
+
msg = "Invalid date expression '#{option.value}'"
|
85
|
+
raise ArgumentError, msg if date.nil?
|
86
|
+
|
87
|
+
option = proxy_value(date)
|
96
88
|
end
|
97
89
|
|
98
|
-
|
90
|
+
@options[key] = option
|
99
91
|
end
|
100
|
-
private :parse_date
|
101
92
|
|
102
|
-
def
|
103
|
-
|
93
|
+
def parse_date(date_expression)
|
94
|
+
return date_expression if date_expression.is_a? Date
|
95
|
+
return nil unless date_regexp.match(date_expression)
|
104
96
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
97
|
+
date_hash = date_regexp_holders.each_with_object({})
|
98
|
+
.with_index(1) do |(key, hash), i|
|
99
|
+
hash[key] = Regexp.last_match[i].to_i
|
100
|
+
end
|
101
|
+
convert_short_year(date_hash)
|
102
|
+
Date.new(date_hash[:year], date_hash[:month], date_hash[:day])
|
103
|
+
end
|
112
104
|
|
113
|
-
|
105
|
+
def convert_short_year(hash)
|
106
|
+
hash[:year] = base_year + hash[:short_year] if hash.key?(:short_year)
|
114
107
|
end
|
115
|
-
private :date_regexp
|
116
108
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
holders = scans.map do |scan|
|
121
|
-
case scan.first
|
122
|
-
when "YYYY"
|
123
|
-
year_count += 1
|
124
|
-
:year
|
125
|
-
when "YY"
|
126
|
-
year_count += 1
|
127
|
-
:short_year
|
128
|
-
when "MM", "M"
|
129
|
-
month_count += 1
|
130
|
-
:month
|
131
|
-
when "DD", "D"
|
132
|
-
day_count += 1
|
133
|
-
:day
|
134
|
-
end
|
109
|
+
def date_regexp
|
110
|
+
regexp_string = HOLDERS.each_with_index.inject(format) do |s, (h, i)|
|
111
|
+
s.sub(/#{h}/, REGEXPS[i])
|
135
112
|
end
|
136
|
-
|
137
|
-
|
113
|
+
|
114
|
+
/^#{regexp_string}$/
|
115
|
+
end
|
116
|
+
|
117
|
+
def date_regexp_holders
|
118
|
+
format.scan(FORMAT_SCANNER_REGEXP).map do |scan|
|
119
|
+
HOLDER_DEFS[scan.first]
|
138
120
|
end
|
139
|
-
|
140
|
-
|
121
|
+
end
|
122
|
+
|
123
|
+
def check_format
|
124
|
+
msg = 'date format must be contained year(YYYY or YY), ' \
|
125
|
+
'month(MM or M) and day(DD or D).'
|
126
|
+
hash = { year: :year, month: :month, day: :day, short_year: :year }
|
127
|
+
|
128
|
+
checked_holders = date_regexp_holders.inject([]) do |array, holder|
|
129
|
+
array << hash[holder]
|
141
130
|
end
|
142
131
|
|
143
|
-
|
132
|
+
raise ArgumentError, msg if checked_holders.include?(nil)
|
133
|
+
raise ArgumentError, msg unless checked_holders.size == 3
|
134
|
+
raise ArgumentError, msg unless checked_holders.uniq!.nil?
|
144
135
|
end
|
145
|
-
private :date_regexp_holders
|
146
136
|
end
|
147
137
|
end
|
148
138
|
end
|