anodator 1.0.0.pre1 → 1.0.0.pre2
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.
- 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
|