a_types 1.0.0
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/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +148 -0
- data/Rakefile +6 -0
- data/a_types.gemspec +29 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/a_types.rb +10 -0
- data/lib/a_types/all.rb +2 -0
- data/lib/a_types/core_ext/all.rb +3 -0
- data/lib/a_types/core_ext/boolean.rb +115 -0
- data/lib/a_types/core_ext/enumerable.rb +17 -0
- data/lib/a_types/core_ext/numeric.rb +74 -0
- data/lib/a_types/decorators/all.rb +3 -0
- data/lib/a_types/decorators/boolean_wrap.rb +185 -0
- data/lib/a_types/decorators/enuemrable_wrap.rb +24 -0
- data/lib/a_types/decorators/numeric_wrap.rb +67 -0
- data/lib/a_types/decorators/wrapper.rb +9 -0
- data/lib/a_types/support/matchers.rb +10 -0
- data/lib/a_types/version.rb +5 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 033d98d342a101aa3715d8da98b9b6f9c3740ca0
|
4
|
+
data.tar.gz: 24a52dba07f7c4fc9a0ecc319956899de80f5551
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 58b046a0a77041f24f3133aa377ae336f73e9e13e2204737e9bf557c3f34c861099d038d73122652da38f71ef21eb6de1bdbb8c0029ce642c0773726d05b7468
|
7
|
+
data.tar.gz: d04f7115599e89ada7d07d536c6e081e592161b2e27f54247c713072998e816b6aee6473062feaf7a7574ce62b7678931e0c0264b4bceaee7637d1169fba4e6d
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Yves Komenda
|
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,148 @@
|
|
1
|
+
[](https://codeclimate.com/github/Dervol03/a_types)
|
2
|
+
[](https://travis-ci.org/Dervol03/a_types)
|
3
|
+
|
4
|
+
# ATypes (Advanced Data Types)
|
5
|
+
|
6
|
+
This gem provides some convenience methods to Ruby's basic data types which
|
7
|
+
are not present in ActiveSupport and especially offers some valuable Boolean
|
8
|
+
interpretation to Ruby's data types.
|
9
|
+
|
10
|
+
The gem comes in two flavors:
|
11
|
+
- core extensions, for those who prefer the handier addition of methods and
|
12
|
+
are sure they won't collide with others in their projects.
|
13
|
+
- decorators, for those who prefer to use the decorator pattern and prefer
|
14
|
+
to be really prudent about possible collisions in their project (i.e.
|
15
|
+
because they already use ActiveSupport and don't to risk it on version
|
16
|
+
updates)
|
17
|
+
|
18
|
+
You may also load both flavors, if you like, they don't collide.
|
19
|
+
|
20
|
+
## Why another gem for advanced types?
|
21
|
+
|
22
|
+
While this gem has been inspired by others, like the [boolean
|
23
|
+
gem](https://rubygems.org/gems/boolean), these gems either have not been
|
24
|
+
updated for a very long time, don't go far enough or simply don't behave
|
25
|
+
really consistent in what they try to achieve.
|
26
|
+
|
27
|
+
Additionally, they often only provide logic for a single data type, which
|
28
|
+
tends to bloat one's Gemfile. Therefore, this gem unites different ideas, but
|
29
|
+
allow you to only load what you really want to use. See the [only take what
|
30
|
+
you need](#only-take-what-you-need) section.
|
31
|
+
|
32
|
+
|
33
|
+
## Installation
|
34
|
+
|
35
|
+
Add this line to your application's Gemfile:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
gem 'a_types'
|
39
|
+
```
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
|
43
|
+
$ bundle
|
44
|
+
|
45
|
+
Or install it yourself as:
|
46
|
+
|
47
|
+
$ gem install a_types
|
48
|
+
|
49
|
+
## Only take what you need
|
50
|
+
|
51
|
+
Similar to ActiveSupport, you won't get anything from simply requiring the
|
52
|
+
gem in your code.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
require 'a_types'
|
56
|
+
```
|
57
|
+
|
58
|
+
You have to specify which parts you wish to include in your project. Let's
|
59
|
+
assume you prefer the core extensions, then you may use following lines:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
|
63
|
+
require 'a_types/core_ext/boolean' # => loads Boolean extensions
|
64
|
+
require 'a_types/core_ext/enumerable' # => loads Enumarable extensions
|
65
|
+
require 'a_types/core_ext/all' # => loads all core extentions
|
66
|
+
```
|
67
|
+
|
68
|
+
You are more the decorator kind? This gem has exactly what you want:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
|
72
|
+
require 'a_types/decorators/boolean' # => loads ATypes::Boolean decorator
|
73
|
+
require 'a_types/decorators/array' # => loads ATypes::Array decorator
|
74
|
+
require 'a_types/decorators/all' # => loads all available decorators
|
75
|
+
```
|
76
|
+
|
77
|
+
You may also simply load everything in the gem, getting the core extension
|
78
|
+
AND the decorators:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
require 'a_types/all'
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
Feel free to browse the list of files which you may require on the [project's
|
86
|
+
homepage](https://github.com/Dervol03/a_types/tree/master/lib).
|
87
|
+
|
88
|
+
You may also find the documentation of each file there or on [rubygems.org]
|
89
|
+
(https://rubygems.org/gems/a_types).
|
90
|
+
|
91
|
+
|
92
|
+
## Examples
|
93
|
+
|
94
|
+
### Core extension
|
95
|
+
|
96
|
+
Loading the boolean extension will provide a `#to_bool` to any object.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
|
100
|
+
require 'a_types/core_ext/boolean'
|
101
|
+
|
102
|
+
'yes'.to_bool # => true
|
103
|
+
'not positive'.to_bool! # => false
|
104
|
+
-1.to_bool # => false
|
105
|
+
3.to_bool # => true
|
106
|
+
```
|
107
|
+
|
108
|
+
### Decorators
|
109
|
+
|
110
|
+
Loading the boolean decorator instead will provide a `Boolean` decorator
|
111
|
+
class. It provides an interpretation of truth to any provided object,
|
112
|
+
preserving its original behavior by delegation, as well.
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
|
116
|
+
require 'a_types/decorators/boolean'
|
117
|
+
|
118
|
+
b = ATypes::Boolean.new('yes')
|
119
|
+
b.content # => 'yes'
|
120
|
+
b.size # => 3
|
121
|
+
|
122
|
+
b.to_bool # => true
|
123
|
+
b.true? # => true
|
124
|
+
b.truthy? # => true
|
125
|
+
|
126
|
+
b2 = ATypes::Boolean.new('false')
|
127
|
+
b2.to_bool # => false
|
128
|
+
b2.true? # => falsse
|
129
|
+
b3.truthy? # => true
|
130
|
+
b2.falsey? # => false
|
131
|
+
|
132
|
+
bnil = ATypes::Boolean.new(nil)
|
133
|
+
bnil.to_bool # => false
|
134
|
+
bnil.true? # => false
|
135
|
+
bnil.truthy? # => false
|
136
|
+
bnil.falsey? # => true
|
137
|
+
|
138
|
+
```
|
139
|
+
|
140
|
+
## Contributing
|
141
|
+
|
142
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Dervol03/a_types.
|
143
|
+
|
144
|
+
|
145
|
+
## License
|
146
|
+
|
147
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
148
|
+
|
data/Rakefile
ADDED
data/a_types.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'a_types/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'a_types'
|
8
|
+
spec.version = ATypes::VERSION
|
9
|
+
spec.authors = ['Yves Komenda']
|
10
|
+
spec.email = ['b_d_v@web.de']
|
11
|
+
|
12
|
+
spec.summary = "Provides advanced versions of Ruby's basic data types"
|
13
|
+
spec.description = "Provides advanced versions of Ruby's basic data types"
|
14
|
+
spec.homepage = 'https://github.com/Dervol03/a_types'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(spec)/})
|
19
|
+
end
|
20
|
+
spec.bindir = 'bin'
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.11'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.36'
|
29
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'a_types.rb'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'pry'
|
14
|
+
Pry.start
|
data/bin/setup
ADDED
data/lib/a_types.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'a_types/version'
|
2
|
+
|
3
|
+
support_dir = File.join(__dir__, 'a_types/support')
|
4
|
+
Dir[File.join(support_dir, '/**/*.rb')].each do |support_file|
|
5
|
+
require support_file
|
6
|
+
end
|
7
|
+
|
8
|
+
# Provides different convenience decorators following the decorator pattern.
|
9
|
+
module ATypes
|
10
|
+
end
|
data/lib/a_types/all.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# This file adds the #to_bool method to numerous default classes of ruby,
|
2
|
+
# providing a more convenient of boolean handling to them. There are special
|
3
|
+
# cases for descendents of String and Numeric, all other objects will simply
|
4
|
+
# return their truthy-value according to Ruby's interpretation of truth.
|
5
|
+
|
6
|
+
|
7
|
+
# Adds #to_bool and #to_bool!
|
8
|
+
class Numeric
|
9
|
+
# Interprets this Numeric to a boolean value.
|
10
|
+
#
|
11
|
+
# @return [true, false] true if this is > 0, false otherwise.
|
12
|
+
def to_bool
|
13
|
+
self > 0 ? true : false
|
14
|
+
end
|
15
|
+
alias to_b to_bool
|
16
|
+
alias to_bool! to_bool
|
17
|
+
alias to_b! to_bool
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Adds #to_bool and #to_bool!
|
22
|
+
class String
|
23
|
+
# Converts this String to a boolean value.
|
24
|
+
# - Single characters are converted to _true_ if they are part of the set
|
25
|
+
# ['y', 'Y', '1']
|
26
|
+
#
|
27
|
+
# - Multiple characters are converted to _true_ if they are part of the set
|
28
|
+
# ['yes', 'Yes', 'YES', 'true', 'True', 'TRUE']
|
29
|
+
#
|
30
|
+
# - In any other case, the result will be false.
|
31
|
+
#
|
32
|
+
# @return [true, false] depending on the content.
|
33
|
+
def to_bool
|
34
|
+
%w(y Y 1 yes Yes YES true True TRUE).include?(self)
|
35
|
+
end
|
36
|
+
alias to_b to_bool
|
37
|
+
|
38
|
+
|
39
|
+
# Converts this String to a boolean value.
|
40
|
+
# - Single characters are converted to true if they are part of the set
|
41
|
+
# ['y', 'Y', '1']
|
42
|
+
#
|
43
|
+
# - Single characters are converted to _false_ if they are part of the set
|
44
|
+
# ['n', 'N', '0', '']
|
45
|
+
#
|
46
|
+
# - Multiple characters are converted to _true_ if they are part of the set
|
47
|
+
# ['yes', 'Yes', 'YES', 'true', 'True', 'TRUE']
|
48
|
+
#
|
49
|
+
# - Multiple characters are converted to _false_ if they are part of the set
|
50
|
+
# ['no', 'No', 'NO', 'false', 'False', 'FALSE']
|
51
|
+
#
|
52
|
+
# - In any other case, an ArgumentError will be raised.
|
53
|
+
#
|
54
|
+
# @return [true, false] depending on the content.
|
55
|
+
# @raise [ArgumentError] if this String is no real boolean value.
|
56
|
+
def to_bool!
|
57
|
+
return true if %w(y Y 1 yes Yes YES true True TRUE).include?(self)
|
58
|
+
|
59
|
+
negative = ['n', 'N', '0', 'no', 'No', 'NO', 'false', 'False', 'FALSE', '']
|
60
|
+
return false if negative.include?(self)
|
61
|
+
|
62
|
+
fail ArgumentError, "#{self} can't be interpreted as boolean!"
|
63
|
+
end
|
64
|
+
alias to_b! to_bool!
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Adds #to_bool and #to_bool!
|
69
|
+
class Object
|
70
|
+
# @return [true] respecting the Ruby way.
|
71
|
+
def to_bool
|
72
|
+
!nil?
|
73
|
+
end
|
74
|
+
alias to_b to_bool
|
75
|
+
alias to_bool! to_bool
|
76
|
+
alias to_b! to_bool
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
# Adds #to_bool and #to_bool!
|
82
|
+
class TrueClass
|
83
|
+
# @return [true] respecting the Ruby way.
|
84
|
+
def to_bool
|
85
|
+
self
|
86
|
+
end
|
87
|
+
alias to_b to_bool
|
88
|
+
alias to_bool! to_bool
|
89
|
+
alias to_b! to_bool
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Adds #to_bool and #to_bool!
|
94
|
+
class FalseClass
|
95
|
+
# @return [false] respecting the Ruby way.
|
96
|
+
def to_bool
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
alias to_b to_bool
|
101
|
+
alias to_bool! to_bool
|
102
|
+
alias to_b! to_bool
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Adds a Boolean cast method.
|
107
|
+
module Kernel
|
108
|
+
# Casts the given object to its boolean representation.
|
109
|
+
#
|
110
|
+
# @param [Object] obj_to_cast to be cast.
|
111
|
+
# @return [true, false] depending on the object.
|
112
|
+
def Boolean(obj_to_cast)
|
113
|
+
obj_to_cast.to_bool
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Adds #blank? if not already defined and #filled? as opposite method.
|
2
|
+
class Object
|
3
|
+
unless method_defined?(:blank?)
|
4
|
+
# Checks whether the object is nil or has no content.
|
5
|
+
#
|
6
|
+
# @return [true, false] depending on whether it is nil or empty.
|
7
|
+
def blank?
|
8
|
+
respond_to?(:empty?) ? empty? : nil?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Checks whether the object has any content.
|
13
|
+
# @return [true, false] depending on whether any content is present.
|
14
|
+
def filled?
|
15
|
+
!blank?
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Provides convenience methods to convert objects into number representations
|
2
|
+
# . Most prominently #to_num method.
|
3
|
+
|
4
|
+
# Numeric additions.
|
5
|
+
class Object
|
6
|
+
# @return nil
|
7
|
+
def to_num
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end # Object
|
11
|
+
|
12
|
+
|
13
|
+
# Numeric Additions.
|
14
|
+
class Numeric
|
15
|
+
# Returns itself.
|
16
|
+
#
|
17
|
+
# @return [Numeric] itself.
|
18
|
+
def to_num
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end # Numeric
|
22
|
+
|
23
|
+
|
24
|
+
# Numeric Additions.
|
25
|
+
class String
|
26
|
+
# Will convert any string with a valid number into the correct type (Fixnum
|
27
|
+
# or Float). If this String does not contain a valid number, nil will be
|
28
|
+
# returned.
|
29
|
+
#
|
30
|
+
# @return [Numeric, nil] depending on the value of this String.
|
31
|
+
def to_num
|
32
|
+
if self =~ /^-?\d+$/
|
33
|
+
to_i
|
34
|
+
elsif self =~ /^-?\d+[,.]\d+$/
|
35
|
+
sub(',', '.').to_f
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end # String
|
39
|
+
|
40
|
+
|
41
|
+
# Numeric Additions.
|
42
|
+
class TrueClass
|
43
|
+
# @return 1
|
44
|
+
def to_num
|
45
|
+
1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Numeric Additions.
|
51
|
+
class FalseClass
|
52
|
+
# @return -1
|
53
|
+
def to_num
|
54
|
+
-1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Numeric Additions.
|
60
|
+
class Array
|
61
|
+
# Tries to convert the joined result of this Array into a number. If this
|
62
|
+
# fails, nil is returned.
|
63
|
+
#
|
64
|
+
# @return [Numeric, nil] depending on whether joining returns a valid
|
65
|
+
# number String.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# [1,2,3,4].to_num # => 1234
|
69
|
+
# [1, '1.5', 6, 7].to_num # => 11.567
|
70
|
+
# [1, 'a', 2].to_num # => nil
|
71
|
+
def to_num
|
72
|
+
join.to_num
|
73
|
+
end
|
74
|
+
end # Array
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require_relative 'wrapper'
|
2
|
+
|
3
|
+
module ATypes
|
4
|
+
# A decorator to any object providing Boolean behavior. In comparisons, it
|
5
|
+
# always returns the real true or false instance to avoid ambiguity. By
|
6
|
+
# default, it will handle special values for different object classes, like
|
7
|
+
# certain strings, e.g. transforming the *'true'* to an instance of the
|
8
|
+
# TrueClass. This behavior may be turned off, though, in which case the
|
9
|
+
# standard Ruby evaluation of truthy and falsey will be respected.
|
10
|
+
class BooleanWrap < Wrapper
|
11
|
+
# Extracts the truth from this BooleanWrap's value according to the
|
12
|
+
# following rules:
|
13
|
+
# - for any kind of numeric: values above *0* are *true*, others false.
|
14
|
+
#
|
15
|
+
# - for strings: any string equal to either of the following
|
16
|
+
# ["y", "Y", "1", "yes", "Yes", "YES", "true", "True", "TRUE"]
|
17
|
+
# will be *true*, any string equal to either of these
|
18
|
+
# ["n", "N", "-1", "no", "No", "NO", "false", "False", "FALSE"]
|
19
|
+
# will be *false*.
|
20
|
+
#
|
21
|
+
# - any other object will be transformed to a hard boolean according Ruby's
|
22
|
+
# default truthy evaluation.
|
23
|
+
#
|
24
|
+
# @return [true, false, nil] depending on whether the object may be
|
25
|
+
# converted and which value it contains.
|
26
|
+
def to_bool
|
27
|
+
@truth ||= extract_truth(content)
|
28
|
+
end
|
29
|
+
alias truth to_bool
|
30
|
+
alias to_b to_bool
|
31
|
+
|
32
|
+
|
33
|
+
# Will try to convert this BooleanWrap according to the rules of {#to_bool},
|
34
|
+
# however, it will raise an ArgumentError if conversion fails.
|
35
|
+
#
|
36
|
+
# @return [true, false, nil] depending on whether the object may be
|
37
|
+
# converted and which value it contains.
|
38
|
+
# @see #to_bool
|
39
|
+
def to_bool!
|
40
|
+
error_msg = ">#{content}< can't be interpreted as boolean!"
|
41
|
+
converted = to_bool
|
42
|
+
|
43
|
+
fail(ArgumentError, error_msg) if converted.nil?
|
44
|
+
converted
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# @return [true, false] depending on whether the content interprets to true.
|
49
|
+
def true?
|
50
|
+
to_bool
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# @return [true, false] depending on whether the content interprets to
|
55
|
+
# false.
|
56
|
+
def false?
|
57
|
+
!to_bool
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# @return [true, false] whether the content is truthy according to Ruby's
|
62
|
+
# rules.
|
63
|
+
def truthy?
|
64
|
+
# content can literally be ANYTHING, thus double negation should be the
|
65
|
+
# tool of choice here.
|
66
|
+
!!content
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# @return [true, false] whether the content is falsey according to Ruby's
|
71
|
+
# rules.
|
72
|
+
def falsey?
|
73
|
+
!content
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# Will operate a logical AND with other, based on this BooleanWrap's
|
78
|
+
# {#to_bool} interpretation. It will therefore handle Ruby's native booleans
|
79
|
+
# and the BooleanWrap instances in the very same way. Otherwise, the logic
|
80
|
+
# abides Ruby's default truthy interpretation.
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# BooleanWrap.new(true) & BooleanWrap.new(true) # => true
|
84
|
+
# BooleanWrap.new('y') & "hello" # => true
|
85
|
+
# BooleanWrap.new('y') & nil # => false
|
86
|
+
#
|
87
|
+
# @param [BooleanWrap, true, false, Object] other to logically combine with
|
88
|
+
# this BooleanWrap.
|
89
|
+
# @return [true, false] result of logical AND.
|
90
|
+
def &(other)
|
91
|
+
other_value = other.respond_to?(:truthy?) ? other.truthy? : other
|
92
|
+
to_bool & other_value
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Will operate a logical OR with other, based on this BooleanWrap's
|
97
|
+
# {#to_bool} interpretation. It will therefore handle Ruby's native booleans
|
98
|
+
# and the BooleanWrap instances in the very same way. Otherwise, the logic
|
99
|
+
# abides Ruby's default truthy interpretation.
|
100
|
+
#
|
101
|
+
# @example
|
102
|
+
# BooleanWrap.new(true) | BooleanWrap.new(true) # => true
|
103
|
+
# BooleanWrap.new('y') | "hello" # => true
|
104
|
+
# BooleanWrap.new('y') | nil # => true
|
105
|
+
# BooleanWrap.new(false) | nil # => false
|
106
|
+
#
|
107
|
+
# @param [BooleanWrap, true, false, Object] other to logically combine with
|
108
|
+
# this BooleanWrap.
|
109
|
+
# @return [true, false] result of logical OR.
|
110
|
+
def |(other)
|
111
|
+
other_value = other.respond_to?(:truthy?) ? other.truthy? : other
|
112
|
+
to_bool | other_value
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# Will operate a logical XOR with other, based on this BooleanWrap's
|
117
|
+
# {#to_bool} interpretation. It will therefore handle Ruby's native booleans
|
118
|
+
# and the BooleanWrap instances in the very same way. Otherwise, the logic
|
119
|
+
# abides Ruby'sdefault truthy interpretation.
|
120
|
+
#
|
121
|
+
# @example
|
122
|
+
# BooleanWrap.new(true) ^ BooleanWrap.new(true) # => false
|
123
|
+
# BooleanWrap.new('y') ^ "hello" # => true
|
124
|
+
# BooleanWrap.new('y') ^ nil # => true
|
125
|
+
# BooleanWrap.new(false) ^ nil # => false
|
126
|
+
#
|
127
|
+
# @param [BooleanWrap, true, false, Object] other to logically combine with
|
128
|
+
# this BooleanWrap.
|
129
|
+
# @return [true, false] result of logical OR.
|
130
|
+
def ^(other)
|
131
|
+
other_value = other.respond_to?(:truthy?) ? other.truthy? : other
|
132
|
+
to_bool ^ other_value
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# @example
|
137
|
+
# BooleanWrap.new('y').to_s # => "true"
|
138
|
+
#
|
139
|
+
# @return [String] string representation of this BooleanWrap's {#to_bool}
|
140
|
+
# interpretation.
|
141
|
+
def to_s
|
142
|
+
to_bool.to_s
|
143
|
+
end
|
144
|
+
alias inspect to_s
|
145
|
+
|
146
|
+
|
147
|
+
# Will try to convert given object to a boolean value according to
|
148
|
+
# {#to_bool!}. If this fails, it will return nil.
|
149
|
+
#
|
150
|
+
# @param [Object] source to be converted to a boolean value.
|
151
|
+
# @return [true, false, nil] depending on whether and how the object is
|
152
|
+
# convertible
|
153
|
+
def self.try_convert(source)
|
154
|
+
new(source).to_bool!
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def convert_string(obj)
|
160
|
+
if %w(y Y 1 yes Yes YES true True TRUE).include?(obj)
|
161
|
+
true
|
162
|
+
elsif %w(n N -1 no No NO false False FALSE).include?(obj)
|
163
|
+
false
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def convert_numeric(value)
|
168
|
+
value > 0
|
169
|
+
end
|
170
|
+
|
171
|
+
alias convert_fixnum convert_numeric
|
172
|
+
alias convert_integer convert_numeric
|
173
|
+
alias convert_bignum convert_numeric
|
174
|
+
alias convert_float convert_numeric
|
175
|
+
alias convert_bigdecimal convert_numeric
|
176
|
+
|
177
|
+
|
178
|
+
def extract_truth(obj)
|
179
|
+
strategy = "convert_#{obj.class.name.downcase}"
|
180
|
+
@truth = respond_to?(strategy, true) ? send(strategy, obj) : truthy?
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
end # BooleanWrap
|
185
|
+
end # ATypes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ATypes
|
2
|
+
# Adds enumerable convenience methods to any object, preserving its original
|
3
|
+
# behavior.
|
4
|
+
class EnumerableWrap < Wrapper
|
5
|
+
# Returns true if this objects contains any actual content.
|
6
|
+
#
|
7
|
+
# @return [true, false] depending on whether this object has content.
|
8
|
+
def filled?
|
9
|
+
!blank?
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# Checks whether the object is nil or empty.
|
14
|
+
#
|
15
|
+
# @return [true, false] if object is empty or nil.
|
16
|
+
def blank?
|
17
|
+
if content.respond_to?(:empty?)
|
18
|
+
content.empty?
|
19
|
+
else
|
20
|
+
content.nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # EnumerableWrap
|
24
|
+
end # ATypes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'wrapper'
|
2
|
+
|
3
|
+
module ATypes
|
4
|
+
# Adds numeric methods to any wrapped object.
|
5
|
+
class NumericWrap < Wrapper
|
6
|
+
# Returns the numeric value of this wrapped object. Depending on its class,
|
7
|
+
# different strategies will be applied in the course:
|
8
|
+
# - Strings will be parsed for their content and return nil if it does not
|
9
|
+
# match any number
|
10
|
+
# - true/false will return 1 / -1
|
11
|
+
# - Numerics will return themselves
|
12
|
+
# - Other objects will simply return nil
|
13
|
+
#
|
14
|
+
# @return [Fixnum, Float, nil] the number that could be interpreted from the
|
15
|
+
# wrapped object.
|
16
|
+
def to_num
|
17
|
+
strategy = "convert_#{content.class.name.downcase}"
|
18
|
+
respond_to?(strategy, true) ? send(strategy, content) : nil
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Tries to convert the given object to a numerical value, according to the
|
23
|
+
# rules of {#to_num}. Returns nil if no conversion is possible.
|
24
|
+
#
|
25
|
+
# @param [Object] source to be converted
|
26
|
+
# @return [Fixnum, Float, nil] the result of the conversion to a numeric
|
27
|
+
# value.
|
28
|
+
def self.try_convert(source)
|
29
|
+
new(source).to_num
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def convert_string(content)
|
35
|
+
if content =~ Matchers::FIXNUM
|
36
|
+
content.to_i
|
37
|
+
elsif content =~ Matchers::FLOAT
|
38
|
+
content.sub(',', '.').to_f
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def convert_trueclass(_content)
|
44
|
+
1
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def convert_falseclass(_content)
|
49
|
+
-1
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def convert_array(content)
|
54
|
+
convert_string(content.join)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def convert_fixnum(content)
|
59
|
+
content
|
60
|
+
end
|
61
|
+
alias convert_bignum convert_fixnum
|
62
|
+
alias convert_numeric convert_fixnum
|
63
|
+
alias convert_integer convert_fixnum
|
64
|
+
alias convert_float convert_fixnum
|
65
|
+
alias convert_bigdecimal convert_fixnum
|
66
|
+
end # NumericWrap
|
67
|
+
end # ATypes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ATypes
|
2
|
+
# Provides common matchers
|
3
|
+
module Matchers
|
4
|
+
# Regular expression representing a Fixnum.
|
5
|
+
FIXNUM = /^-?\d+$/
|
6
|
+
# Regular expression matching any float, independently from the separating
|
7
|
+
# character.
|
8
|
+
FLOAT = /^-?\d+[,.]\d+$/
|
9
|
+
end # Matchers
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: a_types
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yves Komenda
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.36'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.36'
|
83
|
+
description: Provides advanced versions of Ruby's basic data types
|
84
|
+
email:
|
85
|
+
- b_d_v@web.de
|
86
|
+
executables:
|
87
|
+
- console
|
88
|
+
- setup
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- ".gitignore"
|
93
|
+
- ".rspec"
|
94
|
+
- ".rubocop.yml"
|
95
|
+
- ".ruby-version"
|
96
|
+
- ".travis.yml"
|
97
|
+
- Gemfile
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- a_types.gemspec
|
102
|
+
- bin/console
|
103
|
+
- bin/setup
|
104
|
+
- lib/a_types.rb
|
105
|
+
- lib/a_types/all.rb
|
106
|
+
- lib/a_types/core_ext/all.rb
|
107
|
+
- lib/a_types/core_ext/boolean.rb
|
108
|
+
- lib/a_types/core_ext/enumerable.rb
|
109
|
+
- lib/a_types/core_ext/numeric.rb
|
110
|
+
- lib/a_types/decorators/all.rb
|
111
|
+
- lib/a_types/decorators/boolean_wrap.rb
|
112
|
+
- lib/a_types/decorators/enuemrable_wrap.rb
|
113
|
+
- lib/a_types/decorators/numeric_wrap.rb
|
114
|
+
- lib/a_types/decorators/wrapper.rb
|
115
|
+
- lib/a_types/support/matchers.rb
|
116
|
+
- lib/a_types/version.rb
|
117
|
+
homepage: https://github.com/Dervol03/a_types
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata: {}
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 2.5.1
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Provides advanced versions of Ruby's basic data types
|
141
|
+
test_files: []
|
142
|
+
has_rdoc:
|