oval 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
+ 2014-02-08 Pawel Tomulik <ptomulik@meil.pw.edu.pl>
2
+ * release 0.0.6
3
+ * documented a way for validating arbitrary arguments
1
4
  2014-02-03 Pawel Tomulik <ptomulik@meil.pw.edu.pl>
5
+ * added more navigation links to README.md
6
+ * added specs for Oval::Base.it_should
2
7
  * release 0.0.5
3
8
  * refactored ensure_match -> validate
4
9
  * added Oval::Match declarator
data/Modulefile CHANGED
@@ -1,5 +1,5 @@
1
1
  name 'ptomulik-oval'
2
- version '0.0.5'
2
+ version '0.0.6'
3
3
  source 'git://github.com/ptomulik/rubygems-oval.git'
4
4
  author 'ptomulik'
5
5
  license 'Apache License, Version 2.0'
data/README.md CHANGED
@@ -18,17 +18,18 @@
18
18
 
19
19
  ##<a id="overview"></a>Overview
20
20
 
21
- Validate option hashes when passed to methods.
21
+ Validate arguments and option hashes when passed to methods.
22
22
 
23
23
  [[Table of Contents](#table-of-contents)]
24
24
 
25
25
  ##<a id="module-description"></a>Module Description
26
26
 
27
- Using hashes to pass options to methods is a very common ruby practice. With
28
- **Oval** method authors may restrict callers to pass only declared options that
29
- meet requirements described in a hash declaration.
27
+ This module implements simple to use data validators. It was initially thought
28
+ to validate option hashes (so the name *Oval* stands for Options' Validator),
29
+ but it appeared early that it's suitable to validate arbitrary parameters
30
+ (variables).
30
31
 
31
- The shape of acceptable hashes is described by a simple grammar. The validation
32
+ The shape of acceptable data is described by a simple grammar. The validation
32
33
  is then carried out by a recursive-descent parser that matches the actual
33
34
  values provided by caller against [declarators](#declarators) that comprise the
34
35
  hash declaration.
@@ -38,28 +39,27 @@ declarators are created by methods of `Oval` module which have names starting
38
39
  with `ov_` prefix. All other values (such as `:symbol`, `'string'`, `nil`, or
39
40
  `Class`) are terminals. Terminals use `==` operator to match the values
40
41
  provided by caller. Non-terminal use its own logic introducing more elaborate
41
- matching criteria (see for example [ov_collection](#ov_collection)).
42
+ matching criteria (see for example [ov\_collection](#ov_collection)).
42
43
 
43
- **Oval** raises **Oval::DeclError** if the declaration is not well-formed, that
44
- is if the description of options shape is erroneous. This is raised from the
45
- point of declaration. Other, more common exception is the **Oval::ValueError**
46
- which is raised each time the validation fails. This one is raised from within
47
- a method which takes the options as an argument.
44
+ **Oval** raises **Oval::DeclError** if the declaration is not well-formed. This
45
+ is raised from the point of declaration. Other, more common exception is the
46
+ **Oval::ValueError** which is raised each time the validation fails. This one
47
+ is raised from within a method which validates its arguments.
48
48
 
49
49
  [[Table of Contents](#table-of-contents)]
50
50
 
51
51
  ##<a id="usage"></a>Usage
52
52
 
53
53
  The usage is basically a two-step procedure. The first step is to declare
54
- options shape. This would create a validator object. The second step is to
55
- validate options within a method using the previously constructed validator.
56
- For simple hashes the entire construction may fit to a single line. Let's start
57
- with such a simple example.
54
+ data to be validated. This would create a validator object. The second step is
55
+ to validate data using the previously constructed validator. For simple cases
56
+ the entire construction may fit to a single line. Let's start with such a
57
+ simple example.
58
58
 
59
59
  ###<a id="example-1-declaring-simple-options"></a>Example 1: Declaring Simple Options
60
60
 
61
61
  The method `foo` in the following code accepts only `{}` and `{:foo => value}`
62
- as `ops`, where `value` is arbitrary:
62
+ as `ops` hash, and the `value` may be anything:
63
63
 
64
64
  ```ruby
65
65
  # Options validator
@@ -67,7 +67,7 @@ require 'oval'
67
67
  class C
68
68
  extend Oval
69
69
  def self.foo(ops = {})
70
- ov_options[ :foo => ov_anything ].validate(ops, 'ops')
70
+ Oval.validate(ops, ov_options[ :foo => ov_anything ], 'ops')
71
71
  end
72
72
  end
73
73
  ```
@@ -80,12 +80,13 @@ C.foo :foo => 10 # should pass
80
80
  C.foo :foo => 10, :bar => 20 # Oval::ValueError "Invalid option :bar for ops. Allowed options are :foo"
81
81
  ```
82
82
 
83
- Options are declared with [ov_xxx declarators](#declarators). The
84
- [ov_options](#ov_options) method should always be at the top level. Then all
85
- the allowed options should be listed inside of `[]` square brackets. Keys may
86
- be any values convertible to strings (i.e. a key given in declaration must
87
- `respond_to? :to_s`). Values are declared recursively using [ov_xxx
88
- declarators](#declarators) or terminal declarators (any other ruby values).
83
+ Options are declared with [ov\_xxx declarators](#declarators). The
84
+ [ov\_options](#ov_options), for example, declares a hash of options. In
85
+ [ov\_options](#ov_options) all the allowed options should be listed inside of
86
+ `[]` square brackets. Keys may be any values convertible to strings (i.e. a key
87
+ given in declaration must `respond_to? :to_s`). Values are declared recursively
88
+ using [ov_xxx declarators](#declarators) or terminal declarators (any other
89
+ ruby values).
89
90
 
90
91
  In [Example 1](#example-1-declaring-simple-options) we have declared options
91
92
  inside of a method for simplicity. This isn't an optimal technique. Usually
@@ -112,7 +113,7 @@ class C
112
113
  end
113
114
  # use ov to validate ops
114
115
  def self.foo(ops = {})
115
- ov.validate(ops, 'ops')
116
+ Oval.validate(ops, ov, 'ops')
116
117
  end
117
118
  end
118
119
  ```
@@ -123,36 +124,30 @@ end
123
124
 
124
125
  ###<a id="declarators"></a>Declarators
125
126
 
126
- A declaration of options consists entirely of what we call here
127
- **declarators**. The [ov_options](#ov_options) should be used as a root of
128
- every declaration (starting symbol in grammar terms). It accepts a Hash of the
129
- form
127
+ A declaration of data being validated consists entirely of what we call
128
+ **declarators**. The grammar for defining acceptable data uses non-terminal and
129
+ terminal declarators. Non-terminal declarators are most of the
130
+ [ov\_xxx](#declarators) methods of **Oval** module, for example
131
+ [ov\_options](#ov_options). General syntax for non-terminal declarator is
132
+ `ov_xxx[ args ]`, where `args` are declarator-specific arguments.
130
133
 
131
- ```
132
- {optname1 => optdecl1, optname2 => optdecl2, ... }
133
- ```
134
-
135
- as an argument. The **optname#** is an option name, and **optdecl#** is a
136
- declarator restricting the option's value. Each option name (key) must be
137
- convertible to a `String`. Option value declarators are non-terminal
138
- declarators (defined later in this section) or terminals (any other ruby
139
- values). The simple declaration
140
-
141
- ```ruby
142
- ov_options[ :foo => :bar ]
143
- ```
134
+ Terminal declarators include all the other ruby values, for example `nil`. They
135
+ are matched exactly against data being validated, so if the data doesn't equal
136
+ the given value an exception is raised.
144
137
 
145
- uses only terminals inside of **ov_options** and literary permits only the
146
- `{:foo => :bar}` or the empty hash `{}` as options (and nothing else). This is
147
- how terminal declarators (`:foo` and `:bar` in this example) work. More freedom
148
- may be introduced with non-terminal declarators, for example:
138
+ In what follows, we'll document all the core declarators implemented in
139
+ **Oval**.
149
140
 
150
- ```ruby
151
- ov_options[ :foo => ov_anything ]
152
- ```
141
+ ###<a id="index-of-declarators"></a>Index of Declarators
153
142
 
154
- defines an option `:foo` which accepts any value. In what follows, we'll
155
- document all the core non-terminal declarators implemented in **Oval**.
143
+ - [ov\_anything](#ov_anything)
144
+ - [ov\_collection](#ov_collection)
145
+ - [ov\_instance\_of](#ov_instance_of)
146
+ - [ov\_kind\_of](#ov_kind_of)
147
+ - [ov\_match](#ov_match)
148
+ - [ov\_one\_of](#ov_one_of)
149
+ - [ov\_options](#ov_options)
150
+ - [ov\_subclass_of](#ov_subclass_of)
156
151
 
157
152
  ####<a id="ov\_anything"></a>ov\_anything
158
153
 
@@ -174,10 +169,12 @@ document all the core non-terminal declarators implemented in **Oval**.
174
169
  ```ruby
175
170
  ov = ov_options[ :bar => ov_anything ]
176
171
  def foo(ops = {})
177
- ov.validate(ops, 'ops')
172
+ Oval.validate(ops, ov, 'ops')
178
173
  end
179
174
  ```
180
175
 
176
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
177
+
181
178
 
182
179
  ####<a id="ov\_collection"></a>ov\_collection
183
180
 
@@ -206,10 +203,12 @@ document all the core non-terminal declarators implemented in **Oval**.
206
203
  :geez => ov_collection [ Array, instance_of[String] ]
207
204
  ]
208
205
  def foo(ops = {})
209
- ov.validate(ops, 'ops')
206
+ Oval.validate(ops, ov, 'ops')
210
207
  end
211
208
  ```
212
209
 
210
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
211
+
213
212
  ####<a id="ov\_instance\_of"></a>ov\_instance\_of
214
213
 
215
214
  - Declaration
@@ -225,10 +224,12 @@ document all the core non-terminal declarators implemented in **Oval**.
225
224
  ```ruby
226
225
  ov = ov_options[ :bar => ov_instance_of[String] ]
227
226
  def foo(ops = {})
228
- ov.validate(ops,'ops')
227
+ Oval.validate(ops, ov, 'ops')
229
228
  end
230
229
  ```
231
230
 
231
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
232
+
232
233
  ####<a id="ov\_kind\_of"></a>ov\_kind\_of
233
234
 
234
235
  - Declaration
@@ -244,10 +245,12 @@ document all the core non-terminal declarators implemented in **Oval**.
244
245
  ```ruby
245
246
  ov = ov_options[ :bar => ov_kind_of[Numeric] ]
246
247
  def foo(ops = {})
247
- ov.validate(ops,'ops')
248
+ Oval.validate(ops, ov, 'ops')
248
249
  end
249
250
  ```
250
251
 
252
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
253
+
251
254
  ####<a id="ov\_match"></a>ov\_match
252
255
 
253
256
  - Declaration
@@ -264,10 +267,12 @@ document all the core non-terminal declarators implemented in **Oval**.
264
267
  # Only valid identifiers are allowed as :bar option
265
268
  ov = ov_options[ :bar => ov_match[/^[a-z_]\w+$/] ]
266
269
  def foo(ops = {})
267
- ov.validate(ops,'ops')
270
+ Oval.validate(ops, ov, 'ops')
268
271
  end
269
272
  ```
270
273
 
274
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
275
+
271
276
  ####<a id="ov\_one\_of"></a>ov\_one\_of
272
277
 
273
278
  - Declaration
@@ -284,10 +289,12 @@ document all the core non-terminal declarators implemented in **Oval**.
284
289
  :bar => ov_one_of[ ov_instance_of[String], ov_kind_of[Numeric], nil ]
285
290
  ]
286
291
  def foo(ops = {})
287
- ov.validate(ops,'ops')
292
+ Oval.validate(ops, ov, 'ops')
288
293
  end
289
294
  ```
290
295
 
296
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
297
+
291
298
  ####<a id="ov\_options"></a>ov\_options
292
299
 
293
300
  - Declaration
@@ -308,10 +315,12 @@ document all the core non-terminal declarators implemented in **Oval**.
308
315
  # ...
309
316
  ]
310
317
  def foo(ops = {})
311
- ov.validate(ops,'ops')
318
+ Oval.validate(ops, ov, 'ops')
312
319
  end
313
320
  ```
314
321
 
322
+ [[Table of Contents](#table-of-contents)|[Index of Declarators](#index-of-declarators)]
323
+
315
324
  ####<a id="ov\_subclass\_of"></a>ov\_subclass\_of
316
325
 
317
326
  - Declaration
@@ -327,7 +336,7 @@ document all the core non-terminal declarators implemented in **Oval**.
327
336
  ```ruby
328
337
  ov = ov_options[ :bar => ov_subclass_of[Numeric] ]
329
338
  def foo(ops = {})
330
- ov.validate(ops,'ops')
339
+ Oval.validate(ops, ov, 'ops')
331
340
  end
332
341
  ```
333
342
 
data/oval.gemspec CHANGED
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.name = 'oval'
6
- gem.version = '0.0.5'
6
+ gem.version = '0.0.6'
7
7
  gem.authors = ["Pawel Tomulik"]
8
8
  gem.email = ["ptomulik@meil.pw.edu.pl"]
9
9
  gem.description = %q{Validate options when passed to methods}
@@ -15,7 +15,7 @@ describe Oval::Base do
15
15
  end
16
16
 
17
17
  context "an instance" do
18
- let(:subject) { described_class[:shape0] }
18
+ let(:subject) { described_class[:decl0] }
19
19
  [
20
20
  :validate,
21
21
  ].each do |method|
@@ -36,18 +36,18 @@ describe Oval::Base do
36
36
  expect { described_class.validate(:foo,:bar,'subj1') }.to_not raise_error
37
37
  end
38
38
  end
39
- context "validate(:foo,shape)" do
40
- let(:shape) { described_class[:shape0] }
41
- it "should invoke shape.validate(:foo,nil) once" do
42
- shape.expects(:validate).once.with(:foo,nil)
43
- expect { described_class.validate(:foo,shape) }.to_not raise_error
39
+ context "validate(:foo,decl)" do
40
+ let(:decl) { described_class[:decl0] }
41
+ it "should invoke decl.validate(:foo,nil) once" do
42
+ decl.expects(:validate).once.with(:foo,nil)
43
+ expect { described_class.validate(:foo,decl) }.to_not raise_error
44
44
  end
45
45
  end
46
- context "validate(:foo,shape,'subj1')" do
47
- let(:shape) { described_class[:shape0] }
48
- it "should invoke shape.validate(:foo,'subj1') once" do
49
- shape.expects(:validate).once.with(:foo,'subj1')
50
- expect { described_class.validate(:foo,shape,'subj1') }.to_not raise_error
46
+ context "validate(:foo,decl,'subj1')" do
47
+ let(:decl) { described_class[:decl0] }
48
+ it "should invoke decl.validate(:foo,'subj1') once" do
49
+ decl.expects(:validate).once.with(:foo,'subj1')
50
+ expect { described_class.validate(:foo,decl,'subj1') }.to_not raise_error
51
51
  end
52
52
  end
53
53
  end
@@ -65,7 +65,7 @@ describe Oval::Base do
65
65
  end
66
66
 
67
67
  describe "#validate" do
68
- let(:subject) { described_class[:shape0] }
68
+ let(:subject) { described_class[:decl0] }
69
69
  let(:msg) { "This method should be overwritten by a subclass" }
70
70
  [ [], [:arg1,:arg2,:arg3] ].each do |args|
71
71
  context "validate(#{args.map{|x| x.inspect}.join(', ')})" do
@@ -82,52 +82,20 @@ describe Oval::Base do
82
82
  end
83
83
  end
84
84
 
85
- ## describe "#validate_shape" do
86
- ## let(:subject) { described_class[:shape0] }
87
- ## let(:msg) { "This method should be overwritten by a subclass" }
88
- ## [ [:arg1,:arg2] ].each do |args|
89
- ## context "validate_shape(#{args.map{|x| x.inspect}.join(', ')})" do
90
- ## let(:args) { args }
91
- ## it { expect { subject.validate_shape(*args) }.to raise_error ArgumentError }
92
- ## end
93
- ## end
94
- ## context "validate_shape()" do
95
- ## it { expect { subject.validate_shape() }.to raise_error NotImplementedError, msg}
96
- ## end
97
- ## context "validate_shape(:subj1)" do
98
- ## it { expect { subject.validate_shape(:subj1) }.to raise_error NotImplementedError, msg}
99
- ## end
100
- ## end
101
-
102
-
103
- ## describe "shape" do
104
- #### before { described_class.stubs(:validate_shape) }
105
- ## context "new(:shape0).shape" do
106
- ## it { described_class.new(:shape0).shape.should be :shape0 }
107
- ## end
108
- ## context "when @shape == :shape1" do
109
- ## let(:subject) { described_class.new(:shape0) }
110
- ## before { subject.instance_variable_set(:@shape,:shape1) }
111
- ## it { subject.shape.should be :shape1 }
112
- ## end
113
- ## end
114
- ##
115
- ## describe "#shape=" do
116
- #### before { described_class.stubs(:validate_shape) }
117
- ## let(:subject) { described_class.new(:shape0) }
118
- ## context "#shape = :shape1" do
119
- #### it "should call self.class.validate_shape(:shape1) once" do
120
- #### subject # reference before re-stubbing validate_shape
121
- #### described_class.stubs(:validate_shape).never
122
- #### described_class.stubs(:validate_shape).once.with(:shape1,'Base')
123
- #### expect { subject.send(:shape=,:shape1) }.to_not raise_error
124
- #### end
125
- ## it "should assign @shape = :shape1" do
126
- ## subject.send(:shape=, :shape1)
127
- ## subject.instance_variable_get(:@shape).should be :shape1
128
- ## end
129
- ## end
130
- ## end
85
+ describe "#it_should" do
86
+ let(:subject) { described_class[:decl0] }
87
+ let(:msg) { "This method should be overwritten by a subclass" }
88
+ [ [:arg1], [:arg1,:arg2] ].each do |args|
89
+ context "it_should(#{args.map{|x| x.inspect}.join(', ')})" do
90
+ let(:args) { args }
91
+ before { described_class.expects(:it_should).never }
92
+ it { expect { subject.it_should(*args) }.to raise_error ArgumentError }
93
+ end
94
+ end
95
+ context "it_should" do
96
+ it { expect { subject.it_should }.to raise_error NotImplementedError, msg}
97
+ end
98
+ end
131
99
 
132
100
  describe "for_subject" do
133
101
  [
@@ -144,8 +112,7 @@ describe Oval::Base do
144
112
  end
145
113
 
146
114
  describe "#for_subject" do
147
- ## before { described_class.stubs(:validate_shape) }
148
- let(:subject) { described_class.new(:shape0) }
115
+ let(:subject) { described_class.new(:decl0) }
149
116
  context "for_subject(:subj1)" do
150
117
  it "should == self.class.for_subject(subject)" do
151
118
  described_class.expects(:for_subject).once.with(:subj1).returns :ok
@@ -170,8 +137,7 @@ describe Oval::Base do
170
137
  end
171
138
 
172
139
  describe "#enumerate" do
173
- ## before { described_class.stubs(:validate_shape) }
174
- let(:subject) { described_class.new(:shape0) }
140
+ let(:subject) { described_class.new(:decl0) }
175
141
  context "enumerate([],'and')" do
176
142
  it "should == self.class.enumerate(subject)" do
177
143
  described_class.expects(:enumerate).once.with([],'and').returns :ok
@@ -47,7 +47,7 @@ describe Oval do
47
47
  Class.new do
48
48
  extend Oval
49
49
  def self.foo(ops = {})
50
- ov_options[ :foo => ov_anything ].validate(ops, 'ops')
50
+ Oval.validate(ops, ov_options[ :foo => ov_anything ], 'ops')
51
51
  end
52
52
  end
53
53
  end
@@ -73,7 +73,7 @@ describe Oval do
73
73
  end
74
74
  # use ov to validate ops
75
75
  def self.foo(ops = {})
76
- ov.validate(ops, 'ops')
76
+ Oval.validate(ops, ov, 'ops')
77
77
  end
78
78
  end
79
79
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oval
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-03 00:00:00.000000000 Z
12
+ date: 2014-02-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -202,7 +202,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
202
202
  version: '0'
203
203
  segments:
204
204
  - 0
205
- hash: 2837400115143885778
205
+ hash: 3909914024463358041
206
206
  required_rubygems_version: !ruby/object:Gem::Requirement
207
207
  none: false
208
208
  requirements:
@@ -211,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
211
  version: '0'
212
212
  segments:
213
213
  - 0
214
- hash: 2837400115143885778
214
+ hash: 3909914024463358041
215
215
  requirements: []
216
216
  rubyforge_project:
217
217
  rubygems_version: 1.8.23