schemacop 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +59 -1
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +389 -199
  6. data/Rakefile +2 -0
  7. data/VERSION +1 -1
  8. data/doc/Schemacop.html +41 -130
  9. data/doc/Schemacop/ArrayValidator.html +329 -0
  10. data/doc/Schemacop/BooleanValidator.html +145 -0
  11. data/doc/Schemacop/Collector.html +535 -0
  12. data/doc/Schemacop/Exceptions.html +39 -39
  13. data/doc/Schemacop/Exceptions/InvalidSchemaError.html +124 -0
  14. data/doc/Schemacop/Exceptions/ValidationError.html +124 -0
  15. data/doc/Schemacop/FieldNode.html +409 -0
  16. data/doc/Schemacop/FloatValidator.html +158 -0
  17. data/doc/Schemacop/HashValidator.html +263 -0
  18. data/doc/Schemacop/IntegerValidator.html +158 -0
  19. data/doc/Schemacop/NilValidator.html +145 -0
  20. data/doc/Schemacop/Node.html +1426 -0
  21. data/doc/Schemacop/NodeResolver.html +242 -0
  22. data/doc/Schemacop/NodeSupportingField.html +590 -0
  23. data/doc/Schemacop/NodeSupportingType.html +614 -0
  24. data/doc/Schemacop/NodeWithBlock.html +289 -0
  25. data/doc/Schemacop/NumberValidator.html +232 -0
  26. data/doc/Schemacop/ObjectValidator.html +288 -0
  27. data/doc/Schemacop/RootNode.html +171 -0
  28. data/doc/Schemacop/Schema.html +697 -0
  29. data/doc/Schemacop/StringValidator.html +295 -0
  30. data/doc/ScopedEnv.html +351 -0
  31. data/doc/_index.html +190 -47
  32. data/doc/class_list.html +24 -31
  33. data/doc/css/full_list.css +32 -31
  34. data/doc/css/style.css +244 -91
  35. data/doc/file.README.html +428 -232
  36. data/doc/file_list.html +26 -30
  37. data/doc/frames.html +7 -16
  38. data/doc/index.html +428 -232
  39. data/doc/inheritance.graphml +524 -0
  40. data/doc/inheritance.pdf +825 -0
  41. data/doc/js/app.js +106 -77
  42. data/doc/js/full_list.js +170 -135
  43. data/doc/method_list.html +494 -38
  44. data/doc/top-level-namespace.html +36 -36
  45. data/lib/schemacop.rb +22 -7
  46. data/lib/schemacop/collector.rb +34 -0
  47. data/lib/schemacop/exceptions.rb +2 -8
  48. data/lib/schemacop/field_node.rb +26 -0
  49. data/lib/schemacop/node.rb +127 -0
  50. data/lib/schemacop/node_resolver.rb +14 -0
  51. data/lib/schemacop/node_supporting_field.rb +62 -0
  52. data/lib/schemacop/node_supporting_type.rb +112 -0
  53. data/lib/schemacop/node_with_block.rb +16 -0
  54. data/lib/schemacop/root_node.rb +4 -0
  55. data/lib/schemacop/schema.rb +61 -0
  56. data/lib/schemacop/scoped_env.rb +18 -0
  57. data/lib/schemacop/validator/array_validator.rb +30 -0
  58. data/lib/schemacop/validator/boolean_validator.rb +5 -0
  59. data/lib/schemacop/validator/float_validator.rb +5 -0
  60. data/lib/schemacop/validator/hash_validator.rb +18 -0
  61. data/lib/schemacop/validator/integer_validator.rb +5 -0
  62. data/lib/schemacop/validator/nil_validator.rb +5 -0
  63. data/lib/schemacop/validator/number_validator.rb +19 -0
  64. data/lib/schemacop/validator/object_validator.rb +21 -0
  65. data/lib/schemacop/validator/string_validator.rb +37 -0
  66. data/schemacop.gemspec +7 -5
  67. data/test/custom_check_test.rb +86 -0
  68. data/test/custom_if_test.rb +95 -0
  69. data/test/nil_dis_allow_test.rb +41 -0
  70. data/test/short_forms_test.rb +316 -0
  71. data/test/test_helper.rb +6 -0
  72. data/test/types_test.rb +83 -0
  73. data/test/validator_array_test.rb +97 -0
  74. data/test/validator_boolean_test.rb +15 -0
  75. data/test/validator_float_test.rb +57 -0
  76. data/test/validator_hash_test.rb +71 -0
  77. data/test/validator_integer_test.rb +46 -0
  78. data/test/validator_nil_test.rb +13 -0
  79. data/test/validator_number_test.rb +60 -0
  80. data/test/validator_object_test.rb +87 -0
  81. data/test/validator_string_test.rb +76 -0
  82. metadata +78 -14
  83. data/doc/Schemacop/Exceptions/Base.html +0 -127
  84. data/doc/Schemacop/Exceptions/InvalidSchema.html +0 -141
  85. data/doc/Schemacop/Exceptions/Validation.html +0 -142
  86. data/doc/Schemacop/MethodValidation.html +0 -120
  87. data/doc/Schemacop/MethodValidation/ClassMethods.html +0 -196
  88. data/doc/Schemacop/Validator.html +0 -254
  89. data/lib/schemacop/validator.rb +0 -145
  90. data/test/schemacop_validator_test.rb +0 -257
@@ -1,12 +1,12 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1
+ <!DOCTYPE html>
2
+ <html>
4
3
  <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Documentation by YARD 0.8.7.6
9
+ &mdash; Documentation by YARD 0.9.9
10
10
 
11
11
  </title>
12
12
 
@@ -15,9 +15,8 @@
15
15
  <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
16
 
17
17
  <script type="text/javascript" charset="utf-8">
18
- hasFrames = window.top.frames.main ? true : false;
18
+ pathId = "";
19
19
  relpath = '';
20
- framesUrl = "frames.html#!top-level-namespace.html";
21
20
  </script>
22
21
 
23
22
 
@@ -28,58 +27,56 @@
28
27
 
29
28
  </head>
30
29
  <body>
31
- <div id="header">
32
- <div id="menu">
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
33
38
 
34
39
  <a href="_index.html">Index</a> &raquo;
35
40
 
36
41
 
37
42
  <span class="title">Top Level Namespace</span>
38
43
 
39
-
40
- <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
44
  </div>
42
45
 
43
- <div id="search">
46
+ <div id="search">
44
47
 
45
48
  <a class="full_list_link" id="class_list_link"
46
49
  href="class_list.html">
47
- Class List
48
- </a>
49
-
50
- <a class="full_list_link" id="method_list_link"
51
- href="method_list.html">
52
- Method List
53
- </a>
54
-
55
- <a class="full_list_link" id="file_list_link"
56
- href="file_list.html">
57
- File List
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
58
56
  </a>
59
57
 
60
58
  </div>
61
- <div class="clear"></div>
62
- </div>
63
-
64
- <iframe id="search_frame"></iframe>
59
+ <div class="clear"></div>
60
+ </div>
65
61
 
66
- <div id="content"><h1>Top Level Namespace
62
+ <div id="content"><h1>Top Level Namespace
67
63
 
68
64
 
69
65
 
70
66
  </h1>
67
+ <div class="box_info">
68
+
71
69
 
72
- <dl class="box">
73
70
 
74
71
 
75
-
76
72
 
77
-
78
73
 
79
74
 
75
+
80
76
 
81
- </dl>
82
- <div class="clear"></div>
77
+
78
+
79
+ </div>
83
80
 
84
81
  <h2>Defined Under Namespace</h2>
85
82
  <p class="children">
@@ -89,6 +86,8 @@
89
86
 
90
87
 
91
88
 
89
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="ScopedEnv.html" title="ScopedEnv (class)">ScopedEnv</a></span>
90
+
92
91
 
93
92
  </p>
94
93
 
@@ -102,11 +101,12 @@
102
101
 
103
102
  </div>
104
103
 
105
- <div id="footer">
106
- Generated on Thu Oct 6 19:45:02 2016 by
104
+ <div id="footer">
105
+ Generated on Mon May 15 17:46:05 2017 by
107
106
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
- 0.8.7.6 (ruby-2.3.1).
107
+ 0.9.9 (ruby-2.3.1).
109
108
  </div>
110
109
 
110
+ </div>
111
111
  </body>
112
112
  </html>
data/lib/schemacop.rb CHANGED
@@ -1,11 +1,26 @@
1
1
  module Schemacop
2
- # {include:Schemacop::Validator.validate!}
3
- # @see Schemacop::Validator.validate!
4
- def self.validate!(schema, data)
5
- Validator.validate!(schema, data)
6
- end
7
2
  end
8
3
 
9
- require 'active_support/all'
4
+ require 'set'
5
+ require 'active_support/core_ext/class/attribute'
6
+
7
+ require 'schemacop/scoped_env'
10
8
  require 'schemacop/exceptions'
11
- require 'schemacop/validator'
9
+ require 'schemacop/schema'
10
+ require 'schemacop/collector'
11
+ require 'schemacop/node_resolver'
12
+ require 'schemacop/node'
13
+ require 'schemacop/node_with_block'
14
+ require 'schemacop/node_supporting_type'
15
+ require 'schemacop/field_node'
16
+ require 'schemacop/root_node'
17
+ require 'schemacop/node_supporting_field'
18
+ require 'schemacop/validator/array_validator'
19
+ require 'schemacop/validator/boolean_validator'
20
+ require 'schemacop/validator/hash_validator'
21
+ require 'schemacop/validator/number_validator'
22
+ require 'schemacop/validator/integer_validator'
23
+ require 'schemacop/validator/float_validator'
24
+ require 'schemacop/validator/string_validator'
25
+ require 'schemacop/validator/nil_validator'
26
+ require 'schemacop/validator/object_validator' # Matches any object, must be last validator
@@ -0,0 +1,34 @@
1
+ module Schemacop
2
+ class Collector
3
+ attr_reader :current_path
4
+
5
+ def initialize
6
+ @exceptions = []
7
+ @current_path = []
8
+ end
9
+
10
+ def valid?
11
+ @exceptions.empty?
12
+ end
13
+
14
+ def path(segment)
15
+ @current_path << segment
16
+ yield
17
+ ensure
18
+ @current_path.pop
19
+ end
20
+
21
+ def exception_message
22
+ return "Schemacop validation failed:\n" + @exceptions.map do |e|
23
+ "- #{e[:path].join('')}: #{e[:message]}"
24
+ end.join("\n")
25
+ end
26
+
27
+ def error(error_msg)
28
+ @exceptions << {
29
+ path: current_path.dup,
30
+ message: error_msg
31
+ }
32
+ end
33
+ end
34
+ end
@@ -1,10 +1,4 @@
1
1
  module Schemacop::Exceptions
2
- class Base < StandardError; end
3
-
4
- # This exception is thrown when the given schema definition format is invalid.
5
- class InvalidSchema < Base; end
6
-
7
- # This exception is thrown when the given data does not comply with the given
8
- # schema definition.
9
- class Validation < Base; end
2
+ class ValidationError < RuntimeError; end
3
+ class InvalidSchemaError < RuntimeError; end
10
4
  end
@@ -0,0 +1,26 @@
1
+ module Schemacop
2
+ class FieldNode < NodeSupportingType
3
+ attr_reader :name
4
+
5
+ def initialize(name, required, options = {}, &block)
6
+ if options.any?
7
+ fail Exceptions::InvalidSchemaError, 'Node does not support options.'
8
+ end
9
+
10
+ super({}, &block)
11
+
12
+ @name = name
13
+ @required = required
14
+ end
15
+
16
+ def validate(data, collector)
17
+ unless data.key?(name)
18
+ collector.error "Missing key #{name.inspect}." if @required
19
+ return
20
+ end
21
+ collector.path "/#{name}" do
22
+ super(data[name], collector)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,127 @@
1
+ module Schemacop
2
+ class Node
3
+ attr_reader :options
4
+
5
+ class_attribute :allowed_options
6
+ self.allowed_options = {}.freeze
7
+
8
+ class_attribute :symbols
9
+ self.symbols = [].freeze
10
+
11
+ class_attribute :klasses
12
+ self.klasses = [].freeze
13
+
14
+ def self.option(key, default: nil)
15
+ self.allowed_options = allowed_options.merge(key => default)
16
+ end
17
+
18
+ option :if
19
+ option :check
20
+
21
+ def type_label
22
+ str = (symbols.first || 'unknown').to_s
23
+ str += '*' if option?(:if)
24
+ return str
25
+ end
26
+
27
+ def self.symbol(symbol)
28
+ self.symbols += [symbol]
29
+ end
30
+
31
+ def self.clear_symbols
32
+ self.symbols = [].freeze
33
+ end
34
+
35
+ def self.klass(klass)
36
+ self.klasses += [klass]
37
+ end
38
+
39
+ def self.clear_klasses
40
+ self.klasses = [].freeze
41
+ end
42
+
43
+ def self.register(symbols: [], klasses: [], clear: true)
44
+ NodeResolver.register(self)
45
+ symbols = [*symbols]
46
+ klasses = [*klasses]
47
+ if clear
48
+ clear_symbols
49
+ clear_klasses
50
+ end
51
+ symbols.each { |s| symbol s }
52
+ klasses.each { |k| klass k }
53
+ end
54
+
55
+ def self.type_matches?(type)
56
+ symbol_matches?(type) || class_matches?(type)
57
+ end
58
+
59
+ def self.symbol_matches?(type)
60
+ return false unless type.is_a?(Symbol)
61
+ symbols.include?(type)
62
+ end
63
+
64
+ def self.class_matches?(type)
65
+ return false unless type.is_a?(Class)
66
+ klasses.each do |klass|
67
+ return true if type <= klass
68
+ end
69
+ return false
70
+ end
71
+
72
+ def self.build(options, &block)
73
+ new(options, &block)
74
+ end
75
+
76
+ def initialize(options = {})
77
+ # Check and save given options
78
+ @options = self.class.allowed_options.merge(options)
79
+ if (obsolete_opts = @options.keys - self.class.allowed_options.keys).any?
80
+ fail Exceptions::InvalidSchemaError,
81
+ "Unrecognized option(s) #{obsolete_opts.inspect} for #{self.class.inspect}, allowed options: #{self.class.allowed_options.keys.inspect}."
82
+ end
83
+ end
84
+
85
+ def option(key)
86
+ options[key]
87
+ end
88
+
89
+ def option?(key)
90
+ # rubocop:disable Style/DoubleNegation
91
+ !!options[key]
92
+ # rubocop:enable Style/DoubleNegation
93
+ end
94
+
95
+ def exec_block
96
+ fail Exceptions::InvalidSchemaError, 'Node does not support block.' if block_given?
97
+ end
98
+
99
+ def resolve_type_klass(type)
100
+ klass = NodeResolver.resolve(type)
101
+ unless klass
102
+ fail Exceptions::InvalidSchemaError, "No validation class found for type #{type.inspect}."
103
+ end
104
+ return klass
105
+ end
106
+
107
+ def validate(data, collector)
108
+ validate_custom_check(data, collector)
109
+ end
110
+
111
+ def type_matches?(data)
112
+ self.class.type_matches?(data.class) && type_filter_matches?(data)
113
+ end
114
+
115
+ def type_filter_matches?(data)
116
+ !option?(:if) || option(:if).call(data)
117
+ end
118
+
119
+ protected
120
+
121
+ def validate_custom_check(data, collector)
122
+ if option?(:check) && !option(:check).call(data)
123
+ collector.error 'Custom :check failed.'
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,14 @@
1
+ module Schemacop
2
+ class NodeResolver
3
+ class_attribute :node_classes
4
+ self.node_classes = [].freeze
5
+
6
+ def self.register(node_class)
7
+ self.node_classes += [node_class]
8
+ end
9
+
10
+ def self.resolve(type)
11
+ node_classes.find { |c| c.type_matches?(type) }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,62 @@
1
+ module Schemacop
2
+ class NodeSupportingField < NodeWithBlock
3
+ block_method :req?
4
+ block_method :req!
5
+ block_method :req
6
+ block_method :opt?
7
+ block_method :opt!
8
+ block_method :opt
9
+
10
+ attr_reader :fields
11
+
12
+ def initialize(options = {}, &block)
13
+ @fields = {}
14
+ super
15
+ exec_block(&block)
16
+ end
17
+
18
+ def req?(*args, &block)
19
+ field(*args, required: true, allow_nil: true, &block)
20
+ end
21
+
22
+ def req!(*args, &block)
23
+ field(*args, required: true, allow_nil: false, &block)
24
+ end
25
+
26
+ alias req req!
27
+
28
+ def opt?(*args, &block)
29
+ field(*args, required: false, allow_nil: true, &block)
30
+ end
31
+
32
+ def opt!(*args, &block)
33
+ field(*args, required: false, allow_nil: false, &block)
34
+ end
35
+
36
+ alias opt opt?
37
+
38
+ protected
39
+
40
+ def field(*args, required:, allow_nil:, &block)
41
+ # name = args.shift
42
+ # options = args.last.is_a?(Hash) ? args.pop : {}
43
+ name = args.shift
44
+
45
+ # rubocop: disable Style/IfInsideElse
46
+ if @fields[name]
47
+ @fields[name].type(*args, &block)
48
+ else
49
+ if args.any?
50
+ @fields[name] = FieldNode.new(name, required) do
51
+ type(*args, &block)
52
+ end
53
+ else
54
+ @fields[name] = FieldNode.new(name, required, &block)
55
+ end
56
+ end
57
+ # rubocop: enable Style/IfInsideElse
58
+
59
+ @fields[name].type(:nil) if allow_nil
60
+ end
61
+ end
62
+ end