respect 0.1.0
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.
- data/MIT-LICENSE +20 -0
- data/README.md +289 -0
- data/RELATED_WORK.md +40 -0
- data/RELEASE_NOTES.md +23 -0
- data/Rakefile +31 -0
- data/STATUS_MATRIX.html +137 -0
- data/lib/respect.rb +231 -0
- data/lib/respect/any_schema.rb +22 -0
- data/lib/respect/array_def.rb +28 -0
- data/lib/respect/array_schema.rb +203 -0
- data/lib/respect/boolean_schema.rb +32 -0
- data/lib/respect/composite_schema.rb +86 -0
- data/lib/respect/core_statements.rb +206 -0
- data/lib/respect/datetime_schema.rb +27 -0
- data/lib/respect/def_without_name.rb +6 -0
- data/lib/respect/divisible_by_validator.rb +20 -0
- data/lib/respect/doc_helper.rb +24 -0
- data/lib/respect/doc_parser.rb +37 -0
- data/lib/respect/dsl_dumper.rb +181 -0
- data/lib/respect/equal_to_validator.rb +20 -0
- data/lib/respect/fake_name_proxy.rb +116 -0
- data/lib/respect/float_schema.rb +27 -0
- data/lib/respect/format_validator.rb +136 -0
- data/lib/respect/global_def.rb +79 -0
- data/lib/respect/greater_than_or_equal_to_validator.rb +19 -0
- data/lib/respect/greater_than_validator.rb +19 -0
- data/lib/respect/has_constraints.rb +34 -0
- data/lib/respect/hash_def.rb +40 -0
- data/lib/respect/hash_schema.rb +218 -0
- data/lib/respect/in_validator.rb +19 -0
- data/lib/respect/integer_schema.rb +27 -0
- data/lib/respect/ip_addr_schema.rb +23 -0
- data/lib/respect/ipv4_addr_schema.rb +27 -0
- data/lib/respect/ipv6_addr_schema.rb +27 -0
- data/lib/respect/items_def.rb +21 -0
- data/lib/respect/json_schema_html_formatter.rb +143 -0
- data/lib/respect/less_than_or_equal_to_validator.rb +19 -0
- data/lib/respect/less_than_validator.rb +19 -0
- data/lib/respect/match_validator.rb +19 -0
- data/lib/respect/max_length_validator.rb +20 -0
- data/lib/respect/min_length_validator.rb +20 -0
- data/lib/respect/multiple_of_validator.rb +10 -0
- data/lib/respect/null_schema.rb +26 -0
- data/lib/respect/numeric_schema.rb +33 -0
- data/lib/respect/org3_dumper.rb +213 -0
- data/lib/respect/regexp_schema.rb +19 -0
- data/lib/respect/schema.rb +285 -0
- data/lib/respect/schema_def.rb +16 -0
- data/lib/respect/string_schema.rb +21 -0
- data/lib/respect/unit_test_helper.rb +37 -0
- data/lib/respect/uri_schema.rb +23 -0
- data/lib/respect/utc_time_schema.rb +17 -0
- data/lib/respect/validator.rb +51 -0
- data/lib/respect/version.rb +3 -0
- data/test/any_schema_test.rb +79 -0
- data/test/array_def_test.rb +113 -0
- data/test/array_schema_test.rb +487 -0
- data/test/boolean_schema_test.rb +89 -0
- data/test/composite_schema_test.rb +30 -0
- data/test/datetime_schema_test.rb +83 -0
- data/test/doc_helper_test.rb +34 -0
- data/test/doc_parser_test.rb +109 -0
- data/test/dsl_dumper_test.rb +395 -0
- data/test/fake_name_proxy_test.rb +138 -0
- data/test/float_schema_test.rb +146 -0
- data/test/format_validator_test.rb +224 -0
- data/test/hash_def_test.rb +126 -0
- data/test/hash_schema_test.rb +613 -0
- data/test/integer_schema_test.rb +142 -0
- data/test/ip_addr_schema_test.rb +78 -0
- data/test/ipv4_addr_schema_test.rb +71 -0
- data/test/ipv6_addr_schema_test.rb +71 -0
- data/test/json_schema_html_formatter_test.rb +214 -0
- data/test/null_schema_test.rb +46 -0
- data/test/numeric_schema_test.rb +294 -0
- data/test/org3_dumper_test.rb +784 -0
- data/test/regexp_schema_test.rb +54 -0
- data/test/respect_test.rb +108 -0
- data/test/schema_def_test.rb +405 -0
- data/test/schema_test.rb +290 -0
- data/test/string_schema_test.rb +209 -0
- data/test/support/circle.rb +11 -0
- data/test/support/color.rb +24 -0
- data/test/support/point.rb +11 -0
- data/test/support/respect/circle_schema.rb +16 -0
- data/test/support/respect/color_def.rb +19 -0
- data/test/support/respect/color_schema.rb +33 -0
- data/test/support/respect/point_schema.rb +19 -0
- data/test/support/respect/rgba_schema.rb +20 -0
- data/test/support/respect/universal_validator.rb +25 -0
- data/test/support/respect/user_macros.rb +12 -0
- data/test/support/rgba.rb +11 -0
- data/test/test_helper.rb +90 -0
- data/test/uri_schema_test.rb +54 -0
- data/test/utc_time_schema_test.rb +63 -0
- data/test/validator_test.rb +22 -0
- metadata +288 -0
@@ -0,0 +1,181 @@
|
|
1
|
+
module Respect
|
2
|
+
# Dump a schema to a string representation using the DSL syntax so you
|
3
|
+
# can evaluate it and get the same schema back.
|
4
|
+
#
|
5
|
+
# Theoretically, this must always be true:
|
6
|
+
# eval(DslDumper.new(schema).dump) == schema
|
7
|
+
#
|
8
|
+
# The current implementation covers all the _Schema_ and _Validator_
|
9
|
+
# classes defined in this package. User-defined sub-class of {Schema}
|
10
|
+
# are not guarantee to work. Specially those using a custom "Def" class
|
11
|
+
# or with special attributes. The API of this dumper is *experimental*,
|
12
|
+
# so relying on it to teach the dumper how to dump a user-defined schema
|
13
|
+
# class may break in future releases.
|
14
|
+
#
|
15
|
+
# However, sub-classes of {CompositeSchema} are handled
|
16
|
+
# properly as well as all {Validator} sub-classes.
|
17
|
+
class DslDumper
|
18
|
+
|
19
|
+
def initialize(schema)
|
20
|
+
@schema = schema
|
21
|
+
@indent_level = 0
|
22
|
+
@indent_size = 2
|
23
|
+
@context_data = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :schema, :output
|
27
|
+
|
28
|
+
def dump(output = nil)
|
29
|
+
@output = output
|
30
|
+
@output ||= String.new
|
31
|
+
self << "Respect::Schema.define do |s|"
|
32
|
+
self.indent do
|
33
|
+
self.dump_schema(@schema)
|
34
|
+
end
|
35
|
+
self << "\nend\n"
|
36
|
+
@output
|
37
|
+
end
|
38
|
+
|
39
|
+
def <<(str)
|
40
|
+
@output << str.gsub(/(\n+)/, "\\1#{indentation}")
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def indent(count = 1, &block)
|
45
|
+
@indent_level += count
|
46
|
+
if block
|
47
|
+
block.call
|
48
|
+
unindent(count)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def unindent(count = 1)
|
53
|
+
@indent_level -= count
|
54
|
+
end
|
55
|
+
|
56
|
+
def indentation
|
57
|
+
" " * @indent_size * @indent_level
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_accessor :context_data
|
61
|
+
|
62
|
+
def dump_block(args = [ "s" ], &block)
|
63
|
+
self << " do |#{args.join(', ')}|"
|
64
|
+
self.indent(&block)
|
65
|
+
self << "\nend"
|
66
|
+
end
|
67
|
+
|
68
|
+
def dump_schema(schema)
|
69
|
+
self.dump_doc(schema)
|
70
|
+
self << "\ns."
|
71
|
+
self.dump_name(schema)
|
72
|
+
self.dump_arguments(schema)
|
73
|
+
self.dump_body(schema)
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def dump_doc(schema, prefix = false)
|
78
|
+
if schema.doc
|
79
|
+
if schema.description
|
80
|
+
self << "\n"
|
81
|
+
self << %q{s.doc <<-EOS.strip_heredoc}
|
82
|
+
self.indent do
|
83
|
+
self << "\n"
|
84
|
+
self << schema.doc
|
85
|
+
self << "EOS"
|
86
|
+
end
|
87
|
+
else
|
88
|
+
self << "\ns.doc \"#{schema.title}\""
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def dump_name(schema)
|
94
|
+
self << schema.class.statement_name
|
95
|
+
end
|
96
|
+
|
97
|
+
def dump_arguments(schema)
|
98
|
+
# Fetch name if there is one?
|
99
|
+
if self.context_data.has_key?(:name)
|
100
|
+
name = self.context_data[:name]
|
101
|
+
else
|
102
|
+
name = nil
|
103
|
+
end
|
104
|
+
# Compute options to dump.
|
105
|
+
options = schema.non_default_options.reject do |opt|
|
106
|
+
opt == :doc
|
107
|
+
end
|
108
|
+
# Dump name and options
|
109
|
+
if name || !options.empty?
|
110
|
+
if name
|
111
|
+
self << " "
|
112
|
+
self << name.inspect
|
113
|
+
end
|
114
|
+
if !options.empty?
|
115
|
+
if name
|
116
|
+
self << ","
|
117
|
+
end
|
118
|
+
self << " "
|
119
|
+
self.dump_options(schema)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
def dump_options(schema)
|
126
|
+
options = schema.non_default_options
|
127
|
+
option_keys = options.keys
|
128
|
+
option_keys.each do |opt|
|
129
|
+
self << opt.inspect
|
130
|
+
self << " => "
|
131
|
+
self << options[opt].inspect
|
132
|
+
self << ", " unless opt == option_keys.last
|
133
|
+
end
|
134
|
+
self
|
135
|
+
end
|
136
|
+
|
137
|
+
def dump_body(schema)
|
138
|
+
symbol = "dump_body_for_#{schema.class.statement_name}"
|
139
|
+
if respond_to? symbol
|
140
|
+
send(symbol, schema)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def dump_body_for_hash(schema)
|
145
|
+
dump_block do
|
146
|
+
schema.properties.each do |name, schema|
|
147
|
+
context_data[:name] = name
|
148
|
+
dump_schema(schema)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def dump_body_for_array(schema)
|
154
|
+
dump_block do
|
155
|
+
context_data.delete(:name)
|
156
|
+
if schema.item
|
157
|
+
dump_schema(schema.item)
|
158
|
+
end
|
159
|
+
if schema.items && !schema.items.empty?
|
160
|
+
self << "\ns.items do |s|"
|
161
|
+
indent do
|
162
|
+
schema.items.each do |schema|
|
163
|
+
dump_schema(schema)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
self << "\nend"
|
167
|
+
end
|
168
|
+
if schema.extra_items && !schema.extra_items.empty?
|
169
|
+
self << "\ns.extra_items do |s|"
|
170
|
+
indent do
|
171
|
+
schema.extra_items.each do |schema|
|
172
|
+
dump_schema(schema)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
self << "\nend"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end # module Respect
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Respect
|
2
|
+
class EqualToValidator < Validator
|
3
|
+
def initialize(expected)
|
4
|
+
@expected = expected
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(value)
|
8
|
+
unless value == @expected
|
9
|
+
raise ValidationError,
|
10
|
+
"wrong value: `#{value}':#{value.class} instead of `#@expected':#{@expected.class}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def to_h_org3
|
17
|
+
{ 'enum' => [ @expected ] }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Respect
|
2
|
+
# The evaluation proxy used for the DSL.
|
3
|
+
#
|
4
|
+
# This class sends all methods it receives to the target object it has
|
5
|
+
# received when initialized.
|
6
|
+
#
|
7
|
+
# If the target's response to +accept_name?+ is +false+, this proxy
|
8
|
+
# passes a +nil+ value as first argument to target's dynamic methods
|
9
|
+
# and target's methods expecting a name as first argument.
|
10
|
+
#
|
11
|
+
# This is useful to factor method code that should work in two different
|
12
|
+
# contexts. For instance, in the context of a hash schema definition,
|
13
|
+
# core statements expect a name as first argument whereas in the context
|
14
|
+
# of an array schema definition they do not.
|
15
|
+
#
|
16
|
+
# HashSchema.define do |s|
|
17
|
+
# s.integer "age", greater_than: 0
|
18
|
+
# end
|
19
|
+
# ArraySchema.define do |s|
|
20
|
+
# # FakeNameProxy passes +nil+ here as value for the +name+ argument.
|
21
|
+
# s.integer greater_than: 0
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# To factor this code, we define the +integer+ method in a module included
|
25
|
+
# in both context classes.
|
26
|
+
#
|
27
|
+
# module CoreStatements
|
28
|
+
# def integer(name, options = {})
|
29
|
+
# update_context name, IntegerSchema.define(options)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# class HashDef
|
33
|
+
# include CoreStatements
|
34
|
+
# def accept_name?; true; end
|
35
|
+
# def update_context(name, schema)
|
36
|
+
# @hash_schema[name] = schema
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# class ArrayDef
|
40
|
+
# include CoreStatements
|
41
|
+
# def accept_name?; false; end
|
42
|
+
# def update_context(name, schema)
|
43
|
+
# @array_schema.item = schema
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# The +update_context+ method simply ignored the name argument in ArrayDef
|
48
|
+
# because it does not make any sens in this context.
|
49
|
+
class FakeNameProxy < BasicObject
|
50
|
+
|
51
|
+
def initialize(target)
|
52
|
+
@target = target
|
53
|
+
end
|
54
|
+
|
55
|
+
# Return the DSL context object where the evaluation takes place.
|
56
|
+
attr_reader :target
|
57
|
+
|
58
|
+
def method_missing(symbol, *args, &block)
|
59
|
+
if respond_to_missing?(symbol, false)
|
60
|
+
# If the target's default behavior for its methods is to not accept a name as
|
61
|
+
# first argument (this is the case for ArrayDef), we introspect the method
|
62
|
+
# to decide whether we have to send a nil name as first argument.
|
63
|
+
if should_fake_name?
|
64
|
+
method = @target.method(symbol)
|
65
|
+
else
|
66
|
+
method = nil
|
67
|
+
end
|
68
|
+
# If we have a method and this method is either dynamic or expects a name as its first parameter.
|
69
|
+
if method && (dynamic_method?(symbol) || has_name_param?(method))
|
70
|
+
args.insert(0, nil)
|
71
|
+
begin
|
72
|
+
method.call(*args, &block)
|
73
|
+
rescue ::ArgumentError => e
|
74
|
+
# Decrements argument number mentioned in the message by one.
|
75
|
+
message = e.message.sub(/ \((\d+) for (\d+)\)$/) do |match|
|
76
|
+
# FIXME(Nicolas Despres): Not sure if this class is still
|
77
|
+
# re-entrant since we use $1 and $2. I could not find a way to access
|
78
|
+
# to the data matched by sub.
|
79
|
+
" (#{$1.to_i - 1} for #{$2.to_i - 1})"
|
80
|
+
end
|
81
|
+
::Kernel.raise(::ArgumentError, message)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
@target.public_send(symbol, *args, &block)
|
85
|
+
end
|
86
|
+
else
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def respond_to_missing?(symbol, include_all)
|
92
|
+
# We ignore include_all since we are only interested in non-private methods.
|
93
|
+
@target.respond_to?(symbol)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Evaluate the given +block+ in the context of this class and pass it this
|
97
|
+
# instance as argument and returns the value returned by the block.
|
98
|
+
def eval(&block)
|
99
|
+
block.call(self)
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def dynamic_method?(symbol)
|
105
|
+
!@target.methods.include?(symbol)
|
106
|
+
end
|
107
|
+
|
108
|
+
def has_name_param?(method)
|
109
|
+
!method.parameters.empty? && method.parameters.first.last == :name
|
110
|
+
end
|
111
|
+
|
112
|
+
def should_fake_name?
|
113
|
+
@target.respond_to?(:accept_name?) && !@target.accept_name?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Respect
|
2
|
+
class FloatSchema < NumericSchema
|
3
|
+
|
4
|
+
def validate_type(object)
|
5
|
+
case object
|
6
|
+
when String
|
7
|
+
if object =~ /^[-+]?\d+(\.\d+)?$/
|
8
|
+
object.to_f
|
9
|
+
else
|
10
|
+
raise ValidationError,
|
11
|
+
"malformed float value: `#{object}'"
|
12
|
+
end
|
13
|
+
when Float
|
14
|
+
object
|
15
|
+
when NilClass
|
16
|
+
if allow_nil?
|
17
|
+
nil
|
18
|
+
else
|
19
|
+
raise ValidationError, "object is nil but this #{self.class} does not allow nil"
|
20
|
+
end
|
21
|
+
else
|
22
|
+
raise ValidationError, "object is not a float but a '#{object.class}'"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end # class FloatSchema
|
27
|
+
end # module Respect
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Respect
|
5
|
+
class FormatValidator < Validator
|
6
|
+
|
7
|
+
PHONE_NUMBER_REGEXP = /^((\+|00)\d{1,2})?\d+$/
|
8
|
+
|
9
|
+
# FIXME(Nicolas Despres): RFC 1034 mentions that a valid domain can be " "
|
10
|
+
# in section 3.5. (see http://www.rfc-editor.org/rfc/rfc1034.txt) but we don't
|
11
|
+
# since I don't understand when it is useful.
|
12
|
+
HOSTNAME_REGEXP = /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*$/i
|
13
|
+
|
14
|
+
def initialize(format)
|
15
|
+
@format = format
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate(value)
|
19
|
+
send("validate_#@format", value)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Validate the given string _value_ describes a well-formed email
|
23
|
+
# address following this specification
|
24
|
+
# http://www.w3.org/TR/2012/CR-html5-20121217/forms.html#valid-e-mail-address
|
25
|
+
def validate_email(value)
|
26
|
+
unless value =~ /^[a-zA-Z0-9.!#$\%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
|
27
|
+
raise ValidationError, "invalid email address format '#{value}'"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Validate URI string format following RFC 2396
|
32
|
+
# (see http://tools.ietf.org/html/rfc2396)
|
33
|
+
def validate_uri(value)
|
34
|
+
URI.parse(value)
|
35
|
+
rescue URI::InvalidURIError => e
|
36
|
+
raise ValidationError, "invalid URI: #{e.message}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Validate the given string _value_ describes a regular expression
|
40
|
+
# following the Ruby regular expression syntax.
|
41
|
+
def validate_regexp(value)
|
42
|
+
Regexp.new(value)
|
43
|
+
rescue RegexpError => e
|
44
|
+
raise ValidationError, "invalid regexp: #{e.message}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Validate date and time string format following RFC 3399
|
48
|
+
# (see https://tools.ietf.org/html/rfc3339)
|
49
|
+
def validate_datetime(value)
|
50
|
+
DateTime.rfc3339(value)
|
51
|
+
rescue ArgumentError => e
|
52
|
+
raise ValidationError, e.message
|
53
|
+
end
|
54
|
+
|
55
|
+
# Validate IPV4 using the standard "ipaddr" ruby module.
|
56
|
+
def validate_ipv4_addr(value)
|
57
|
+
ipaddr = IPAddr.new(value)
|
58
|
+
unless ipaddr.ipv4?
|
59
|
+
raise ValidationError, "IP address '#{value}' is not IPv4"
|
60
|
+
end
|
61
|
+
ipaddr
|
62
|
+
rescue ArgumentError => e
|
63
|
+
raise ValidationError, "invalid IPv4 address '#{value}' - #{e.message}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Validate phone number following E.123
|
67
|
+
# (see http://en.wikipedia.org/wiki/E.123)
|
68
|
+
def validate_phone_number(value)
|
69
|
+
unless value =~ PHONE_NUMBER_REGEXP
|
70
|
+
raise ValidationError, "invalid phone number '#{value}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Validate that the given string _value_ describes a well-formed
|
75
|
+
# IPV6 network address using the standard "ipaddr" ruby module.
|
76
|
+
def validate_ipv6_addr(value)
|
77
|
+
ipaddr = IPAddr.new(value)
|
78
|
+
unless ipaddr.ipv6?
|
79
|
+
raise ValidationError, "IP address '#{value}' is not IPv6"
|
80
|
+
end
|
81
|
+
ipaddr
|
82
|
+
rescue ArgumentError => e
|
83
|
+
raise ValidationError, "invalid IPv6 address '#{value}' - #{e.message}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Validate that the given string _value_ describes a well-formed
|
87
|
+
# IP (IPv6 or IPv4) network address using the standard "ipaddr" ruby module.
|
88
|
+
def validate_ip_addr(value)
|
89
|
+
IPAddr.new(value)
|
90
|
+
rescue ArgumentError => e
|
91
|
+
raise ValidationError, "invalid IP address '#{value}' - #{e.message}"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Validate that the given string _value_ describes a well-formed
|
95
|
+
# host name as specified by RFC 1034.
|
96
|
+
# (see http://www.rfc-editor.org/rfc/rfc1034.txt)
|
97
|
+
def validate_hostname(value)
|
98
|
+
match_data = HOSTNAME_REGEXP.match(value)
|
99
|
+
if match_data
|
100
|
+
value.split('.').each_with_index do |label, i|
|
101
|
+
unless label.length <= 63
|
102
|
+
raise ValidationError,
|
103
|
+
"hostname's #{i.ordinalize} label '#{label}' is not less than 63 characters in '#{value}'"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
raise ValidationError, "invalid hostname '#{value}'"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def to_h_org3
|
114
|
+
{ 'format' => convert_to_org3_format(@format) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def convert_to_org3_format(format)
|
118
|
+
format_type_map = {
|
119
|
+
regexp: 'regex',
|
120
|
+
datetime: 'date-time',
|
121
|
+
ipv4_addr: 'ip-address',
|
122
|
+
phone_number: 'phone',
|
123
|
+
ipv6_addr: 'ipv6',
|
124
|
+
ip_addr: nil,
|
125
|
+
hostname: 'host-name',
|
126
|
+
}.freeze
|
127
|
+
if format_type_map.has_key?(format)
|
128
|
+
translation_value = format_type_map[format]
|
129
|
+
translation_value unless translation_value.nil?
|
130
|
+
else
|
131
|
+
format.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end # class FormatValidator
|
136
|
+
end # module Respect
|