verifier 0.0.1
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 +7 -0
- data/.metrics +5 -0
- data/.rspec +2 -0
- data/.yardopts +2 -0
- data/Guardfile +6 -0
- data/LICENSE +21 -0
- data/README.md +126 -0
- data/Rakefile +17 -0
- data/config/metrics/STYLEGUIDE +230 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +15 -0
- data/config/metrics/pippi.yml +3 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +79 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +8 -0
- data/config/metrics/yardstick.yml +37 -0
- data/lib/verifier.rb +51 -0
- data/lib/verifier/exceptions.rb +14 -0
- data/lib/verifier/scope.rb +60 -0
- data/lib/verifier/verification.rb +125 -0
- data/lib/verifier/version.rb +7 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/verifier/invalid_spec.rb +6 -0
- data/spec/verifier/method_fails_spec.rb +6 -0
- data/spec/verifier/method_not_defined_spec.rb +6 -0
- data/spec/verifier/verify_spec.rb +135 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9dfc1bf33da69d7167f3d952b11ea361d290985e
|
4
|
+
data.tar.gz: d3cbb113f342c8fb4720761f6ef9092943e561ce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ee5faa714966ff475c60f14ccf7003650cd8aa22061f911c092f35a600846d4d1401ba9dde5f534822586ab0387207b9842424e8e83e2e9ce9016a5ab80fdb8
|
7
|
+
data.tar.gz: f7963fb3309f2ec7d424977269df7d87a6278d069b6ca83cdcdf38fc999e3895019c8f8b795eb54058913e5de2687ac099f8170ab5bd9caf09e40d821199898b
|
data/.metrics
ADDED
data/.rspec
ADDED
data/.yardopts
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2015 Andrew Kozin, andrew.kozin@gmail.com
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# Verifier
|
2
|
+
|
3
|
+
[][gem]
|
4
|
+
[][travis]
|
5
|
+
[][gemnasium]
|
6
|
+
[][codeclimate]
|
7
|
+
[][coveralls]
|
8
|
+
[](file:LICENSE)
|
9
|
+
|
10
|
+
[gem]: https://rubygems.org/gems/verifier
|
11
|
+
[travis]: https://travis-ci.org/nepalez/verifier
|
12
|
+
[gemnasium]: https://gemnasium.com/nepalez/verifier
|
13
|
+
[codeclimate]: https://codeclimate.com/github/nepalez/verifier
|
14
|
+
[coveralls]: https://coveralls.io/r/nepalez/verifier
|
15
|
+
|
16
|
+
The library to verify variables are satisfy given condititions and raise `ArgumentError` otherwise.
|
17
|
+
|
18
|
+
Defines a `#verify` instance method with a block to be yielded in a variable's scope and raised an error if the block returns false or fails.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Add this line to your application's Gemfile:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem "verifier"
|
26
|
+
```
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
```
|
31
|
+
$ bundle
|
32
|
+
```
|
33
|
+
|
34
|
+
Or install it yourself as:
|
35
|
+
|
36
|
+
```
|
37
|
+
$ gem install verifier
|
38
|
+
```
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
Include the module into class or Method to use it in the instance methods, or extend the class to check verifier of the class methods.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
require "verifier"
|
46
|
+
|
47
|
+
class Greeter
|
48
|
+
include Verifier
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
This will define the `#verify` instance method.
|
53
|
+
|
54
|
+
Call it from your method with the names of the verified variable and the condition, and the block to be called **in the scope of a value, returned by the method**.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
class Greeter
|
58
|
+
# ...
|
59
|
+
def hello(name)
|
60
|
+
verify(:name, :long_enough) { count > 1 }
|
61
|
+
"Hello, #{ name }!"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
Then define i18n translations for error messages:
|
67
|
+
|
68
|
+
```yaml
|
69
|
+
# config/locales/en.yml
|
70
|
+
---
|
71
|
+
en:
|
72
|
+
verifier: # the module's scope
|
73
|
+
greeter: # the class name
|
74
|
+
instance: # the scope for the method
|
75
|
+
# the message to be raised when the method raises an exception
|
76
|
+
fails: "The method fails: %{value}"
|
77
|
+
# the message to be raised when the method isn't defined
|
78
|
+
undefined: "The method undefined: %{value}"
|
79
|
+
name: # the name of the method to be verified
|
80
|
+
# the message to be raised when the block fails or returns false
|
81
|
+
long_enough: "The name to greet seems damn short: %{value}"
|
82
|
+
```
|
83
|
+
|
84
|
+
The block is yielded **in the scope of a corresponding variable**.
|
85
|
+
|
86
|
+
An `ArgumentError` will be raised in any case when:
|
87
|
+
* the verified method is undefined;
|
88
|
+
* the method raises an exception;
|
89
|
+
* the block raises an exception;
|
90
|
+
* the block returns a value, whose negation is `true`
|
91
|
+
(see the motivation [below]{#negation}).
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
greeter = Greeter.new
|
95
|
+
|
96
|
+
greeter.hello "Al"
|
97
|
+
# => "Hello, Al!"
|
98
|
+
|
99
|
+
greeter.hello "A"
|
100
|
+
# => <ArgumentError @message="The name to greet seems damn short: A" ...>
|
101
|
+
```
|
102
|
+
|
103
|
+
## Compatibility
|
104
|
+
|
105
|
+
Tested under MRI rubies >= 2.1
|
106
|
+
|
107
|
+
RSpec 3.0+ used for testing
|
108
|
+
|
109
|
+
Collection of used testing, debugging and code metric tools is defined
|
110
|
+
in the [hexx-suit](https://github.com/nepalez/hexx-suit) gem.
|
111
|
+
|
112
|
+
## Contributing
|
113
|
+
|
114
|
+
* Fork the project.
|
115
|
+
* Read the [styleguide](file:./config/metrics/STYLEGUIDE).
|
116
|
+
* Make your feature addition or bug fix.
|
117
|
+
* Add tests for it. This is important so I don't break it in a
|
118
|
+
future version unintentionally.
|
119
|
+
* Commit, do not mess with Rakefile or version
|
120
|
+
(if you want to have your own version, that is fine but bump version
|
121
|
+
in a commit by itself I can ignore when I pull)
|
122
|
+
* Send me a pull request. Bonus points for topic branches.
|
123
|
+
|
124
|
+
## License
|
125
|
+
|
126
|
+
See [MIT LICENSE](file:LICENSE).
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
begin
|
3
|
+
require "bundler/setup"
|
4
|
+
rescue LoadError
|
5
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
6
|
+
exit
|
7
|
+
end
|
8
|
+
|
9
|
+
# Loads bundler tasks
|
10
|
+
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
# Loads the Hexx::Suit and its tasks
|
13
|
+
require "hexx-suit"
|
14
|
+
Hexx::Suit.install_tasks
|
15
|
+
|
16
|
+
# Sets the Hexx::Suit :test task to default
|
17
|
+
task default: "check:coverage:run"
|
@@ -0,0 +1,230 @@
|
|
1
|
+
= Ruby Style Guide
|
2
|
+
|
3
|
+
Adapted from Dan Kubb's Ruby Style Guide
|
4
|
+
https://github.com/dkubb/styleguide/blob/master/RUBY-STYLE
|
5
|
+
|
6
|
+
== Commiting:
|
7
|
+
|
8
|
+
* Write descriptive commit messages, following the pattern:
|
9
|
+
|
10
|
+
[TYPE] name
|
11
|
+
|
12
|
+
The message, describing the changes being made
|
13
|
+
|
14
|
+
* Use the types below to mark commits:
|
15
|
+
|
16
|
+
- FEATURE - for adding new features, or backward-compatible changes;
|
17
|
+
- CHANGE - for backward-incompatible changes;
|
18
|
+
- BUG FIX - for fixing bugs;
|
19
|
+
- REFACTORING - for other changes of the code not affecting the API;
|
20
|
+
- OTHER - for changes in documentaton, metrics etc, not touching the code;
|
21
|
+
- VERSION - for version changes.
|
22
|
+
|
23
|
+
* Always separate commits of different types (such as FEATURE and CHANGE).
|
24
|
+
|
25
|
+
* Try to separate various features from each other.
|
26
|
+
|
27
|
+
* Include specification to the same commit as the code.
|
28
|
+
|
29
|
+
* Run all tests before making a commit.
|
30
|
+
Never commit the code that break unit tests.
|
31
|
+
|
32
|
+
* Use metric (run `rake check`) before making a commit.
|
33
|
+
|
34
|
+
* Do refactoring before making a commit. Best writing is rewriting.
|
35
|
+
|
36
|
+
* Follow semantic versioning.
|
37
|
+
|
38
|
+
http://semver.org/
|
39
|
+
|
40
|
+
* For versions name the commit after a version number, following the pattern:
|
41
|
+
|
42
|
+
VERSION 1.0.0-rc2
|
43
|
+
|
44
|
+
|
45
|
+
== Formatting:
|
46
|
+
|
47
|
+
* Use UTF-8. Declare encoding in the first line of every file.
|
48
|
+
|
49
|
+
# encoding: utf-8
|
50
|
+
|
51
|
+
* Use 2 space indent, no tabs.
|
52
|
+
|
53
|
+
* Use Unix-style line endings.
|
54
|
+
|
55
|
+
* Use spaces around operators, after commas, colons and semicolons,
|
56
|
+
around { and before }.
|
57
|
+
|
58
|
+
* No spaces after (, [ and before ], ).
|
59
|
+
|
60
|
+
* Align `when` and `else` with `case`.
|
61
|
+
|
62
|
+
* Use an empty line before the return value of a method (unless it
|
63
|
+
only has one line), and an empty line between defs.
|
64
|
+
|
65
|
+
* Use empty lines to break up a long method into logical paragraphs.
|
66
|
+
|
67
|
+
* Keep lines fewer than 80 characters.
|
68
|
+
|
69
|
+
* Strip trailing whitespace.
|
70
|
+
|
71
|
+
|
72
|
+
== Syntax:
|
73
|
+
|
74
|
+
* Write for 2.0.
|
75
|
+
|
76
|
+
* Use double quotes
|
77
|
+
|
78
|
+
http://viget.com/extend/just-use-double-quoted-ruby-strings
|
79
|
+
|
80
|
+
* Use def with parentheses when there are arguments.
|
81
|
+
|
82
|
+
* Never use for, unless you exactly know why.
|
83
|
+
|
84
|
+
* Never use then, except in case statements.
|
85
|
+
|
86
|
+
* Use when x then ... for one-line cases.
|
87
|
+
|
88
|
+
* Use &&/|| for boolean expressions, and/or for control flow. (Rule
|
89
|
+
of thumb: If you have to use outer parentheses, you are using the
|
90
|
+
wrong operators.)
|
91
|
+
|
92
|
+
* Avoid double negation (!!), unless Null Objects are expected.
|
93
|
+
|
94
|
+
http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness
|
95
|
+
|
96
|
+
* Avoid multiline ?:, use if.
|
97
|
+
|
98
|
+
* Use {...} when defining blocks on one line. Use do...end for multiline
|
99
|
+
blocks.
|
100
|
+
|
101
|
+
* Avoid return where not required.
|
102
|
+
|
103
|
+
* Use ||= freely.
|
104
|
+
|
105
|
+
* Use OO regexps, and avoid =~ $0-9, $~, $` and $' when possible.
|
106
|
+
|
107
|
+
* Do not use Enumerable#inject when the "memo" object does not change between
|
108
|
+
iterations, use Enumerable#each_with_object instead (in ruby 1.9,
|
109
|
+
active_support and backports).
|
110
|
+
|
111
|
+
* Prefer ENV.fetch to ENV[] syntax.
|
112
|
+
Prefer block syntax for ENV.fetch to usage of the second argument.
|
113
|
+
|
114
|
+
|
115
|
+
== Naming:
|
116
|
+
|
117
|
+
* Use snake_case for methods.
|
118
|
+
|
119
|
+
* Use CamelCase for classes and modules. (Keep acronyms like HTTP,
|
120
|
+
RFC, XML uppercase.)
|
121
|
+
|
122
|
+
* Use SCREAMING_SNAKE_CASE for other constants.
|
123
|
+
|
124
|
+
* Do not use single letter variable names. Avoid uncommunicative names.
|
125
|
+
|
126
|
+
* Use consistent variable names. Try to keep the variable names close
|
127
|
+
to the object class name.
|
128
|
+
|
129
|
+
* Use names prefixed with _ for unused variables.
|
130
|
+
|
131
|
+
* When defining a predicate method that compares against another object of
|
132
|
+
a similar type, name the argument "other".
|
133
|
+
|
134
|
+
* Prefer map over collect, detect over find, select over find_all.
|
135
|
+
|
136
|
+
* Use def self.method to define singleton methods.
|
137
|
+
|
138
|
+
* Avoid alias when alias_method will do.
|
139
|
+
|
140
|
+
|
141
|
+
== Comments:
|
142
|
+
|
143
|
+
* Use YARD and its conventions for API documentation. Don't put an
|
144
|
+
empty line between the comment block and the def.
|
145
|
+
|
146
|
+
* Comments longer than a word are capitalized and use punctuation.
|
147
|
+
Use one space after periods.
|
148
|
+
|
149
|
+
* Avoid superfluous comments.
|
150
|
+
|
151
|
+
|
152
|
+
== Code structuring:
|
153
|
+
|
154
|
+
* Break code into packages, decoupled from the environment.
|
155
|
+
|
156
|
+
* Wrap packages into gems.
|
157
|
+
|
158
|
+
* Inject dependencies explicitly.
|
159
|
+
Leave all outer references on the border of any package. Inside
|
160
|
+
the package use internal references only.
|
161
|
+
|
162
|
+
* Follow SOLID principles.
|
163
|
+
|
164
|
+
http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
|
165
|
+
|
166
|
+
* Only give a method one purpose for existing. If you pass in a boolean
|
167
|
+
to a method, what you're saying is that this method has two different
|
168
|
+
behaviours. Just split it into two single purpose methods. If you have
|
169
|
+
to use the words "AND" or "OR" to describe what the method does it
|
170
|
+
probably does too much.
|
171
|
+
|
172
|
+
* Avoid long methods.
|
173
|
+
Try to keep them at no more than 6 lines long, and preferably 4 or less.
|
174
|
+
|
175
|
+
If sections of a method are logically separate by blank lines, then
|
176
|
+
that's probably a sign that those sections should be split into separate
|
177
|
+
methods.
|
178
|
+
|
179
|
+
* Avoid hashes-as-optional-parameters. Does the method do too much?
|
180
|
+
|
181
|
+
* Avoid long parameter lists.
|
182
|
+
|
183
|
+
* Add "global" methods to Kernel (if you have to) and make them private.
|
184
|
+
|
185
|
+
* Use OptionParser for parsing complex command line options and
|
186
|
+
ruby -s for trivial command line options.
|
187
|
+
|
188
|
+
* Avoid needless metaprogramming.
|
189
|
+
|
190
|
+
* Always freeze objects assigned to constants.
|
191
|
+
|
192
|
+
|
193
|
+
== General:
|
194
|
+
|
195
|
+
* Code in a functional way, avoid mutation when it makes sense.
|
196
|
+
|
197
|
+
* Try to have methods either return the state of the object and have
|
198
|
+
no side effects, or return self and have side effects. This is
|
199
|
+
otherwise known as Command-query separation (CQS):
|
200
|
+
|
201
|
+
http://en.wikipedia.org/wiki/Command-query_separation
|
202
|
+
|
203
|
+
* Do not mutate arguments unless that is the purpose of the method.
|
204
|
+
|
205
|
+
* Try following TRUE heuristics by Sandi Metz
|
206
|
+
|
207
|
+
http://designisrefactoring.com/2015/02/08/introducing-sandi-metz-true/
|
208
|
+
|
209
|
+
* Do not mess around in core classes when writing libraries.
|
210
|
+
Namespace your code inside the modules, or wrap core classes to
|
211
|
+
decorators of your own.
|
212
|
+
|
213
|
+
* Do not program defensively.
|
214
|
+
|
215
|
+
http://www.erlang.se/doc/programming_rules.shtml#HDR11
|
216
|
+
|
217
|
+
* Keep the code simple.
|
218
|
+
|
219
|
+
* Don't overdesign.
|
220
|
+
|
221
|
+
* Don't underdesign.
|
222
|
+
|
223
|
+
* Avoid bugs.
|
224
|
+
|
225
|
+
* Read other style guides and apply the parts that don't dissent with
|
226
|
+
this list.
|
227
|
+
|
228
|
+
* Be consistent.
|
229
|
+
|
230
|
+
* Use common sense.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
folders: # The list of folders to be used by any metric.
|
3
|
+
- lib
|
4
|
+
- app
|
5
|
+
metrics: # The list of allowed metrics. The other metrics are disabled.
|
6
|
+
- cane
|
7
|
+
- churn
|
8
|
+
- flay
|
9
|
+
- flog
|
10
|
+
- reek
|
11
|
+
- roodi
|
12
|
+
- saikuro
|
13
|
+
format: html
|
14
|
+
output: tmp/metric_fu
|
15
|
+
verbose: false
|
@@ -0,0 +1 @@
|
|
1
|
+
---
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
AssignmentInConditionalCheck:
|
3
|
+
CaseMissingElseCheck:
|
4
|
+
ClassLineCountCheck:
|
5
|
+
line_count: 300
|
6
|
+
ClassNameCheck:
|
7
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
8
|
+
ClassVariableCheck:
|
9
|
+
CyclomaticComplexityBlockCheck:
|
10
|
+
complexity: 4
|
11
|
+
CyclomaticComplexityMethodCheck:
|
12
|
+
complexity: 8
|
13
|
+
EmptyRescueBodyCheck:
|
14
|
+
ForLoopCheck:
|
15
|
+
MethodLineCountCheck:
|
16
|
+
line_count: 20
|
17
|
+
MethodNameCheck:
|
18
|
+
pattern: !ruby/regexp /^[\||\^|\&|\!]$|^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
|
19
|
+
ModuleLineCountCheck:
|
20
|
+
line_count: 300
|
21
|
+
ModuleNameCheck:
|
22
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
23
|
+
ParameterNumberCheck:
|
24
|
+
parameter_count: 5
|
@@ -0,0 +1,79 @@
|
|
1
|
+
---
|
2
|
+
# settings added by the 'hexx-suit' module
|
3
|
+
# output: "tmp/rubocop"
|
4
|
+
# format: "html"
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
Exclude:
|
8
|
+
- '**/db/schema.rb'
|
9
|
+
|
10
|
+
Lint/HandleExceptions:
|
11
|
+
Exclude:
|
12
|
+
- 'spec/**/*'
|
13
|
+
|
14
|
+
Lint/RescueException:
|
15
|
+
Exclude:
|
16
|
+
- 'spec/**/*'
|
17
|
+
|
18
|
+
Metrics/ClassLength:
|
19
|
+
Exclude:
|
20
|
+
- 'lib/**/generator*'
|
21
|
+
|
22
|
+
Style/AccessorMethodName:
|
23
|
+
Exclude:
|
24
|
+
- 'spec/**/*'
|
25
|
+
|
26
|
+
Style/AsciiComments:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Style/ClassAndModuleChildren:
|
30
|
+
Exclude:
|
31
|
+
- 'spec/**/*'
|
32
|
+
|
33
|
+
Style/Documentation:
|
34
|
+
Exclude:
|
35
|
+
- 'lib/**/version.rb'
|
36
|
+
- 'spec/**/*'
|
37
|
+
|
38
|
+
Style/EmptyLinesAroundBlockBody:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Style/EmptyLinesAroundClassBody:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Style/EmptyLinesAroundMethodBody:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Style/EmptyLinesAroundModuleBody:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Style/EmptyLineBetweenDefs:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Style/FileName:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Style/RaiseArgs:
|
57
|
+
EnforcedStyle: compact
|
58
|
+
|
59
|
+
Style/SingleLineMethods:
|
60
|
+
Exclude:
|
61
|
+
- 'spec/**/*'
|
62
|
+
|
63
|
+
Style/SingleSpaceBeforeFirstArg:
|
64
|
+
Enabled: false
|
65
|
+
|
66
|
+
Style/SpecialGlobalVars:
|
67
|
+
Exclude:
|
68
|
+
- 'Gemfile'
|
69
|
+
- '*.gemspec'
|
70
|
+
|
71
|
+
Style/StringLiterals:
|
72
|
+
EnforcedStyle: double_quotes
|
73
|
+
|
74
|
+
Stype/StringLiteralsInInterpolation:
|
75
|
+
EnforcedStyle: double_quotes
|
76
|
+
|
77
|
+
Style/TrivialAccessors:
|
78
|
+
Exclude:
|
79
|
+
- 'spec/**/*'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
# Settings added by the 'hexx-suit' gem
|
3
|
+
output: "tmp/yardstick/output.log"
|
4
|
+
path: "lib/**/*.rb"
|
5
|
+
rules:
|
6
|
+
ApiTag::Presence:
|
7
|
+
enabled: false
|
8
|
+
exclude: []
|
9
|
+
ApiTag::Inclusion:
|
10
|
+
enabled: true
|
11
|
+
exclude: []
|
12
|
+
ApiTag::ProtectedMethod:
|
13
|
+
enabled: true
|
14
|
+
exclude: []
|
15
|
+
ApiTag::PrivateMethod:
|
16
|
+
enabled: false
|
17
|
+
exclude: []
|
18
|
+
ExampleTag:
|
19
|
+
enabled: true
|
20
|
+
exclude: []
|
21
|
+
ReturnTag:
|
22
|
+
enabled: true
|
23
|
+
exclude: []
|
24
|
+
Summary::Presence:
|
25
|
+
enabled: true
|
26
|
+
exclude: []
|
27
|
+
Summary::Length:
|
28
|
+
enabled: true
|
29
|
+
exclude: []
|
30
|
+
Summary::Delimiter:
|
31
|
+
enabled: true
|
32
|
+
exclude: []
|
33
|
+
Summary::SingleLine:
|
34
|
+
enabled: true
|
35
|
+
exclude: []
|
36
|
+
threshold: 100
|
37
|
+
verbose: false
|
data/lib/verifier.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
%w(
|
3
|
+
exceptions
|
4
|
+
scope
|
5
|
+
verification
|
6
|
+
).each { |name| require_relative "verifier/#{ name }" }
|
7
|
+
|
8
|
+
# Defines {#verify} method to check variables
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# class Greeter
|
12
|
+
# include Verifier
|
13
|
+
#
|
14
|
+
# def hello(name)
|
15
|
+
# verify(:name, :long_enough) { count > 1 }
|
16
|
+
# "Hello, #{ name }!"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# greeter = Greeter.new
|
21
|
+
# greeter.hello "Ali"
|
22
|
+
# # => "Hello, Ali!"
|
23
|
+
#
|
24
|
+
# greeter.hello "X"
|
25
|
+
# # => <Verifier::Invalid ...>
|
26
|
+
module Verifier
|
27
|
+
|
28
|
+
# Runs a verification
|
29
|
+
#
|
30
|
+
# @param [Symbol] method
|
31
|
+
# the name of the method to be verified
|
32
|
+
# @param [Symbol] name
|
33
|
+
# the name of verification
|
34
|
+
# @param [Proc] block
|
35
|
+
#
|
36
|
+
# @yield block in the scope of a value returned by the method
|
37
|
+
#
|
38
|
+
# @raise [Verifier::MethodNotDefined]
|
39
|
+
# if the method not defined
|
40
|
+
# @raise [Verifier::MethodFails]
|
41
|
+
# it calling the method raises a +StandardError+
|
42
|
+
# @raise [Verifier::Invalid]
|
43
|
+
# if the block fails or returns a value whose negation is truthy
|
44
|
+
#
|
45
|
+
# @return [undefined]
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def verify(method, name, &block)
|
49
|
+
Verification.run(self, method, name, &block)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Exceptions raised by Verifier#verify method
|
4
|
+
module Verifier
|
5
|
+
|
6
|
+
# Exception raised when a verification fails
|
7
|
+
Invalid = Class.new ::RuntimeError
|
8
|
+
|
9
|
+
# Exception raised when calling a verified method raises a StandardError
|
10
|
+
MethodFails = Class.new ::RuntimeError
|
11
|
+
|
12
|
+
# Exception raised when a verified method is not defined
|
13
|
+
MethodNotDefined = Class.new ::NameError
|
14
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "extlib"
|
3
|
+
|
4
|
+
module Verifier
|
5
|
+
|
6
|
+
# Provides the scope for I18n translations of verification errors
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Scope
|
10
|
+
|
11
|
+
# Initializes a new instance
|
12
|
+
#
|
13
|
+
# @param [Object] object
|
14
|
+
# the object whose method should be verified
|
15
|
+
# @param [Symbol] method
|
16
|
+
# the name of the method to be verified
|
17
|
+
#
|
18
|
+
# @return [undefined]
|
19
|
+
def initialize(object, method)
|
20
|
+
@object, @method = object, method
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a scope for all translations of {#object} verification errors
|
24
|
+
#
|
25
|
+
# @return [Array<Symbol>]
|
26
|
+
def short
|
27
|
+
@short ||= [:verifier, name, type]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a scope for translations of {#method} verification errors
|
31
|
+
#
|
32
|
+
# @return [Array<Symbol>]
|
33
|
+
def full
|
34
|
+
@full ||= short + [method.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a tag (# or .) for the method
|
38
|
+
#
|
39
|
+
# @return [<String>]
|
40
|
+
def tag
|
41
|
+
(type == :class) ? "." : "#"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :object, :method
|
47
|
+
|
48
|
+
def type
|
49
|
+
@type ||= object.is_a?(Class) ? :class : :instance
|
50
|
+
end
|
51
|
+
|
52
|
+
def name
|
53
|
+
@name ||= object_class_name.split("::").map(&:snake_case).join("/").to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
def object_class_name
|
57
|
+
object.class.name
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Verifier
|
4
|
+
|
5
|
+
# Verification runner
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class Verification
|
9
|
+
|
10
|
+
# Initializes a verification object
|
11
|
+
#
|
12
|
+
# @param [Object] object
|
13
|
+
# the object whose method should be verified
|
14
|
+
# @param [Symbol] variable
|
15
|
+
# the name of the variable to be verified
|
16
|
+
# @param [Symbol] name
|
17
|
+
# the name of verification
|
18
|
+
# @param [Proc] block
|
19
|
+
#
|
20
|
+
# @return [undefined]
|
21
|
+
def initialize(object, variable, name, &block)
|
22
|
+
fail SyntaxError.new "No block given" unless block_given?
|
23
|
+
@object, @variable, @name, @block = object, variable, name, block
|
24
|
+
end
|
25
|
+
|
26
|
+
# Runs a verification
|
27
|
+
#
|
28
|
+
# @yield block in the scope of a value returned by the {#variable}
|
29
|
+
#
|
30
|
+
# @raise [Verifier::MethodNotDefined]
|
31
|
+
# if the {#variable} not defined by {#object}
|
32
|
+
# @raise [Verifier::MethodFails]
|
33
|
+
# it calling the {#variable} raises a +StandardError+
|
34
|
+
# @raise [Verifier::Invalid]
|
35
|
+
# if the block fails or returns a value whose negation is truthy
|
36
|
+
#
|
37
|
+
# @return [undefined]
|
38
|
+
def run
|
39
|
+
check_method_existence
|
40
|
+
check_condition
|
41
|
+
end
|
42
|
+
|
43
|
+
# Constructs and runs a verification object
|
44
|
+
#
|
45
|
+
# @param (see #initialize)
|
46
|
+
#
|
47
|
+
# @raise (see #run)
|
48
|
+
#
|
49
|
+
# @return (see #run)
|
50
|
+
def self.run(object, variable, name, &block)
|
51
|
+
send(:new, object, variable, name, &block).run
|
52
|
+
end
|
53
|
+
|
54
|
+
# @note
|
55
|
+
# The class has a private constructor. Use {.run} method instead.
|
56
|
+
private_class_method :new
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
attr_reader :object, :variable, :name, :block
|
61
|
+
|
62
|
+
def check_method_existence
|
63
|
+
fail(undefined) unless object.respond_to?(variable)
|
64
|
+
end
|
65
|
+
|
66
|
+
def value
|
67
|
+
@value ||= object.send(variable)
|
68
|
+
rescue
|
69
|
+
raise method_fails
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_condition
|
73
|
+
fail unless value.instance_eval(&block)
|
74
|
+
rescue
|
75
|
+
raise invalid
|
76
|
+
end
|
77
|
+
|
78
|
+
# Exceptions to be raised
|
79
|
+
|
80
|
+
def undefined
|
81
|
+
MethodNotDefined.new translate(
|
82
|
+
:undefined,
|
83
|
+
scope: scope.short,
|
84
|
+
value: variable,
|
85
|
+
default: "Method not defined: #{ method_name }"
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def method_fails
|
90
|
+
MethodFails.new translate(
|
91
|
+
:fails,
|
92
|
+
scope: scope.short,
|
93
|
+
value: variable,
|
94
|
+
default: "Method fails: #{ method_name }"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def invalid
|
99
|
+
Invalid.new translate(
|
100
|
+
name,
|
101
|
+
scope: scope.full,
|
102
|
+
value: value,
|
103
|
+
default: default_message
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
def default_message
|
108
|
+
"#{ method_name } verification failed: #{ value.inspect } not #{ name }"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Translation helpers
|
112
|
+
|
113
|
+
def method_name
|
114
|
+
@method_name ||= "#{ object.class.name }#{ scope.tag }#{ variable }"
|
115
|
+
end
|
116
|
+
|
117
|
+
def scope
|
118
|
+
@scope ||= Scope.new(object, variable)
|
119
|
+
end
|
120
|
+
|
121
|
+
def translate(name, options = {})
|
122
|
+
I18n.t(name, options)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
describe Verifier, "#verify" do
|
2
|
+
|
3
|
+
# subject is an instance of class, that includes Verifier and has #foo method
|
4
|
+
before { Test = Class.new }
|
5
|
+
before { Test.include described_class }
|
6
|
+
before { Test.send(:define_method, :foo) { "foo" } }
|
7
|
+
subject { Test.new }
|
8
|
+
after { Object.send :remove_const, :Test }
|
9
|
+
|
10
|
+
it "is defined" do
|
11
|
+
expect(subject).to respond_to(:verify).with(2).arguments
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when a block isn't given" do
|
15
|
+
|
16
|
+
it "raises SyntaxError" do
|
17
|
+
expect { subject.verify(:foo, :valid) }.to raise_error SyntaxError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when a method is not defined" do
|
22
|
+
|
23
|
+
it "raises Verifier::MethodNotDefined" do
|
24
|
+
expect { subject.verify(:bar, :valid) { true } }
|
25
|
+
.to raise_error Verifier::MethodNotDefined
|
26
|
+
end
|
27
|
+
|
28
|
+
it "displays proper error message" do
|
29
|
+
expected_message = "Method not defined: Test#bar"
|
30
|
+
|
31
|
+
begin
|
32
|
+
subject.verify(:bar, :valid) { true }
|
33
|
+
rescue => error
|
34
|
+
expect(error.message).to eq expected_message
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when a method raises RuntimeError" do
|
40
|
+
|
41
|
+
before { Test.send(:define_method, :bar) { fail } }
|
42
|
+
|
43
|
+
it "raises Verifier::MethodFails" do
|
44
|
+
expect { subject.verify(:bar, :valid) { true } }
|
45
|
+
.to raise_error Verifier::MethodFails
|
46
|
+
end
|
47
|
+
|
48
|
+
it "displays proper error message" do
|
49
|
+
expected_message = "Method fails: Test#bar"
|
50
|
+
|
51
|
+
begin
|
52
|
+
subject.verify(:bar, :valid) { true }
|
53
|
+
rescue => error
|
54
|
+
expect(error.message).to eq expected_message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when a block raises RuntimeError" do
|
60
|
+
|
61
|
+
it "raises Verifier::Invalid" do
|
62
|
+
expect { subject.verify(:foo, :valid) { fail RuntimeError } }
|
63
|
+
.to raise_error Verifier::Invalid
|
64
|
+
end
|
65
|
+
|
66
|
+
it "displays proper error message" do
|
67
|
+
expected_message = "Test#foo verification failed: \"foo\" not valid"
|
68
|
+
|
69
|
+
begin
|
70
|
+
subject.verify(:foo, :valid) { false }
|
71
|
+
rescue => error
|
72
|
+
expect(error.message).to eq expected_message
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when a block returns false" do
|
78
|
+
|
79
|
+
it "raises Verifier::Invalid" do
|
80
|
+
expect { subject.verify(:foo, :valid) { false } }
|
81
|
+
.to raise_error Verifier::Invalid
|
82
|
+
end
|
83
|
+
|
84
|
+
it "displays proper error message" do
|
85
|
+
expected_message = "Test#foo verification failed: \"foo\" not valid"
|
86
|
+
|
87
|
+
begin
|
88
|
+
subject.verify(:foo, :valid) { false }
|
89
|
+
rescue => error
|
90
|
+
expect(error.message).to eq expected_message
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when a block returns nil" do
|
96
|
+
|
97
|
+
it "raises Verifier::Invalid" do
|
98
|
+
expect { subject.verify(:foo, :valid) { nil } }
|
99
|
+
.to raise_error Verifier::Invalid
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when a block returns true" do
|
104
|
+
|
105
|
+
it "doesn't raise error" do
|
106
|
+
expect { subject.verify(:foo, :valid) { true } }.not_to raise_error
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when negation of a block is truthy" do
|
111
|
+
|
112
|
+
let(:null) { double :null, :! => true }
|
113
|
+
|
114
|
+
it "raises Verifier::Invalid" do
|
115
|
+
expect { subject.verify(:foo, :valid) { null } }
|
116
|
+
.to raise_error Verifier::Invalid
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when a block returns false in a variable's scope" do
|
121
|
+
|
122
|
+
it "raises Verifier::Invalid" do
|
123
|
+
expect { subject.verify(:foo, :valid) { self != "foo" } }
|
124
|
+
.to raise_error Verifier::Invalid
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when a block returns true in a variable's scope" do
|
129
|
+
|
130
|
+
it "doesn't raise error" do
|
131
|
+
expect { subject.verify(:foo, :valid) { self == "foo" } }
|
132
|
+
.not_to raise_error
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: verifier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Kozin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: extlib
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: hexx-suit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.0'
|
41
|
+
description: Variables verification.
|
42
|
+
email: andrew.kozin@gmail.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files:
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- ".yardopts"
|
49
|
+
files:
|
50
|
+
- ".metrics"
|
51
|
+
- ".rspec"
|
52
|
+
- ".yardopts"
|
53
|
+
- Guardfile
|
54
|
+
- LICENSE
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- config/metrics/STYLEGUIDE
|
58
|
+
- config/metrics/cane.yml
|
59
|
+
- config/metrics/churn.yml
|
60
|
+
- config/metrics/flay.yml
|
61
|
+
- config/metrics/metric_fu.yml
|
62
|
+
- config/metrics/pippi.yml
|
63
|
+
- config/metrics/reek.yml
|
64
|
+
- config/metrics/roodi.yml
|
65
|
+
- config/metrics/rubocop.yml
|
66
|
+
- config/metrics/saikuro.yml
|
67
|
+
- config/metrics/simplecov.yml
|
68
|
+
- config/metrics/yardstick.yml
|
69
|
+
- lib/verifier.rb
|
70
|
+
- lib/verifier/exceptions.rb
|
71
|
+
- lib/verifier/scope.rb
|
72
|
+
- lib/verifier/verification.rb
|
73
|
+
- lib/verifier/version.rb
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
- spec/verifier/invalid_spec.rb
|
76
|
+
- spec/verifier/method_fails_spec.rb
|
77
|
+
- spec/verifier/method_not_defined_spec.rb
|
78
|
+
- spec/verifier/verify_spec.rb
|
79
|
+
homepage: https://github.com/nepalez/verifier
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.1'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.2.2
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Variables verification.
|
103
|
+
test_files:
|
104
|
+
- ".rspec"
|
105
|
+
- spec/verifier/verify_spec.rb
|
106
|
+
- spec/verifier/method_fails_spec.rb
|
107
|
+
- spec/verifier/method_not_defined_spec.rb
|
108
|
+
- spec/verifier/invalid_spec.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
- Guardfile
|
111
|
+
- Rakefile
|
112
|
+
- ".metrics"
|
113
|
+
- config/metrics/cane.yml
|
114
|
+
- config/metrics/metric_fu.yml
|
115
|
+
- config/metrics/simplecov.yml
|
116
|
+
- config/metrics/yardstick.yml
|
117
|
+
- config/metrics/flay.yml
|
118
|
+
- config/metrics/rubocop.yml
|
119
|
+
- config/metrics/churn.yml
|
120
|
+
- config/metrics/saikuro.yml
|
121
|
+
- config/metrics/reek.yml
|
122
|
+
- config/metrics/roodi.yml
|
123
|
+
- config/metrics/STYLEGUIDE
|
124
|
+
- config/metrics/pippi.yml
|
125
|
+
has_rdoc:
|