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.
@@ -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
@@ -0,0 +1,5 @@
1
+ # Settings for metric_fu and its packages are collected in the `config/metrics`
2
+ # and loaded by the Hexx::Suit::Metrics::MetricFu.
3
+
4
+ require "hexx-suit"
5
+ Hexx::Suit::Metrics::MetricFu.load
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --color
@@ -0,0 +1,2 @@
1
+ --asset LICENSE
2
+ --exclude lib/**/version.rb
@@ -0,0 +1,6 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ watch "spec/tests/**/*_spec.rb"
3
+ watch("lib/verifier.rb") { "spec/tests/lib/verifier_spec.rb" }
4
+ watch("spec/spec_helper.rb") { "spec" }
5
+ watch("lib/verifier.rb") { "spec" }
6
+ end
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.
@@ -0,0 +1,126 @@
1
+ # Verifier
2
+
3
+ [![Gem Version](https://img.shields.io/gem/v/verifier.svg?style=flat)][gem]
4
+ [![Build Status](https://img.shields.io/travis/nepalez/verifier/master.svg?style=flat)][travis]
5
+ [![Dependency Status](https://img.shields.io/gemnasium/nepalez/verifier.svg?style=flat)][gemnasium]
6
+ [![Code Climate](https://img.shields.io/codeclimate/coverage/github/nepalez/verifier.svg?style=flat)][codeclimate]
7
+ [![Coverage](https://img.shields.io/coveralls/nepalez/verifier.svg?style=flat)][coveralls]
8
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](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).
@@ -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,5 @@
1
+ ---
2
+ abc_max: "10"
3
+ line_length: "80"
4
+ no_doc: "y"
5
+ no_readme: "y"
@@ -0,0 +1,6 @@
1
+ ---
2
+ ignore_files:
3
+ - spec
4
+ - config
5
+ minimum_churn_count: 0
6
+ start_date: "1 year ago"
@@ -0,0 +1,2 @@
1
+ ---
2
+ minimum_score: 5
@@ -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,3 @@
1
+ ---
2
+ checkset: basic
3
+ output: "tmp/pippi/output.log"
@@ -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,3 @@
1
+ ---
2
+ warn_cyclo: 4
3
+ error_cyclo: 6
@@ -0,0 +1,8 @@
1
+ ---
2
+ output: tmp/coverage
3
+ filters: # The list of paths to be excluded from coverage checkup
4
+ - "spec/"
5
+ - "config/"
6
+ groups: # The list of groups to be shown in the coverage report
7
+ Libraries: "lib/"
8
+ Application: "app/"
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ module Verifier
4
+ # The semantic version of the module.
5
+ # @see http://semver.org/ Semantic versioning 2.0
6
+ VERSION = "0.0.1".freeze
7
+ end # module Verifier
@@ -0,0 +1,6 @@
1
+ # Loads the RSpec test suit.
2
+ require "hexx-suit"
3
+ Hexx::Suit.load_metrics_for(self)
4
+
5
+ # Loads the gem.
6
+ require "verifier"
@@ -0,0 +1,6 @@
1
+ describe Verifier::Invalid do
2
+
3
+ it "is a RuntimeError" do
4
+ expect(described_class.superclass).to eq ::RuntimeError
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ describe Verifier::MethodFails do
2
+
3
+ it "is a RuntimeError" do
4
+ expect(described_class.superclass).to eq ::RuntimeError
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ describe Verifier::MethodNotDefined do
2
+
3
+ it "is a NameError" do
4
+ expect(described_class.superclass).to eq ::NameError
5
+ end
6
+ end
@@ -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: