ensure_it 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +332 -0
- data/Rakefile +11 -0
- data/ensure_it.gemspec +39 -0
- data/lib/ensure_it/config.rb +23 -0
- data/lib/ensure_it/ensure_array.rb +67 -0
- data/lib/ensure_it/ensure_class.rb +30 -0
- data/lib/ensure_it/ensure_float.rb +48 -0
- data/lib/ensure_it/ensure_hash.rb +22 -0
- data/lib/ensure_it/ensure_instance_of.rb +27 -0
- data/lib/ensure_it/ensure_integer.rb +89 -0
- data/lib/ensure_it/ensure_string.rb +43 -0
- data/lib/ensure_it/ensure_symbol.rb +26 -0
- data/lib/ensure_it/errors.rb +173 -0
- data/lib/ensure_it/patch.rb +17 -0
- data/lib/ensure_it/version.rb +3 -0
- data/lib/ensure_it.rb +18 -0
- data/lib/ensure_it_refines.rb +8 -0
- data/spec/integration/refines_spec.rb +37 -0
- data/spec/lib/config_spec.rb +50 -0
- data/spec/lib/ensure_array_spec.rb +75 -0
- data/spec/lib/ensure_class_spec.rb +54 -0
- data/spec/lib/ensure_float_spec.rb +65 -0
- data/spec/lib/ensure_hash_spec.rb +45 -0
- data/spec/lib/ensure_instance_of_spec.rb +49 -0
- data/spec/lib/ensure_integer_spec.rb +89 -0
- data/spec/lib/ensure_string_spec.rb +53 -0
- data/spec/lib/ensure_symbol_spec.rb +39 -0
- data/spec/lib/errors_spec.rb +124 -0
- data/spec/lib/patch_spec.rb +31 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/example_groups/ensure_it_example_group.rb +66 -0
- data/spec/support/matchers/warn_matcher.rb +30 -0
- data/spec/support/shared_examples/unmet_objects.rb +60 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: efbdf0a3bed9ded886ef7d1170937026c97921ba
|
4
|
+
data.tar.gz: 37e7605734053df525d58d23160f9e610722eb72
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 77cef5c0dda07903b845259cd3ee07e72a66f46650a741cf1dd1b5d8a05c25459423bbc8e2dfc5d0ea8df6ba9d30e74c5099aa4de1aa78ba7d59ab5cfec04a8b
|
7
|
+
data.tar.gz: 0432891707fbdbd1e4e6e1d2737040ffb1bcbec5368a8f80b4d3756544a32222b359d175af1266e4a63b8b8ca2715a3d9d90d03121e9866da63ae8e53206872d
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p353
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Алексей Овчинников
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,332 @@
|
|
1
|
+
[![Code Climate](https://codeclimate.com/github/cybernetlab/ensure_it.png)](https://codeclimate.com/github/cybernetlab/ensure_it)
|
2
|
+
[![Build Status](https://travis-ci.org/cybernetlab/ensure_it.svg?branch=master)](https://travis-ci.org/cybernetlab/ensure_it)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/cybernetlab/ensure_it/badge.png?branch=master)](https://coveralls.io/r/cybernetlab/ensure_it?branch=master)
|
4
|
+
|
5
|
+
# EnsureIt
|
6
|
+
|
7
|
+
This library provides way to check and converts local variables for every-method usage, like arguments checking.
|
8
|
+
|
9
|
+
The main goal of EnsureIt is to provide as fast executed code as it possible with simple and usable syntax.
|
10
|
+
|
11
|
+
> **Note:** this library doesn't support ruby older than `2.0.0`
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'ensure_it'
|
19
|
+
```
|
20
|
+
|
21
|
+
or for [refinements](#refinements) version:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'ensure_it', require: 'ensure_it_refines'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
```sh
|
30
|
+
$ bundle
|
31
|
+
```
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
```sh
|
36
|
+
$ gem install ensure_it
|
37
|
+
```
|
38
|
+
|
39
|
+
## Configuration
|
40
|
+
|
41
|
+
For this moment only one configuration option available - global setting of smart errors (see [Usage section](usage)):
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'ensure_it'
|
45
|
+
|
46
|
+
EnsureIt.configuration do |config|
|
47
|
+
# config.errors = :standard
|
48
|
+
config.errors = :smart
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
## Usage
|
53
|
+
|
54
|
+
EnsureIt does monkey-patching or provides refines (see [Refinements section](#refinements)) for general ruby objects with set of `ensure_*` methods. So you can call this methods with everything in ruby. Corresponding to method name it returns `nil` (or raise exception for bang version of method, that name ended with `!`) for unusual or impossible type conversions and returns object of ensured type if conversion is possible.
|
55
|
+
|
56
|
+
For example `ensure_symbol` method returns symbol itself for Symbols, converted to symbol value for Strings and nil for all other. Same way `ensure_symbol!` returns symbol for String and Symbol, and raises exception for all other.
|
57
|
+
|
58
|
+
The special thing, that EnsureIt can do (and do it by default) is smart error messages in bang methods. In most cases, EnsureIt guesses right context in wich `ensure_*` method called and froms more informative message. It recognizes name of local variable if method called for variable like `my_var.ensure_symbol`, argument name, if variable is argument of method and method calls itself like `'some_string'.to_sym.ensure_symbol` - so `ensure_symbol` called on result of `to_sym` method. You can disable this functionality at all (see [Configuration section](configuration)) or override globally configuration for any method call by `smart` option like this `:symbol.ensure_symbol(smart: true)` or `:symbol.ensure_symbol(smart: false)`. In any way, this `:smart` errors doesn't affect execution speed because the analyzing block of code executed only on exception - not on every `ensure_*` call.
|
59
|
+
|
60
|
+
For example, following code
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
def awesome(arg)
|
64
|
+
arg = arg.ensure_symbol!
|
65
|
+
end
|
66
|
+
|
67
|
+
awesome(0)
|
68
|
+
```
|
69
|
+
|
70
|
+
will produce error message `argument 'arg' of 'awesome' method should be a Symbol or a String`.
|
71
|
+
|
72
|
+
For bang methods you can override error class with `error` option and error message with `message` option. In message you can specify a placeholder for subject as `#{subject}`, just subject name as `#{name}` and method name as `#{method_name}`. For example:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
def awesome(arg)
|
76
|
+
arg = arg.ensure_symbol!(
|
77
|
+
error: ArgumentError,
|
78
|
+
message: 'it\'s bad that #{subject} with name #{name} is not a symbol.' \
|
79
|
+
' Raised by #{method_name}'
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
awesome(0)
|
84
|
+
```
|
85
|
+
|
86
|
+
will produce ArgumentError with message `it's unusual that 'arg' of 'awesome' method with name arg is not a symbol. Raised in ensure_symbol!`.
|
87
|
+
|
88
|
+
### ensure_symbol, ensure_symbol!
|
89
|
+
|
90
|
+
Returns self for Symbol, converted value for String, nil (or raise) for other:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
:test.ensure_symbol # => :test
|
94
|
+
'test'.ensure_symbol # => :test
|
95
|
+
100.ensure_symbol # => nil
|
96
|
+
```
|
97
|
+
|
98
|
+
### ensure_string, ensure_string!
|
99
|
+
|
100
|
+
By default, returns self for String, converted value for Symbol and nil (or raise) for other. With `numbers: true` option returns number, converted to string for Numeric and Rational objects:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
:test.ensure_string # => 'test'
|
104
|
+
'test'.ensure_string # => 'test'
|
105
|
+
100.ensure_string # => nil
|
106
|
+
100.ensure_string(numbers: true) # => '100'
|
107
|
+
```
|
108
|
+
|
109
|
+
### ensure_integer, ensure_integer!
|
110
|
+
|
111
|
+
By default, returns Fixnum or Bignum for Integer itself, rounded value for Float, converted Strings with strong check ('123test' will return nil) and nil (or raise) for other. With `boolean: true` option returns `0` for `false` and `1` for `true`, with `boolean: Fixnum-value` returns `0` for false and specified value for true:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
:test.ensure_integer # => nil
|
115
|
+
:'100'.ensure_integer # => nil
|
116
|
+
'100'.ensure_integer # => 100
|
117
|
+
'1_200'.ensure_integer # => 1200
|
118
|
+
'0x0a'.ensure_integer # => 10
|
119
|
+
'0b100'.ensure_integer # => 4
|
120
|
+
'010'.ensure_integer # => 10 !!! Octals are not accepted by default,
|
121
|
+
# use octal: true for this
|
122
|
+
'010'.ensure_integer(octal: true) # => 8
|
123
|
+
100.4.ensure_integer # => 100
|
124
|
+
100.5.ensure_integer # => 101
|
125
|
+
true.ensure_integer # => nil
|
126
|
+
true.ensure_integer(boolean: true) # => 1
|
127
|
+
true.ensure_integer(boolean: 1000) # => 1000
|
128
|
+
```
|
129
|
+
|
130
|
+
Be aware that octal numbers, beginning with `0` is not accepted by default, because its usage is rarely, that more common situation to have leading zeroes in decimal numbers while loading data from something like csv file. To recognize zero-strated numbers as octals, use `octal: true` option.
|
131
|
+
|
132
|
+
### ensure_float, ensure_float!
|
133
|
+
|
134
|
+
By default, returns Float for Numerics, converted Strings with strong check ('123test' will return nil) and nil (or raise) for other:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
:test.ensure_float # => nil
|
138
|
+
:'100'.ensure_float # => nil
|
139
|
+
'100'.ensure_float # => 100.0
|
140
|
+
'.1'.ensure_float # => 0.1
|
141
|
+
'1e3'.ensure_float # => 1000.0
|
142
|
+
100.ensure_float # => 100.0
|
143
|
+
100.5.ensure_float # => 100.5
|
144
|
+
('1/2').to_r.ensure_float # => 0.5
|
145
|
+
true.ensure_float # => nil
|
146
|
+
```
|
147
|
+
|
148
|
+
### ensure_array, ensure_array!
|
149
|
+
|
150
|
+
By default, returns Array only for Array itself and **empty** array (not nil) for others. This method have many usefull optioins. Just list it in example:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
[1, nil, 2].ensure_array # => [1, nil, 2]
|
154
|
+
true.ensure_array # => []
|
155
|
+
true.ensure_array(wrong: nil) # => nil
|
156
|
+
[1, nil, 2].ensure_array(compact: true) # => [1, 2]
|
157
|
+
[1, [2, 3], 4].ensure_array(flatten: true) # => [1, 2, 3, 4]
|
158
|
+
[1, [5, 6], 4].ensure_array(flatten: true, sorted: true) # => [1, 4, 5, 6]
|
159
|
+
[1, [5, 6], 4].ensure_array(flatten: true, sorted: :desc) # => [6, 5, 4, 1]
|
160
|
+
[1, [5, 6], 4].ensure_array(flatten: true, ordered: true) # => alias to sorted
|
161
|
+
arr = ['some', nil, :value]
|
162
|
+
arr.ensure_array(:ensure_symbol, compact: true) # => [:some, :value]
|
163
|
+
arr.ensure_array(:ensure_symbol!, compact: true) # => raise on second element
|
164
|
+
arr = ['some', :value]
|
165
|
+
arr.ensure_array(:to_s) # => ['some', 'value'] standard methods can be used
|
166
|
+
arr.ensure_array(:ensure_string, :to_sym) # => [:some, :value] you can chain methods
|
167
|
+
```
|
168
|
+
|
169
|
+
Simple usage example:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
require 'ensure_it'
|
173
|
+
|
174
|
+
class Awesome
|
175
|
+
def self.define_getters(*args)
|
176
|
+
args.ensure_array(:ensure_symbol, compact: true).each do |n|
|
177
|
+
define_method(n) { instance_variable_get("@#{n}") }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
Awesome.define_getters(:one, 'two', nil, false, Object, :three)
|
183
|
+
Awesome.methods(false) #=> [:one, :two, :three]
|
184
|
+
```
|
185
|
+
|
186
|
+
### ensure_hash, ensure_hash!
|
187
|
+
|
188
|
+
Returns Hash only for Hash itself and **empty** hash (not nil) for others. Symbolizes keys with `symbolize_keys: true` option:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
{some: 0, 'key' => 1}.ensure_hash # => {some: 0, 'key' => 1}
|
192
|
+
0.ensure_hash # => {}
|
193
|
+
0.ensure_hash(wrong: nil) # => nil
|
194
|
+
{some: 0, 'key' => 1}.ensure_hash(symbolize_keys: true) # => {some: 0, key: 0}
|
195
|
+
```
|
196
|
+
|
197
|
+
### ensure_instance_of, ensure_instance_of!
|
198
|
+
|
199
|
+
Returns self only if it instance of specified class or nil (or raise) elsewhere:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
10.ensure_instance_of(Fixnum) # => 10
|
203
|
+
10.0.ensure_instance_of(Fixnum) # => nil
|
204
|
+
10.0.ensure_instance_of(Fixnum, wrong: -1) # => -1
|
205
|
+
```
|
206
|
+
|
207
|
+
### ensure_class, ensure_class!
|
208
|
+
|
209
|
+
Returns self only if it is a class and optionally have specified ancestors or nil (or raise) elsewhere:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
10.ensure_class # => nil
|
213
|
+
String.ensure_class # => String
|
214
|
+
Fixnum.ensure_class(Integer) # => Fixnum
|
215
|
+
Float.ensure_class(Integer) # => nil
|
216
|
+
|
217
|
+
module CustomModule; end
|
218
|
+
class CustomArray < Array;
|
219
|
+
include CustomModule
|
220
|
+
end
|
221
|
+
CustomArray.ensure_class(Enumerable, CustomModule) # => CustomArray
|
222
|
+
Array.ensure_class(Enumerable, CustomModule) # => nil
|
223
|
+
Array.ensure_class(Enumerable) # => Array
|
224
|
+
```
|
225
|
+
|
226
|
+
### Common options for all non-bang methods
|
227
|
+
|
228
|
+
|option|possible values|meaning|
|
229
|
+
|------|---------------|-------|
|
230
|
+
|`:wrong`|any|if present then will be used as wrong value instead of default `nil`|
|
231
|
+
|
232
|
+
### Common options for all bang methods
|
233
|
+
|
234
|
+
|option|possible values|meaning|
|
235
|
+
|------|---------------|-------|
|
236
|
+
|`:message`|`String`|custom error message|
|
237
|
+
|`:error`|`Exception` class|custom error class|
|
238
|
+
|`:smart`|`true` or `false`|use smart errors|
|
239
|
+
|
240
|
+
## Refinements
|
241
|
+
|
242
|
+
Since ruby `2.0.0` [refinements](http://www.ruby-doc.org/core-2.1.1/doc/syntax/refinements_rdoc.html) mechanism intorduced and was experimental till `2.1.0`. Starting from `2.1.0` you can use it without warnings and in module and class scope.
|
243
|
+
|
244
|
+
EnsureIt is fully tested and working with refinements. But not by default and not for ruby `< 2.1.0`. To use refined version of EnsureIt (with zero-monkey-pathing) just require `ensure_it_refines` instead of `ensure_it`. If you use bundler, you can do it, by specifying `require: 'ensure_it_refines'` option for `gem 'ensure_it'` in your `Gemfile`:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
gem 'ensure_it', require: 'ensure_it_refines'
|
248
|
+
```
|
249
|
+
|
250
|
+
Or without bundler:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
# In you code initialization
|
254
|
+
require 'ensure_it_refines'
|
255
|
+
```
|
256
|
+
|
257
|
+
Then activate EnsureIt refines by `using EnsureIt` in needed scope:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
require 'ensure_it_refines'
|
261
|
+
|
262
|
+
class AwesomeClass
|
263
|
+
using EnsureIt
|
264
|
+
|
265
|
+
def awesome_method(arg)
|
266
|
+
arg = arg.ensure_symbol!
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
AwesomeClass.new.awesome_method(0) # => raises EnsureIt::Error with message
|
271
|
+
# "argument 'arg' of 'awesome_method'
|
272
|
+
# method should be a Symbol or a String"
|
273
|
+
```
|
274
|
+
|
275
|
+
Please read carefully [refinements](http://www.ruby-doc.org/core-2.1.1/doc/syntax/refinements_rdoc.html) documentation before using refined EnsureIt. Don't forget to call `using EnsureIt` in every file (not class or method if your class or method placed in many files) you need it.
|
276
|
+
|
277
|
+
## Changelog
|
278
|
+
|
279
|
+
`0.1.0`
|
280
|
+
* set of methods for beginning:
|
281
|
+
- ensure_symbol
|
282
|
+
- ensure_string
|
283
|
+
- ensure_integer
|
284
|
+
- ensure_float
|
285
|
+
- ensure_array
|
286
|
+
- ensure_hash
|
287
|
+
- ensure_instance_of
|
288
|
+
- ensure_class
|
289
|
+
|
290
|
+
## Versions
|
291
|
+
|
292
|
+
`0.x.x` is pre-release. After some testing in real applications, `1.x.x` as first release will be started.
|
293
|
+
|
294
|
+
## Todo
|
295
|
+
|
296
|
+
* enlarge method set
|
297
|
+
* enlarge number of options for arrays and hashes
|
298
|
+
* block processing for arrays and hashes
|
299
|
+
* benchmarking and profiling
|
300
|
+
* custom extending functionality support
|
301
|
+
|
302
|
+
## Contributing
|
303
|
+
|
304
|
+
1. Fork it ( http://github.com/<my-github-username>/skeleton/fork )
|
305
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
306
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
307
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
308
|
+
5. Create new Pull Request
|
309
|
+
|
310
|
+
# License
|
311
|
+
|
312
|
+
The MIT License (MIT)
|
313
|
+
|
314
|
+
Copyright (c) 2014 Alexey Ovchinnikov
|
315
|
+
|
316
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
317
|
+
of this software and associated documentation files (the "Software"), to deal
|
318
|
+
in the Software without restriction, including without limitation the rights
|
319
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
320
|
+
copies of the Software, and to permit persons to whom the Software is
|
321
|
+
furnished to do so, subject to the following conditions:
|
322
|
+
|
323
|
+
The above copyright notice and this permission notice shall be included in
|
324
|
+
all copies or substantial portions of the Software.
|
325
|
+
|
326
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
327
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
328
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
329
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
330
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
331
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
332
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require File.join %w(bundler gem_tasks)
|
8
|
+
require File.join %w(rspec core rake_task)
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
task :default => :spec
|
data/ensure_it.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path(File.join('..', 'lib'), __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require File.join %w(ensure_it version)
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.required_ruby_version = '>= 2.0.0'
|
8
|
+
|
9
|
+
spec.name = 'ensure_it'
|
10
|
+
spec.version = EnsureIt::VERSION
|
11
|
+
spec.authors = ['Alexey Ovchinnikov']
|
12
|
+
spec.email = ['alexiss@cybernetlab.ru', 'alexey.ovchinnikov@yandex.ru']
|
13
|
+
spec.summary = %q{Provides variables and arguments parsing}
|
14
|
+
spec.description = %q{Main goal of project is to provide fastest way to
|
15
|
+
every-method arguments and variables checks with
|
16
|
+
minimal coding requirements}
|
17
|
+
spec.summary = <<-EOL.gsub(/^\s+\|/, '')
|
18
|
+
|This library provides way to check and converts local variables for
|
19
|
+
|every-method usage, like arguments checking.
|
20
|
+
|The main goal of EnsureIt is to provide as fast executed code as it
|
21
|
+
|possible with simple and usable syntax.
|
22
|
+
EOL
|
23
|
+
spec.homepage = 'http://github.com/cybernetlab/ensure_it'
|
24
|
+
spec.license = 'MIT'
|
25
|
+
spec.metadata = {
|
26
|
+
'issue_tracker' => 'https://github.com/cybernetlab/ensure_it/issues'
|
27
|
+
}
|
28
|
+
|
29
|
+
spec.files = `git ls-files`.split($/)
|
30
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
31
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
|
34
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.1'
|
36
|
+
spec.add_development_dependency 'redcarpet', '~> 3.1'
|
37
|
+
spec.add_development_dependency 'yard', '~> 0.8'
|
38
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
module Config
|
3
|
+
ERRORS = %i(smart standard)
|
4
|
+
|
5
|
+
def self.errors(value = nil)
|
6
|
+
value.nil? ? @errors ||= ERRORS.first : self.errors = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.errors=(value)
|
10
|
+
value = value.to_sym if value.is_a?(String)
|
11
|
+
@errors = ERRORS.include?(value) ? value : ERRORS.first
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.config
|
16
|
+
Config
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
yield(Config) if block_given?
|
21
|
+
Config
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
patch Object do
|
3
|
+
def ensure_array(*args, **opts)
|
4
|
+
opts.key?(:wrong) ? opts[:wrong] : []
|
5
|
+
end
|
6
|
+
|
7
|
+
def ensure_array!(*args, **opts)
|
8
|
+
opts[:message] ||= '#{subject} should be an Array'
|
9
|
+
EnsureIt.raise_error(:ensure_array!, **opts)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
patch Array do
|
14
|
+
using EnsureIt if ENSURE_IT_REFINES
|
15
|
+
|
16
|
+
if ENSURE_IT_REFINES
|
17
|
+
def ensure_array(*args, **opts)
|
18
|
+
arr = self
|
19
|
+
args.each do |arg|
|
20
|
+
arg = arg.ensure_symbol || next
|
21
|
+
arr =
|
22
|
+
if arg.to_s.index('ensure_') == 0
|
23
|
+
case arg
|
24
|
+
when :ensure_symbol then map { |x| x.ensure_symbol }
|
25
|
+
when :ensure_symbol! then map { |x| x.ensure_symbol! }
|
26
|
+
when :ensure_string then map { |x| x.ensure_string }
|
27
|
+
when :ensure_string! then map { |x| x.ensure_string! }
|
28
|
+
when :ensure_integer then map { |x| x.ensure_integer }
|
29
|
+
when :ensure_integer! then map { |x| x.ensure_integer! }
|
30
|
+
when :ensure_float then map { |x| x.ensure_float }
|
31
|
+
when :ensure_float! then map { |x| x.ensure_float! }
|
32
|
+
when :ensure_array then map { |x| x.ensure_array }
|
33
|
+
when :ensure_array! then map { |x| x.ensure_array! }
|
34
|
+
end
|
35
|
+
else
|
36
|
+
arr.map(&arg)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
return arr if opts.empty?
|
40
|
+
arr = arr.map { |x| x } if arr == self
|
41
|
+
arr.flatten! if opts[:flatten] == true
|
42
|
+
opts[:sorted] ||= opts.delete(:ordered) if opts.key?(:ordered)
|
43
|
+
arr.sort! if opts.key?(:sorted)
|
44
|
+
arr.reverse! if opts[:sorted].ensure_symbol == :desc
|
45
|
+
arr.compact! if opts[:compact] == true
|
46
|
+
arr
|
47
|
+
end
|
48
|
+
else
|
49
|
+
def ensure_array(*args, **opts)
|
50
|
+
arr = self
|
51
|
+
args.each do |arg|
|
52
|
+
arg = arg.ensure_symbol || next
|
53
|
+
arr = arr.map(&arg)
|
54
|
+
end
|
55
|
+
return arr if opts.empty?
|
56
|
+
arr = arr.map { |x| x } if arr == self
|
57
|
+
arr.flatten! if opts[:flatten] == true
|
58
|
+
opts[:sorted] ||= opts.delete(:ordered) if opts.key?(:ordered)
|
59
|
+
arr.sort! if opts.key?(:sorted)
|
60
|
+
arr.reverse! if opts[:sorted].ensure_symbol == :desc
|
61
|
+
arr.compact! if opts[:compact] == true
|
62
|
+
arr
|
63
|
+
end
|
64
|
+
end
|
65
|
+
alias_method :ensure_array!, :ensure_array
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
patch Object do
|
3
|
+
def ensure_class(*args, **opts)
|
4
|
+
opts.key?(:wrong) ? opts[:wrong] : nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def ensure_class!(*args, **opts)
|
8
|
+
opts[:message] ||= '#{subject} should be a class'
|
9
|
+
EnsureIt.raise_error(:ensure_class!, **opts)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
patch Class do
|
14
|
+
using EnsureIt if ENSURE_IT_REFINES
|
15
|
+
|
16
|
+
def ensure_class(*args, **opts)
|
17
|
+
args.select! { |x| x.is_a?(Module) }
|
18
|
+
args.all? { |x| self <= x } ? self : super(**opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_class!(*args, **opts)
|
22
|
+
args.select! { |x| x.is_a?(Module) }
|
23
|
+
return self if args.all? { |x| self <= x }
|
24
|
+
args = args.map!(&:name).join(', ')
|
25
|
+
opts[:message] ||=
|
26
|
+
"\#{subject} should subclass or extend all of ['#{args}']"
|
27
|
+
EnsureIt.raise_error(:ensure_class!, **opts)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
FLOAT_REGEXP = /\A[+\-]?(?:\d+(?:\.\d*)?|\d*\.\d+)(?:[eE][+\-]?\d+)?\z/
|
3
|
+
|
4
|
+
patch Object do
|
5
|
+
def ensure_float(**opts)
|
6
|
+
opts.key?(:wrong) ? opts[:wrong] : nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def ensure_float!(**opts)
|
10
|
+
opts[:message] ||= '#{subject} should be a float or be able' \
|
11
|
+
' to convert to it'
|
12
|
+
EnsureIt.raise_error(:ensure_float!, **opts)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
patch String do
|
17
|
+
using EnsureIt if ENSURE_IT_REFINES
|
18
|
+
|
19
|
+
def ensure_float(**opts)
|
20
|
+
self =~ FLOAT_REGEXP ? to_f : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def ensure_float!(**opts)
|
24
|
+
ensure_float(**opts) || super(**opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
patch Integer do
|
29
|
+
def ensure_float(**opts)
|
30
|
+
to_f
|
31
|
+
end
|
32
|
+
alias_method :ensure_float!, :ensure_float
|
33
|
+
end
|
34
|
+
|
35
|
+
patch Float do
|
36
|
+
def ensure_float(**opts)
|
37
|
+
self
|
38
|
+
end
|
39
|
+
alias_method :ensure_float!, :ensure_float
|
40
|
+
end
|
41
|
+
|
42
|
+
patch Rational do
|
43
|
+
def ensure_float(**opts)
|
44
|
+
to_f
|
45
|
+
end
|
46
|
+
alias_method :ensure_float!, :ensure_float
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
patch Object do
|
3
|
+
def ensure_hash(*args, **opts)
|
4
|
+
opts.key?(:wrong) ? opts[:wrong] : {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def ensure_hash!(*args, **opts)
|
8
|
+
opts[:message] ||= '#{subject} should be a Hash'
|
9
|
+
EnsureIt.raise_error(:ensure_hash!, **opts)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
patch Hash do
|
14
|
+
using EnsureIt if ENSURE_IT_REFINES
|
15
|
+
|
16
|
+
def ensure_hash(*args, **opts)
|
17
|
+
return self if opts[:symbolize_keys] != true
|
18
|
+
Hash[map { |k, v| [k.ensure_symbol, v] }.reject { |x| x[0].nil? }]
|
19
|
+
end
|
20
|
+
alias_method :ensure_hash!, :ensure_hash
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module EnsureIt
|
2
|
+
patch Object do
|
3
|
+
def ensure_instance_of(klass, **opts)
|
4
|
+
unless klass.is_a?(Class)
|
5
|
+
fail(
|
6
|
+
ArgumentError,
|
7
|
+
'Wrong class argument for #ensure_instance_of specified'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
return self if is_a?(klass)
|
11
|
+
opts.key?(:wrong) ? opts[:wrong] : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def ensure_instance_of!(klass, **opts)
|
15
|
+
unless klass.is_a?(Class)
|
16
|
+
fail(
|
17
|
+
ArgumentError,
|
18
|
+
'Wrong class argument for #ensure_instance_of specified'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
return self if is_a?(klass)
|
22
|
+
opts[:message] ||=
|
23
|
+
"\#{subject} should be an instance of '#{klass.name}' class"
|
24
|
+
EnsureIt.raise_error(:ensure_instance_of!, **opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|