oval 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ fixtures:
2
+ symlinks:
3
+ repos: "#{source_dir}"
@@ -0,0 +1,18 @@
1
+ .pkg
2
+ Gemfile.lock
3
+ vendor
4
+ pkg
5
+ spec/lib
6
+ spec/fixtures
7
+ .rspec_system
8
+ .bundle
9
+ # Editor junk
10
+ *.swp
11
+ *.bkp
12
+ *.bak
13
+ *~
14
+ .tmp/
15
+ .yardoc/
16
+ doc/
17
+ coverage/
18
+ oval-*.gem
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format d
2
+ --colour
3
+ --backtrace
@@ -0,0 +1,25 @@
1
+ #! /bin/sh
2
+
3
+ # Build puppet module in /tmp for a given commit or tag.
4
+
5
+ set -e
6
+
7
+ ROOT=$(readlink -f "$(dirname $0)/..")
8
+ SOURCE="."
9
+ TARGET=`mktemp -d`
10
+
11
+ function do_build_module {
12
+ tag=$1
13
+ tgz="$TARGET/ptomulik-repos-${tag}.tar.gz"
14
+ dir="ptomulik-repos-$tag/"
15
+ git archive --prefix $dir --output $tgz $tag
16
+ (cd $TARGET && tar -xzf $tgz && cd $TARGET/$dir && puppet module build)
17
+ }
18
+
19
+ if [ $# -lt 1 ]; then
20
+ echo "Usage: $0 <commit>" >&2;
21
+ echo " or: $0 <tag>" >&2;
22
+ exit 1
23
+ fi
24
+
25
+ (cd $ROOT && do_build_module $1)
@@ -0,0 +1,22 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - 2.0.0
7
+ script: "bundle exec rake spec SPEC_OPTS='--format documentation'"
8
+ branches:
9
+ only:
10
+ master
11
+ env:
12
+ matrix:
13
+ - FACTER_GEM_VERSION="~> 1.3.0"
14
+ - FACTER_GEM_VERSION="~> 1.5.0"
15
+ - FACTER_GEM_VERSION="~> 1.6.0"
16
+ - FACTER_GEM_VERSION="~> 1.7.0"
17
+ #matrix:
18
+ # exclude:
19
+ # - rvm: 2.0.0
20
+ # env: FACTER_GEM_VERSION="~> 2.7.0"
21
+ notifications:
22
+ email: false
@@ -0,0 +1,4 @@
1
+ --title 'Options Validator'
2
+ --markup-provider=redcarpet
3
+ --markup=markdown
4
+ lib/**/*.rb
@@ -0,0 +1,2 @@
1
+ 2014-01-30 Pawel Tomulik <ptomulik@meil.pw.edu.pl>
2
+ * initial commit
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rspec-core'
5
+ gem 'rspec-expectations'
6
+ gem 'mocha'
7
+ if RUBY_VERSION >= "1.9"
8
+ gem 'coveralls', :require => false
9
+ gem 'yard'
10
+ gem 'redcarpet'
11
+ gem 'github-markup'
12
+ end
13
+ end
14
+
15
+ gemspec
16
+
17
+ # vim: ft=ruby
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (C) 2014 Paweł Tomulik <ptomulik@meil.pw.edu.pl>.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,8 @@
1
+ name 'ptomulik-options_validator'
2
+ version '0.0.1'
3
+ source 'git://github.com/ptomulik/puppet-options_validator.git'
4
+ author 'ptomulik'
5
+ license 'Apache License, Version 2.0'
6
+ summary 'Simple utility to validate Hashes of options.'
7
+ description 'Simple utility to validate Hashes of options.'
8
+ project_page 'https://gitbub.com/ptomulik/puppet-options_validator'
@@ -0,0 +1,280 @@
1
+ #Oval - Options Validator
2
+
3
+ [![Build Status](https://travis-ci.org/ptomulik/rubygems-oval.png?branch=master)](https://travis-ci.org/ptomulik/rubygems-oval)
4
+ [![Coverage Status](https://coveralls.io/options_validator/ptomulik/rubygems-oval/badge.png)](https://coveralls.io/r/ptomulik/rubygems-oval)
5
+ [![Code Climate](https://codeclimate.com/github/ptomulik/rubygems-oval.png)](https://codeclimate.com/github/ptomulik/rubygems-oval)
6
+
7
+ ####<a id="table-of-contents"></a>Table of Contents
8
+
9
+ 1. [Overview](#overview)
10
+ 2. [Module Description](#module-description)
11
+ 3. [Usage](#usage)
12
+ * [Example 1: Declaring simple options](#example-1-declaring-simple-options)
13
+ * [Example 2: Separating declaration from validation](#example-2-separating-declaration-from-validation)
14
+ 4. [Reference](#reference)
15
+ * [Declarators](#declarators)
16
+ * [API Reference](#api-reference)
17
+ 5. [Limitations](#limitations)
18
+
19
+ ##<a id="overview"></a>Overview
20
+
21
+ Validate option hashes when passed to methods.
22
+
23
+ [[Table of Contents](#table-of-contents)]
24
+
25
+ ##<a id="module-description"></a>Module Description
26
+
27
+ Using hashes to pass options to methods is a very common ruby practice. With **Oval** method authors may restrict callers to pass only declared options that meet requirements described in a hash declaration.
28
+
29
+ The shape of acceptable hashes is described by a simple grammar. The validation is then carried out by a recursive-descent parser that matches the actual values provided by caller against [declarators](#declarators) that comprise the hash declaration.
30
+
31
+ A declaration consists of terminal and non-terminal declarators. Non-terminal declarators are created by methods of `Oval` module which have names starting with `ov_` prefix. All other values (such as `:symbol`, `'string'`, `nil`, or `Class`) are terminals. Terminals use `==` operator to match the values provided by caller. Non-teminal use its own logic introducing more elaborate matching criteria (see for example [ov_collection](#ov_collection)).
32
+
33
+ **Oval** raises **Oval::DeclError** if the declaration is not well-formed, that is if the description of options shape is erronrneous. This is raised from the point of declaration. Other, more common exception is the **Oval::ValueError** which is raised everytime validation fails. This one is raised from within a method which takes the options as an argument.
34
+
35
+ [[Table of Contents](#table-of-contents)]
36
+
37
+ ##<a id="usage"></a>Usage
38
+
39
+ The usage is basically a two-step procedure. The first step is to declare options shape. This would create a validator object. The second step is to validate options within a method using the previously constructed validator. For simple hashes the entire construction may fit to a single line. Let's start with such a simple example.
40
+
41
+ ###<a id="example-1-declaring-simple-options"></a>Example 1: Declaring Simple Options
42
+
43
+ The method `foo` in the following code accepts only `{}` and `{:foo => value}`
44
+ as `options`, where `value` is arbitrary:
45
+
46
+ ```ruby
47
+ # Options validator
48
+ require 'oval'
49
+ class C
50
+ extend Oval
51
+ def self.foo(ops = {})
52
+ ov_options[ :foo => ov_anything ].validate(ops, 'ops')
53
+ end
54
+ end
55
+ ```
56
+
57
+ What does it do? Just try it out:
58
+
59
+ ```ruby
60
+ C.foo # should pass
61
+ C.foo :foo => 10 # should pass
62
+ C.foo :foo => 10, :bar => 20 # Oval::ValueError "Invalid option :bar for ops. Allowed options are :foo"
63
+ ```
64
+
65
+ Options are declared with [ov_xxx declarators](#declarators). The [ov_options](#ov_options) method should always be at the top level. Then all the allowed options should be listed inside of `[]` square brackets. Keys may be any values convertible to strings (i.e. a key given in declaration must `respond_to? :to_s`). Values are declared recursivelly using [ov_xxx declarators](#declarators) or terminal declarators (any other ruby values).
66
+
67
+ In [Example 1](#example-1-declaring-simple-options) we have declared options inside of a method for simplicity. This isn't an optimal technique. Usually options' declaration remains same for the entire lifetime of an application, so it is unnecessary to recreate the declaration each time function is called. In other words, we should move the declaration outside of the method, convert it to a singleton and only validate options inside of a function. For that purpose, t
68
+ he [Example 1](#example-1-declaring-simple-options) could be modified to the following form
69
+
70
+ ###<a id="example-2-separating-declaration-from-validation"></a>Example 2: Separating declaration from validation
71
+
72
+ In this example we separate options declaration from the validation to reduce costs related to options declaration:
73
+
74
+ ```ruby
75
+ # Options validator
76
+ require 'oval'
77
+ class C
78
+ extend Oval
79
+ # create a singleton declaration ov
80
+ def self.ov
81
+ @ov ||= ov_options[ :foo => ov_anything ]
82
+ end
83
+ # use ov to validate ops
84
+ def self.foo(ops = {})
85
+ ov.validate(ops, 'ops')
86
+ end
87
+ end
88
+ ```
89
+
90
+ [[Table of Contents](#table-of-contents)]
91
+
92
+ ##<a id="reference"></a>Reference
93
+
94
+ ###<a id="declarators"></a>Declarators
95
+
96
+ A declaration of options consists entirely of what we call here **declarators**. The [ov_options](#ov_options) should be used as a root of every declaration (starting symbol in grammar terms). It accepts a Hash of the form **{optname => optdecl, ...}** as an argument. The **optname** is an option name, and **optdecl** is a declarator restricting the options's value. Each option name (key) must be convertible to a `String`. Option value declarators are non-terminal declarators (defined later in this section) or terminals (any other ruby values). The simple declaration
97
+
98
+ ```ruby
99
+ ov_options[ :foo => :bar ]
100
+ ```
101
+
102
+ uses only terminals inside of **ov_options** and literarly permits only the `{:foo => :bar}` or the empty hash `{}` as options (and nothing else). This is how terminal declarators (`:foo` and `:bar` in this example) work. More freedom may be introduced with non-terminal declarators, for example:
103
+
104
+ ```ruby
105
+ ov_options[ :foo => ov_anything ]
106
+ ```
107
+
108
+ defines an option `:foo` which accepts any value. In what follows, we'll document all the core non-terminal declarators implemented in **Oval**.
109
+
110
+ ####<a id="ov\_anything"></a>ov\_anything
111
+
112
+ - Declaration
113
+
114
+ ```ruby
115
+ ov_anything
116
+ ```
117
+
118
+ or
119
+
120
+ ```ruby
121
+ ov_anything[]
122
+ ```
123
+
124
+ - Validation - permits any value
125
+ - Example
126
+
127
+ ```ruby
128
+ ov = ov_options[ :bar => ov_anything ]
129
+ def foo(ops = {})
130
+ ov.validate(ops, 'ops')
131
+ end
132
+ ```
133
+
134
+
135
+ ####<a id="ov\_collection"></a>ov\_collection
136
+
137
+ - Declaration
138
+
139
+ ```ruby
140
+ ov_collection[ class_decl, item_decl ]
141
+ ```
142
+
143
+ - Validation - permits only collections of type **class_decl** with items matching **item_decl** declaration
144
+ - Allowed values for **class\_decl** are:
145
+ - `Hash` or `Array` or any subclass of `Hash` or `Array`,
146
+ - `ov_subclass_of[klass]` where **klass** is `Hash` or `Array` or a subclass of any of them.
147
+ - Allowed values for **item_decl**:
148
+ - if **class\_decl** is `Array`-like, then any value is allowed as **item\_decl**,
149
+ - if **class\_decl** is `Hash`-like, then **item\_decl** should be a one-element Hash in form **{ key\_decl => val\_decl }**.
150
+ - Example
151
+
152
+ ```ruby
153
+ ov = ov_options[
154
+ :bar => ov_collection[ Hash, { instance_of[Symbol] => anything } ],
155
+ :geez => ov_collection [ Array, instance_of[String] ]
156
+ ]
157
+ def foo(ops = {})
158
+ ov.validate(ops, 'ops')
159
+ end
160
+ ```
161
+
162
+ ####<a id="ov\_instance\_of"></a>ov\_instance\_of
163
+
164
+ - Declaration
165
+
166
+ ```ruby
167
+ ov_instance_of[klass]
168
+ ```
169
+
170
+ - Validation - permits only instances of a given class **klass**
171
+ - Allowed values for **klass** - only class names, for example `String`, `Hash`, etc.
172
+ - Example
173
+
174
+ ```ruby
175
+ ov = ov_options[ :bar => ov_instance_of[String] ]
176
+ def foo(ops = {})
177
+ ov.validate(ops,'ops')
178
+ end
179
+ ```
180
+
181
+ ####<a id="ov\_kind\_of"></a>ov\_kind\_of
182
+
183
+ - Declaration
184
+
185
+ ```ruby
186
+ ov_kind_of[klass]
187
+ ```
188
+
189
+ - Validation - permits only values that are a kind of given class **klass**
190
+ - Allowed values for **klass** - only class names, for example `String`, `Hash`, etc.
191
+ - Example
192
+
193
+ ```ruby
194
+ ov = ov_options[ :bar => ov_kind_of[Numeric] ]
195
+ def foo(ops = {})
196
+ ov.validate(ops,'ops')
197
+ end
198
+ ```
199
+
200
+ ####<a id="ov\_one\_of"></a>ov\_one\_of
201
+
202
+ - Declaration
203
+
204
+ ```ruby
205
+ ov_one_of[decl1,decl2,...]
206
+ ```
207
+
208
+ - Validation - permits only values matching one of declarations `decl`, `decl2`, ...
209
+ - Example
210
+
211
+ ```ruby
212
+ ov = ov_options[
213
+ :bar => ov_one_of[ ov_instance_of[String], ov_kind_of[Numeric], nil ]
214
+ ]
215
+ def foo(ops = {})
216
+ ov.validate(ops,'ops')
217
+ end
218
+ ```
219
+
220
+ ####<a id="ov\_options"></a>ov\_options
221
+
222
+ - Declaration
223
+
224
+ ```ruby
225
+ ov_options[ optkey_decl1 => optval_decl1, ... ]
226
+ ```
227
+
228
+ - Validation - permits only declared options and their values.
229
+ - Allowed values for `optkey_declN` - anything that is convertible to string (namely, anything that responds to `to_s` method).
230
+ - Example:
231
+
232
+ ```ruby
233
+ ov = ov_options[
234
+ :bar => ov_anything,
235
+ :geez => ov_instance_of[String],
236
+ # ...
237
+ ]
238
+ def foo(ops = {})
239
+ ov.validate(ops,'ops')
240
+ end
241
+ ```
242
+
243
+ ####<a id="ov\_subclass\_of"></a>ov\_subclass\_of
244
+
245
+ - Declaration
246
+
247
+ ```ruby
248
+ ov_subclass_of[klass]
249
+ ```
250
+
251
+ - Validation - permits only subclasses of **klass**
252
+ - Allowed values for **klass** - only class names, for example `String`, `Hash`, etc.
253
+ - Example
254
+
255
+ ```ruby
256
+ ov = ov_options[ :bar => ov_subclass_of[Numeric] ]
257
+ def foo(ops = {})
258
+ ov.validate(ops,'ops')
259
+ end
260
+ ```
261
+
262
+ ###<a id="api-reference"></a>API Reference
263
+
264
+ API reference may be generated with
265
+
266
+ ```console
267
+ bundle exec rake yard
268
+ ```
269
+
270
+ The generated documentation goes to `doc/` directory. Note that this works only
271
+ under ruby >= 1.9.
272
+
273
+ The API documentation is also available
274
+ [online](http://rdoc.info/github/ptomulik/rubygems-oval/).
275
+
276
+ [[Table of Contents](#table-of-contents)]
277
+
278
+ ##Limitations
279
+
280
+ [[Table of Contents](#table-of-contents)]
@@ -0,0 +1,27 @@
1
+ # rubygems-oval
2
+
3
+ ## Notes for developers
4
+
5
+ ### Cloning the repository
6
+
7
+ git clone git://github.com/ptomulik/rubygems-oval.git
8
+
9
+ ### Installing required gems
10
+
11
+ bundle install --path vendor
12
+
13
+ ### Runing unit tests
14
+
15
+ bundle exec rake spec
16
+
17
+ ### Runing single test (e.g. **macro_spec.rb**)
18
+
19
+ bundle exec rake spec_prep && \
20
+ bundle exec rspec spec/unit/oval/base.rb
21
+
22
+ ### Generating API documentation
23
+
24
+ bundle exec rake yard
25
+
26
+ The generated documentation goes to `doc/` directory. Note that this works only
27
+ under ruby >= 1.9.
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ Bundler.require :default
5
+
6
+ require 'rspec/core/rake_task'
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ if RUBY_VERSION >= "1.9"
11
+ # Generating API documentation, run with 'rake yard'
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new do |t|
14
+ t.options = [
15
+ '--title', 'Options Validator',
16
+ '--markup-provider=redcarpet',
17
+ '--markup=markdown',
18
+ 'lib/**/*.rb'
19
+ ]
20
+ end
21
+ end
22
+
23
+ task :default do
24
+ sh %{rake -T}
25
+ end