inquisitive 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e22f450e21c1139aff9b5587f6da20f9964ed3f5
4
- data.tar.gz: 26d9737845ee0028316664d7715ec0b2457619b1
3
+ metadata.gz: 78b5345c827669dee4928a4907d68799180a7b6a
4
+ data.tar.gz: 39899a19a8e7701645acc4134d1c1f8d4e7af5a0
5
5
  SHA512:
6
- metadata.gz: 213264cbb822921b64d7393fcdeee3c135dbee7e4ae4ed93d9150b01354fe6f0803d4028cc2ad64147ccf47239de5c2ec49121a60338911beec8dc4d697dc561
7
- data.tar.gz: eea7a7c74d2a3288e6902b1012bccefbaec395e7847007d1dd87fa1cfaa109bdea7d9bcf00ea41af33f36115c504e28059bf6be4ceac90f2b7750aaa0c877e65
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 auto-instanciate and read inquisitive datastructures straight from your `ENV` hash through the `Inquisitive::Environment` module.
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
 
@@ -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.0"
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."
@@ -2,11 +2,20 @@ module Inquisitive
2
2
 
3
3
  class << self
4
4
 
5
- def [](object)
6
- Inquisitive.const_get(:"#{object.class}", false).new object
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
- !!object
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
- def predicate_method?(string)
35
- string[-1] == '?'
36
- end
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
@@ -1,6 +1,6 @@
1
1
  module Inquisitive
2
2
  class Array < ::Array
3
- include Inquisitive
3
+ include Inquisitive::Utils
4
4
 
5
5
  attr_accessor :negated
6
6
  def exclude
@@ -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
- found.empty? ? nil : found
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].respond_to? :store
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 == "" or value.nil? ? NilClass.new(nil) : value
113
+ Inquisitive.present?(value) ? value : NilClass.new(nil)
112
114
  end
113
115
 
114
116
  end
@@ -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
- false ^ negated
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
@@ -1,6 +1,6 @@
1
1
  module Inquisitive
2
2
  class String < ::String
3
- include Inquisitive
3
+ include Inquisitive::Utils
4
4
 
5
5
  attr_accessor :negated
6
6
  def not
@@ -23,6 +23,7 @@ class InquisitiveCombinatorialEnvironmentTest < EnvironmentTest
23
23
  ENV.delete 'HASH__IN'
24
24
  ENV.delete 'HASH__DATABASES'
25
25
  ENV.delete 'HASH__NESTED__KEY'
26
+ ENV.delete 'HASH__NESTED__ARRAY'
26
27
  ENV.delete 'HASH__SOMETHING_NEW'
27
28
  end
28
29
 
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class InquisitiveTest < Test
4
- Helpers = Module.new.extend Inquisitive
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
- # HELPERS
150
+ # UTILS
151
151
  ##
152
152
  def test_found_symbol_predicate_method_helper
153
- assert Helpers.send :predicate_method?, :foo?
153
+ assert Utils.send :predicate_method?, :foo?
154
154
  end
155
155
  def test_found_string_predicate_method_helper
156
- assert Helpers.send :predicate_method?, "foo?"
156
+ assert Utils.send :predicate_method?, "foo?"
157
157
  end
158
158
  def test_missing_symbol_predicate_method_helper
159
- refute Helpers.send :predicate_method?, :foo
159
+ refute Utils.send :predicate_method?, :foo
160
160
  end
161
161
  def test_missing_string_predicate_method_helper
162
- refute Helpers.send :predicate_method?, "foo"
162
+ refute Utils.send :predicate_method?, "foo"
163
163
  end
164
164
 
165
165
  def test_symbol_predication_helper
166
- assert_equal Helpers.send(:predication, :foo?), 'foo'
166
+ assert_equal Utils.send(:predication, :foo?), 'foo'
167
167
  end
168
168
  def test_string_predication_helper
169
- assert_equal Helpers.send(:predication, "foo?"), 'foo'
169
+ assert_equal Utils.send(:predication, "foo?"), 'foo'
170
170
  end
171
171
  end
@@ -10,22 +10,48 @@ module HashTests
10
10
  refute hash.registration?
11
11
  end
12
12
 
13
- def test_hash_access_implicit_nil
13
+ def test_hash_method_access_implicit_nil
14
14
  assert_instance_of Inquisitive::NilClass, hash.missing_key
15
15
  end
16
- def test_hash_access_explicit_nil
16
+ def test_hash_method_access_explicit_nil
17
17
  assert_instance_of Inquisitive::NilClass, hash.nothing
18
18
  end
19
- def test_hash_access_string
19
+ def test_hash_method_access_string
20
20
  assert_instance_of Inquisitive::String, hash.in
21
21
  end
22
- def test_hash_access_array
22
+ def test_hash_method_access_array
23
23
  assert_instance_of Inquisitive::Array, hash.databases
24
24
  end
25
- def test_hash_access_hash
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
@@ -56,6 +56,7 @@ class Test < MiniTest::Test
56
56
  databases: @raw_array,
57
57
  nested: {key: 'value', array: %w[foo bar]}
58
58
  }
59
+ @default_value = 'foo'
59
60
  end
60
61
 
61
62
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquisitive
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Keele