inquisitive 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +116 -1
- data/inquisitive.gemspec +1 -1
- data/lib/inquisitive.rb +31 -8
- data/lib/inquisitive/array.rb +1 -1
- data/lib/inquisitive/environment.rb +7 -5
- data/lib/inquisitive/hash.rb +29 -5
- data/lib/inquisitive/nil_class.rb +10 -2
- data/lib/inquisitive/string.rb +1 -1
- data/test/inquisitive/combinatorial_environment_test.rb +1 -0
- data/test/inquisitive_test.rb +8 -8
- data/test/shared/hash_tests.rb +31 -5
- data/test/test_helper.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78b5345c827669dee4928a4907d68799180a7b6a
|
4
|
+
data.tar.gz: 39899a19a8e7701645acc4134d1c1f8d4e7af5a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a8a2423a9dccc219ac6d3dd13fc9d953e827a83cf6aa089e6dec24deaf21e171c73f4e4b130e7472c3c4467ad4cd821bf75450c13f028096df95153f806580a
|
7
|
+
data.tar.gz: aae5568da7e1a36a75adbc0573fa7a2a3c26b2ef543deee13f1c44631870e752e2710d441603004fed126ca2b7bcf419ae82ca38f93d6249ff7542012bc45349
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ Synopsis
|
|
10
10
|
|
11
11
|
Inquisitive provides String, Array, and Hash subclasses with dynamic predicate methods that allow you to interrogate the most common Ruby datastructures in a readable, friendly fashion. It's the inevitable evolution of ActiveSupport's `StringInquirer`.
|
12
12
|
|
13
|
-
It also allows you to
|
13
|
+
It also allows you to elegantly interrogate your `ENV` hash through the `Inquisitive::Environment` module.
|
14
14
|
|
15
15
|
Inquisitive will try to use ActiveSupport's `HashWithIndifferentAccess`, but if that cannot be found it will bootstrap itself with a minimal, well-tested version extracted from ActiveSupport 4.0.
|
16
16
|
|
@@ -70,6 +70,92 @@ Usage
|
|
70
70
|
-----
|
71
71
|
|
72
72
|
|
73
|
+
### Helpers
|
74
|
+
|
75
|
+
You can coerce any object to a supported Inquisitive equivalent with the Inquisitive coercion helpers:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Inquisitive.coerce('foo').class
|
79
|
+
#=> Inquisitive::String
|
80
|
+
Inquisitive.coerce(1).class
|
81
|
+
#=> Integer
|
82
|
+
|
83
|
+
Inquisitive['foo'].class
|
84
|
+
#=> Inquisitive::String
|
85
|
+
Inquisitive[1].class
|
86
|
+
#=> Integer
|
87
|
+
|
88
|
+
Inquisitive.coerce!('foo').class
|
89
|
+
#=> Inquisitive::String
|
90
|
+
Inquisitive.coerce!(1).class
|
91
|
+
#=> NameError
|
92
|
+
```
|
93
|
+
|
94
|
+
You can check if any object appears to be present with the Inquisitive presence helper:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
Inquisitive.present? 'foo'
|
98
|
+
#=> true
|
99
|
+
Inquisitive.present? %i[foo]
|
100
|
+
#=> true
|
101
|
+
Inquisitive.present? {foo: :bar}
|
102
|
+
#=> true
|
103
|
+
Inquisitive.present? 0
|
104
|
+
#=> true
|
105
|
+
Inquisitive.present? true
|
106
|
+
#=> true
|
107
|
+
|
108
|
+
Inquisitive.present? ''
|
109
|
+
#=> false
|
110
|
+
Inquisitive.present? Array.new
|
111
|
+
#=> false
|
112
|
+
Inquisitive.present? Hash.new
|
113
|
+
#=> false
|
114
|
+
Inquisitive.present? false
|
115
|
+
#=> false
|
116
|
+
Inquisitive.present? nil
|
117
|
+
#=> false
|
118
|
+
Inquisitive.present? Inquisitive::NilClass.new
|
119
|
+
#=> false
|
120
|
+
```
|
121
|
+
|
122
|
+
Finally, you can check if any object is explicitly an Inquisitive object with the Inquisitive object helper:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
nil_object = nil
|
126
|
+
Inquisitive.object? nil_object
|
127
|
+
#=> false
|
128
|
+
Inquisitive.object? Inquisitive[nil_object]
|
129
|
+
#=> true
|
130
|
+
Inquisitive.object? Inquisitive::NilClass.new nil_object
|
131
|
+
#=> true
|
132
|
+
|
133
|
+
string = 'foo'
|
134
|
+
Inquisitive.object? string
|
135
|
+
#=> false
|
136
|
+
Inquisitive.object? Inquisitive[string]
|
137
|
+
#=> true
|
138
|
+
Inquisitive.object? Inquisitive::String.new string
|
139
|
+
#=> true
|
140
|
+
|
141
|
+
array = %i[foo]
|
142
|
+
Inquisitive.object? array
|
143
|
+
#=> false
|
144
|
+
Inquisitive.object? Inquisitive[array]
|
145
|
+
#=> true
|
146
|
+
Inquisitive.object? Inquisitive::Array.new array
|
147
|
+
#=> true
|
148
|
+
|
149
|
+
hash = {foo: :bar}
|
150
|
+
Inquisitive.object? hash
|
151
|
+
#=> false
|
152
|
+
Inquisitive.object? Inquisitive[hash]
|
153
|
+
#=> true
|
154
|
+
Inquisitive.object? Inquisitive::Hash.new hash
|
155
|
+
#=> true
|
156
|
+
```
|
157
|
+
|
158
|
+
|
73
159
|
### String
|
74
160
|
|
75
161
|
`Inquisitive::String` tests equality:
|
@@ -212,6 +298,35 @@ stubbed.api.domains.web?
|
|
212
298
|
#=> false
|
213
299
|
```
|
214
300
|
|
301
|
+
This custom `Inquisitive::NilClass` comes with a few caveats, read the section below to understand them.
|
302
|
+
|
303
|
+
|
304
|
+
### NilClass
|
305
|
+
|
306
|
+
`Inquisitive::NilClass` is a black-hole null object that respects the Inquisitive interface, allowing you to inquire on non-existant nested datastructures as if there was one there, negated methods included:
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
nillish = Inquisitive::NilClass.new
|
310
|
+
#=> nil
|
311
|
+
|
312
|
+
nillish.nil?
|
313
|
+
#=> true
|
314
|
+
nillish.present?
|
315
|
+
#=> false
|
316
|
+
|
317
|
+
|
318
|
+
nillish.access
|
319
|
+
#=> nil
|
320
|
+
nillish.not.access
|
321
|
+
#=> true
|
322
|
+
nillish.exclude.access
|
323
|
+
#=> true
|
324
|
+
nillish.no.access
|
325
|
+
#=> true
|
326
|
+
```
|
327
|
+
|
328
|
+
**Be warned**: since Ruby doesn't allow subclassing `NilClass` and provides no boolean-coercion mechanism, `Inquisitive::NilClass` **will** appear truthy. I recommend using built-in predicates (`stubbed.authentication? && ...`), presence predicates with ActiveSupport (`stubbed.authentication.present? && ...`), Inquisitive's presence utility (`Inquisitive.present?(stubbed.authentication) && ...`) or nil predicates (`stubbed.authentication.nil? || ...`) in boolean chains. Also note that for `Inquisitive::Hash` access, `stubbed.fetch(:authentication, ...)` behaves as expected.
|
329
|
+
|
215
330
|
|
216
331
|
### Inquisitive Environment
|
217
332
|
|
data/inquisitive.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "inquisitive"
|
7
|
-
spec.version = "3.1.
|
7
|
+
spec.version = "3.1.1"
|
8
8
|
spec.authors = ["Chris Keele"]
|
9
9
|
spec.email = ["dev@chriskeele.com"]
|
10
10
|
spec.summary = "Predicate methods for those curious about their datastructures."
|
data/lib/inquisitive.rb
CHANGED
@@ -2,11 +2,20 @@ module Inquisitive
|
|
2
2
|
|
3
3
|
class << self
|
4
4
|
|
5
|
-
def
|
6
|
-
|
5
|
+
def coerce(object)
|
6
|
+
coerce! object
|
7
7
|
rescue NameError
|
8
8
|
object
|
9
9
|
end
|
10
|
+
alias_method :[], :coerce
|
11
|
+
|
12
|
+
def coerce!(object)
|
13
|
+
if Inquisitive.object? object
|
14
|
+
object
|
15
|
+
else
|
16
|
+
Inquisitive.const_get(:"#{object.class}", false).new object
|
17
|
+
end
|
18
|
+
end
|
10
19
|
|
11
20
|
def present?(object)
|
12
21
|
case object
|
@@ -23,20 +32,34 @@ module Inquisitive
|
|
23
32
|
when ::NilClass, NilClass
|
24
33
|
false
|
25
34
|
else
|
26
|
-
|
35
|
+
if object.respond_to?(:present?)
|
36
|
+
object.present?
|
37
|
+
else
|
38
|
+
!!object
|
39
|
+
end
|
27
40
|
end
|
28
41
|
end
|
29
42
|
|
43
|
+
def object?(object)
|
44
|
+
object.class.name.start_with? 'Inquisitive::'
|
45
|
+
end
|
46
|
+
|
30
47
|
end
|
31
48
|
|
32
49
|
private
|
33
50
|
|
34
|
-
|
35
|
-
|
36
|
-
|
51
|
+
module Utils
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def predicate_method?(string)
|
56
|
+
string[-1] == '?'
|
57
|
+
end
|
58
|
+
|
59
|
+
def predication(string)
|
60
|
+
string[0..-2]
|
61
|
+
end
|
37
62
|
|
38
|
-
def predication(string)
|
39
|
-
string[0..-2]
|
40
63
|
end
|
41
64
|
|
42
65
|
end
|
data/lib/inquisitive/array.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Inquisitive
|
2
2
|
module Environment
|
3
|
-
include Inquisitive
|
3
|
+
include Inquisitive::Utils
|
4
4
|
|
5
5
|
def truthy
|
6
6
|
/true|yes|1/i
|
@@ -80,7 +80,7 @@ module Inquisitive
|
|
80
80
|
|
81
81
|
def can_find_env_keys_from(var_name)
|
82
82
|
found = env_keys_from(var_name)
|
83
|
-
|
83
|
+
Inquisitive.present?(found) ? found : nil
|
84
84
|
end
|
85
85
|
|
86
86
|
def env_keys_from(var_name)
|
@@ -91,24 +91,26 @@ module Inquisitive
|
|
91
91
|
|
92
92
|
def set_hash_value_of(hash, var)
|
93
93
|
keypath = var.split('__').map(&:downcase)
|
94
|
-
keypath.shift
|
94
|
+
keypath.shift # discard variable namespace
|
95
95
|
hash.tap do |hash|
|
96
96
|
keypath.reduce(hash) do |namespace, key|
|
97
|
+
|
97
98
|
namespace[key] = if key == keypath.last
|
98
99
|
replace_empty Inquisitive[Parser[var]]
|
99
100
|
else
|
100
|
-
if namespace[key].
|
101
|
+
if namespace[key].kind_of? ::Hash
|
101
102
|
namespace[key]
|
102
103
|
else
|
103
104
|
Hash.new
|
104
105
|
end
|
105
106
|
end
|
107
|
+
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
109
111
|
|
110
112
|
def replace_empty(value)
|
111
|
-
value
|
113
|
+
Inquisitive.present?(value) ? value : NilClass.new(nil)
|
112
114
|
end
|
113
115
|
|
114
116
|
end
|
data/lib/inquisitive/hash.rb
CHANGED
@@ -1,20 +1,44 @@
|
|
1
1
|
module Inquisitive
|
2
2
|
class Hash < HashWithIndifferentAccess
|
3
|
-
include Inquisitive
|
3
|
+
include Inquisitive::Utils
|
4
4
|
|
5
5
|
attr_accessor :negated
|
6
6
|
def no
|
7
7
|
dup.tap{ |s| s.negated = !s.negated }
|
8
8
|
end
|
9
9
|
|
10
|
-
def convert_value(value, options={})
|
11
|
-
super(Inquisitive[value], options)
|
12
|
-
end
|
13
|
-
|
14
10
|
def === other
|
15
11
|
other.class == Class and other == ::Hash or super
|
16
12
|
end
|
17
13
|
|
14
|
+
alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
|
15
|
+
def [](key)
|
16
|
+
Inquisitive[regular_reader key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch(key, default=nil)
|
20
|
+
key = convert_key(key)
|
21
|
+
value = self[key]
|
22
|
+
if Inquisitive.present? value
|
23
|
+
value
|
24
|
+
else
|
25
|
+
if block_given?
|
26
|
+
yield(key)
|
27
|
+
else
|
28
|
+
default
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def convert_value(value, options={})
|
36
|
+
if options[:for] == :assignment
|
37
|
+
return if value.kind_of? NilClass
|
38
|
+
end
|
39
|
+
super(Inquisitive[value], options)
|
40
|
+
end
|
41
|
+
|
18
42
|
private
|
19
43
|
|
20
44
|
def dup
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Inquisitive
|
2
2
|
class NilClass
|
3
|
-
include Inquisitive
|
3
|
+
include Inquisitive::Utils
|
4
4
|
|
5
5
|
def initialize(object=nil); end
|
6
6
|
|
@@ -13,6 +13,10 @@ module Inquisitive
|
|
13
13
|
|
14
14
|
undef_method :nil?, :inspect, :to_s
|
15
15
|
|
16
|
+
def present?
|
17
|
+
presence
|
18
|
+
end
|
19
|
+
|
16
20
|
# Since we can't subclass NilClass
|
17
21
|
# (it has no allocate method)
|
18
22
|
# we fake its identity.
|
@@ -38,11 +42,15 @@ module Inquisitive
|
|
38
42
|
if nil.respond_to? method_name
|
39
43
|
nil.send method_name, *arguments
|
40
44
|
elsif predicate_method? method_name
|
41
|
-
|
45
|
+
presence
|
42
46
|
else
|
43
47
|
self
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
51
|
+
def presence
|
52
|
+
false ^ negated
|
53
|
+
end
|
54
|
+
|
47
55
|
end
|
48
56
|
end
|
data/lib/inquisitive/string.rb
CHANGED
data/test/inquisitive_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class InquisitiveTest < Test
|
4
|
-
|
4
|
+
Utils = Module.new.extend Inquisitive::Utils
|
5
5
|
HashWithIndifferentAccess ||= Inquisitive::HashWithIndifferentAccess
|
6
6
|
|
7
7
|
def setup
|
@@ -147,25 +147,25 @@ class InquisitiveTest < Test
|
|
147
147
|
end
|
148
148
|
|
149
149
|
####
|
150
|
-
#
|
150
|
+
# UTILS
|
151
151
|
##
|
152
152
|
def test_found_symbol_predicate_method_helper
|
153
|
-
assert
|
153
|
+
assert Utils.send :predicate_method?, :foo?
|
154
154
|
end
|
155
155
|
def test_found_string_predicate_method_helper
|
156
|
-
assert
|
156
|
+
assert Utils.send :predicate_method?, "foo?"
|
157
157
|
end
|
158
158
|
def test_missing_symbol_predicate_method_helper
|
159
|
-
refute
|
159
|
+
refute Utils.send :predicate_method?, :foo
|
160
160
|
end
|
161
161
|
def test_missing_string_predicate_method_helper
|
162
|
-
refute
|
162
|
+
refute Utils.send :predicate_method?, "foo"
|
163
163
|
end
|
164
164
|
|
165
165
|
def test_symbol_predication_helper
|
166
|
-
assert_equal
|
166
|
+
assert_equal Utils.send(:predication, :foo?), 'foo'
|
167
167
|
end
|
168
168
|
def test_string_predication_helper
|
169
|
-
assert_equal
|
169
|
+
assert_equal Utils.send(:predication, "foo?"), 'foo'
|
170
170
|
end
|
171
171
|
end
|
data/test/shared/hash_tests.rb
CHANGED
@@ -10,22 +10,48 @@ module HashTests
|
|
10
10
|
refute hash.registration?
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def test_hash_method_access_implicit_nil
|
14
14
|
assert_instance_of Inquisitive::NilClass, hash.missing_key
|
15
15
|
end
|
16
|
-
def
|
16
|
+
def test_hash_method_access_explicit_nil
|
17
17
|
assert_instance_of Inquisitive::NilClass, hash.nothing
|
18
18
|
end
|
19
|
-
def
|
19
|
+
def test_hash_method_access_string
|
20
20
|
assert_instance_of Inquisitive::String, hash.in
|
21
21
|
end
|
22
|
-
def
|
22
|
+
def test_hash_method_access_array
|
23
23
|
assert_instance_of Inquisitive::Array, hash.databases
|
24
24
|
end
|
25
|
-
def
|
25
|
+
def test_hash_method_access_hash
|
26
26
|
assert_instance_of Inquisitive::Hash, hash.nested
|
27
27
|
end
|
28
28
|
|
29
|
+
def test_hash_access_implicit_nil
|
30
|
+
assert_instance_of Inquisitive::NilClass, hash[:missing_key]
|
31
|
+
end
|
32
|
+
def test_hash_access_explicit_nil
|
33
|
+
assert_instance_of Inquisitive::NilClass, hash[:nothing]
|
34
|
+
end
|
35
|
+
def test_hash_access_string
|
36
|
+
assert_instance_of Inquisitive::String, hash[:in]
|
37
|
+
end
|
38
|
+
def test_hash_access_array
|
39
|
+
assert_instance_of Inquisitive::Array, hash[:databases]
|
40
|
+
end
|
41
|
+
def test_hash_access_hash
|
42
|
+
assert_instance_of Inquisitive::Hash, hash[:nested]
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_hash_fetch_implicit_nil
|
46
|
+
assert_equal hash.fetch(:missing_key, @default_value), @default_value
|
47
|
+
end
|
48
|
+
def test_hash_fetch_explicit_nil
|
49
|
+
assert_equal hash.fetch(:nothing, @default_value), @default_value
|
50
|
+
end
|
51
|
+
def test_hash_present_value
|
52
|
+
assert_equal hash.fetch(:in), @raw_string
|
53
|
+
end
|
54
|
+
|
29
55
|
def test_hash_negative_match
|
30
56
|
assert hash.no.registration?
|
31
57
|
end
|
data/test/test_helper.rb
CHANGED