inquisitive 2.0.1 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae129b66c1055352e43e907ac246009511ef0cd2
4
- data.tar.gz: 4cc0713d97d9ed273f904a186bd12cc2d8bdf8b3
3
+ metadata.gz: 80d236d855c6c33b3ec287fcd2c3a302388608f3
4
+ data.tar.gz: bd301adffafcbc757db422e5e0adeb780a06b5e4
5
5
  SHA512:
6
- metadata.gz: 82aa740e308e0cc964700818ce3ea10446a90c586788ea8e856102a89ec00676a23ccfb60de5b3670ef48333c720e6dc20cc6c15ff66a3b46e854579eb76f368
7
- data.tar.gz: b6d575e5815e3ee08fb6c933779604288f5a6995f6ad7d03ac78f01f3fbf91a6b766b45169fad54fdf2463d401aeafda30701f53643da9919891b0ed3d450b96
6
+ metadata.gz: e19cf79e18d77f23a58ee9c6dfc6d87af7262e4fd828f271e9cfe3694c67b38d11ea6c10764a14b6483ce037accac1491348a9a25ef6351c5d7332b6f0cd1d6a
7
+ data.tar.gz: 5e287d046ac747a2f27391bb6c38046b33c3123c93e953546948a06d16500cacde4629fcb77b66c39cfee4941eebb8e1d8df6ba7e4ca41ae6313d7c5989cadd3
data/.travis.yml CHANGED
@@ -4,10 +4,11 @@ rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
6
  - 2.1
7
+ - 2.2
7
8
  - ruby-head
8
9
  - rbx-2
9
10
  - jruby
10
-
11
+
11
12
  gemfile:
12
13
  - Gemfile
13
14
  - Gemfile.ActiveSupport
@@ -20,10 +21,6 @@ env:
20
21
 
21
22
  matrix:
22
23
  fast_finish: true
23
- allow_failures:
24
- - rvm: rbx-2
25
- - rvm: jruby
26
- - rvm: ruby-head
27
24
  exclude:
28
25
  - gemfile: Gemfile.ActiveSupport
29
26
  env: ""
@@ -33,7 +30,7 @@ matrix:
33
30
  env: "activesupport=4.1.1"
34
31
  - gemfile: Gemfile
35
32
  env: "activesupport=master"
36
-
33
+
37
34
  branches:
38
35
  except:
39
36
  - gh-pages
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Chris Keele
1
+ Copyright (c) 2013-2015 Chris Keele
2
2
  ------------------------------
3
3
 
4
4
  MIT License
data/README.md CHANGED
@@ -4,6 +4,7 @@ Inquisitive
4
4
  > **Predicate methods for those curious about their datastructures.**
5
5
 
6
6
 
7
+
7
8
  Synopsis
8
9
  --------
9
10
 
@@ -14,10 +15,12 @@ It also allows you to auto-instanciate and read inquisitive datastructures strai
14
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.
15
16
 
16
17
 
18
+
17
19
  Status
18
20
  ------
19
21
 
20
- [status]: https://travis-ci.org/christhekeele/inquisitive
22
+ [status]: https://travis-ci.org/christhekeele/inquisitive
23
+ [coverage]: https://rawgit.com/christhekeele/inquisitive/master/coverage/index.html
21
24
 
22
25
  [version]: https://rubygems.org/gems/inquisitive/versions
23
26
  [version-image]: https://badge.fury.io/rb/inquisitive@2x.svg
@@ -38,12 +41,13 @@ Status
38
41
 
39
42
  [![Version][version-image]][version] [![Quality][quality-image]][quality] [![Dependencies][dependencies-image]][dependencies]
40
43
 
41
- | :thumbsup: | [Continuous Integration][status] | Test Coverage |
44
+ | :thumbsup: | [Continuous Integration][status] | [Test Coverage][coverage] |
42
45
  |:--------------------------:|:-----------------------------------:|:----------------------------------------:|
43
46
  | [Master][master] | ![Build Status][master-status] | ![Coverage Status][master-coverage] |
44
47
  | [Development][development] | ![Build Status][development-status] | ![Coverage Status][development-coverage] |
45
48
 
46
49
 
50
+
47
51
  Installation
48
52
  ------------
49
53
 
@@ -61,9 +65,11 @@ $ gem install inquisitive
61
65
  ```
62
66
 
63
67
 
68
+
64
69
  Usage
65
70
  -----
66
71
 
72
+
67
73
  ### String
68
74
 
69
75
  `Inquisitive::String` tests equality:
@@ -77,6 +83,7 @@ environment.not.development?
77
83
  #=> false
78
84
  ```
79
85
 
86
+
80
87
  ### Array
81
88
 
82
89
  `Inquisitive::Array` tests inclusion:
@@ -92,6 +99,7 @@ supported_databases.exclude.sql_server?
92
99
  #=> true
93
100
  ```
94
101
 
102
+
95
103
  ### Hash
96
104
 
97
105
  `Inquisitive::Hash` provides struct-like access to its values, wrapped in other inquisitive objects:
@@ -101,11 +109,13 @@ stubbed = Inquisitive::Hash.new(
101
109
  authentication: true,
102
110
  in: 'development',
103
111
  services: %w[database api],
112
+ api: {protocol: 'https', subdomains: %w[app web db]},
104
113
  ignorable: { junk: [ "" ] }
105
114
  )
106
115
  #=> {"authentication"=>true,
107
116
  #=> "in"=>"development",
108
117
  #=> "services"=>["database", "api"],
118
+ #=> "api"=>{"protocol"=>"https", "subdomains"=>["app", "web", "db"]},
109
119
  #=> "ignorable"=>{"junk"=>[""]}}
110
120
 
111
121
  stubbed.authentication?
@@ -114,6 +124,8 @@ stubbed.registration?
114
124
  #=> false
115
125
  stubbed.services?
116
126
  #=> true
127
+ stubbed.api?
128
+ #=> true
117
129
  stubbed.ignorable?
118
130
  #=> false
119
131
 
@@ -121,10 +133,18 @@ stubbed.in.development?
121
133
  #=> true
122
134
  stubbed.in.production?
123
135
  #=> false
136
+
124
137
  stubbed.services.database?
125
138
  #=> true
126
139
  stubbed.services.sidekiq?
127
140
  #=> false
141
+
142
+ stubbed.api.protocol?
143
+ #=> true
144
+ stubbed.api.protocol.http?
145
+ #=> false
146
+ stubbed.api.domains.web?
147
+ #=> true
128
148
  ```
129
149
 
130
150
  `Inquisitive::Hash` also allows negation with the `no` method:
@@ -143,6 +163,56 @@ config.no.api?
143
163
  #=> true
144
164
  ```
145
165
 
166
+ Empty keys and nil values become instances of `Inquisitive::NilClass`, which 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:
167
+
168
+ ```ruby
169
+ stubbed = Inquisitive::Hash.new
170
+ #=> {}
171
+
172
+ # We can query it as if we assumed we had:
173
+ #=> {"authentication"=>true,
174
+ #=> "in"=>"development",
175
+ #=> "services"=>["database", "api"],
176
+ #=> "api"=>{"protocol"=>"https", "subdomains"=>["app", "web", "db"]}}
177
+
178
+ stubbed.authentication?
179
+ #=> false
180
+ stubbed.registration?
181
+ #=> false
182
+ stubbed.services?
183
+ #=> false
184
+ stubbed.api?
185
+ #=> false
186
+ stubbed.ignorable?
187
+ #=> false
188
+ stubbed.no.ignorable?
189
+ #=> true
190
+
191
+ stubbed.in.development?
192
+ #=> false
193
+ stubbed.in.production?
194
+ #=> false
195
+ stubbed.in.not.production?
196
+ #=> true
197
+
198
+ stubbed.services.database?
199
+ #=> false
200
+ stubbed.services.sidekiq?
201
+ #=> false
202
+ stubbed.services.exclude.sidekiq?
203
+ #=> true
204
+
205
+ stubbed.api.protocol?
206
+ #=> false
207
+ stubbed.api.no.protocol?
208
+ #=> true
209
+ stubbed.api.protocol.http?
210
+ #=> false
211
+ stubbed.api.domains.web?
212
+ #=> false
213
+ ```
214
+
215
+
146
216
  ### Inquisitive Environment
147
217
 
148
218
  `Inquisitive::Environment` can be used in your modules and classes to more easily interrogate `ENV` variables with inquisitive objects:
@@ -151,59 +221,69 @@ config.no.api?
151
221
 
152
222
  ```ruby
153
223
  ENV['ENVIRONMENT'] = "development"
154
- class MyGame
224
+ class MyApp
155
225
  extend Inquisitive::Environment
156
226
  inquires_about 'ENVIRONMENT'
157
227
  end
158
228
 
159
- MyGame.environment
229
+ MyApp.environment
160
230
  #=> "development"
161
- MyGame.environment.development?
231
+ MyApp.environment.development?
162
232
  #=> true
163
- MyGame.environment.production?
233
+ MyApp.environment.production?
164
234
  #=> false
165
235
  ```
166
236
 
167
237
  #### Arrays
168
238
 
239
+ Arrays are recognized when environment variables contain commas:
240
+
169
241
  ```ruby
170
242
  ENV['SUPPORTED_DATABASES'] = "mysql,postgres,sqlite"
171
- class MyGame
243
+ class MyApp
172
244
  extend Inquisitive::Environment
173
245
  inquires_about 'SUPPORTED_DATABASES'
174
246
  end
175
247
 
176
- MyGame.supported_databases
248
+ MyApp.supported_databases
177
249
  #=> ["mysql", "postgres", "sqlite"]
178
- MyGame.supported_databases.sqlite?
250
+ MyApp.supported_databases.sqlite?
179
251
  #=> true
180
- MyGame.supported_databases.sql_server?
252
+ MyApp.supported_databases.sql_server?
181
253
  #=> false
182
254
  ```
183
255
 
184
256
  #### Hashes
185
257
 
258
+ Hashes are recognized when environment variables names contain double underscores:
259
+
186
260
  ```ruby
187
261
  ENV['STUB__AUTHENTICATION'] = 'true'
188
262
  ENV['STUB__IN'] = "development"
189
263
  ENV['STUB__SERVICES'] = "database,api"
190
- class MyGame
264
+ ENV['STUB__API__PROTOCOL'] = "https"
265
+ ENV['STUB__API__SUBDOMAINS'] = "app,web,db"
266
+ class MyApp
191
267
  extend Inquisitive::Environment
192
268
  inquires_about 'STUB'
193
269
  end
194
270
 
195
- MyGame.stub.authentication?
271
+ MyApp.stub.authentication?
196
272
  #=> true
197
- MyGame.stub.registration?
273
+ MyApp.stub.registration?
198
274
  #=> false
199
- MyGame.stub.in.development?
275
+ MyApp.stub.in.development?
200
276
  #=> true
201
- MyGame.stub.in.production?
277
+ MyApp.stub.in.production?
202
278
  #=> false
203
- MyGame.stub.services.exclude.sidekiq?
279
+ MyApp.stub.services.exclude.sidekiq?
204
280
  #=> true
205
- MyGame.stub.services.sidekiq?
281
+ MyApp.stub.services.sidekiq?
282
+ #=> false
283
+ MyApp.stub.api.protocol.http?
206
284
  #=> false
285
+ MyApp.stub.api.subdomains.web?
286
+ #=> true
207
287
  ```
208
288
 
209
289
  #### Naming
@@ -212,100 +292,16 @@ You can name your environment inquirers with `:with`:
212
292
 
213
293
  ```ruby
214
294
  ENV['ENVIRONMENT'] = "development"
215
- class MyGame
295
+ class MyApp
216
296
  extend Inquisitive::Environment
217
297
  inquires_about 'ENVIRONMENT', with: :env
218
298
  end
219
299
 
220
- MyGame.env
300
+ MyApp.env
221
301
  #=> "development"
222
- MyGame.env.development?
223
- #=> true
224
- MyGame.env.production?
225
- #=> false
226
- ```
227
-
228
- #### Presence
229
-
230
- Environment inquirers can have explicit presence checks, circumventing a common pitfall when reasoning about environment variables. Borrowing from the example above:
231
-
232
- ```ruby
233
- ENV['STUB__AUTHENTICATION'] = 'false'
234
- class MyGame
235
- extend Inquisitive::Environment
236
- inquires_about 'STUB'
237
- end
238
-
239
- MyGame.stub.authentication
240
- #=> "false"
241
- MyGame.stub.authentication?
302
+ MyApp.env.development?
242
303
  #=> true
243
- MyGame.stub.authentication.true?
244
- #=> false
245
- ```
246
-
247
- It's common to use the presence of environment variables as runtime booleans. This is frequently done by setting the environment variable to the string `"true"` when you want it to be true, and not at all otherwise. As demonstrated, this pattern can lead to ambiguity when the string is other values.
248
-
249
- By default such variables will be parsed as an `Inquisitive::String`, so predicate methods will return true whatever their contents, as long as they exist. You can bind the predicate method tighter to an explicit value if you prefer:
250
-
251
- ```ruby
252
- ENV['STUB_AUTHENTICATION'] = 'false'
253
- ENV['STUB_REGISTRATION'] = 'true'
254
- class MyGame
255
- extend Inquisitive::Environment
256
- inquires_about 'STUB_AUTHENTICATION', present_if: 'true'
257
- inquires_about 'STUB_REGISTRATION', present_if: 'true'
258
- end
259
-
260
- MyGame.stub_authentication
261
- #=> "false"
262
- MyGame.stub_authentication?
263
- #=> false
264
-
265
- MyGame.stub_registration
266
- #=> "true"
267
- MyGame.stub_registration?
268
- #=> true
269
- ```
270
-
271
- This only works on top-level inquirers, so there's no way to get our nested `MyGame.stubbed.authentication?` to behave as expected (currently).
272
-
273
- The `present_if` check uses `===` under the covers for maximum expressiveness, so you can also use it to match against regexs, classes, and other constructs.
274
-
275
- ##### Truthy Booleans
276
-
277
- `Inquisitive::Environment.truthy` contains a regex useful for reading booleans from environment variables.
278
-
279
- ```ruby
280
- ENV['NO'] = 'no'
281
- ENV['YES'] = 'yes'
282
- ENV['TRUTHY'] = 'TrUe'
283
- ENV['FALSEY'] = 'FaLsE'
284
- ENV['BOOLEAN'] = '1'
285
- ENV['BOOLENOPE'] = '0'
286
- class MyCli
287
- extend Inquisitive::Environment
288
- inquires_about 'NO', present_if: truthy
289
- inquires_about 'YES', present_if: truthy
290
- inquires_about 'TRUTHY', present_if: truthy
291
- inquires_about 'FALSEY', present_if: truthy
292
- inquires_about 'BOOLEAN', present_if: truthy
293
- inquires_about 'BOOLENOPE', present_if: truthy
294
- end
295
-
296
- MyGame.no?
297
- #=> false
298
- MyGame.yes?
299
- #=> true
300
-
301
- MyGame.truthy?
302
- #=> true
303
- MyGame.falsey?
304
- #=> false
305
-
306
- MyGame.boolean?
307
- #=> true
308
- MyGame.boolenope?
304
+ MyApp.env.production?
309
305
  #=> false
310
306
  ```
311
307
 
@@ -314,7 +310,7 @@ MyGame.boolenope?
314
310
  Environment inquirers have three configurable modes, defaulting to `:static`.
315
311
 
316
312
  ```ruby
317
- class MyGame
313
+ class MyApp
318
314
  extend Inquisitive::Environment
319
315
  inquires_about 'STUB', mode: %i[dynamic lazy static].sample
320
316
  end
@@ -336,7 +332,8 @@ end
336
332
 
337
333
  Environment inquiries use the contents of `ENV` at the moment `inquires_about` was invoked.
338
334
 
339
- Use if your application is well-behaved and doesn't go mucking around with the environment at runtime.
335
+ Use if your application is well-behaved and doesn't go mucking around with the environment at runtim.
336
+
340
337
 
341
338
 
342
339
  Contributing
data/Rakefile CHANGED
@@ -7,6 +7,17 @@ Rake::TestTask.new do |t|
7
7
  end
8
8
  task default: :test
9
9
 
10
- task :console do
11
- `pry -I lib -r inquisitive.rb`
10
+ desc "Open a pry console preloaded with this library"
11
+ task console: 'console:pry'
12
+
13
+ namespace :console do
14
+
15
+ task :pry do
16
+ sh "bundle exec pry -I lib -r inquisitive.rb"
17
+ end
18
+
19
+ task :irb do
20
+ sh "bundle exec irb -I lib -r inquisitive.rb"
21
+ end
22
+
12
23
  end
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 = "2.0.1"
7
+ spec.version = "3.0.0"
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."
@@ -18,11 +18,10 @@ Gem::Specification.new do |spec|
18
18
  Also allows you to auto-instanciate and read inquisitive datastructures straight
19
19
  from your `ENV` hash.
20
20
  DESC
21
- spec.homepage = "https://github.com/rawsugar/inquisitive"
21
+ spec.homepage = "http://christhekeele.github.io/inquisitive"
22
22
  spec.license = "MIT"
23
-
24
- spec.files = `git ls-files`.split($/)
25
- spec.test_files = spec.files.grep(%r{^(test)/})
23
+ spec.files = `git ls-files lib README.md LICENSE.md`.split($/)
24
+ spec.test_files = `git ls-files test inquisitive.gemspec Gemfile Gemfile.lock Gemfile.ActiveSupport Rakefile .travis.yml .coveralls.yml`.split($/)
26
25
  spec.require_paths = ["lib"]
27
26
 
28
27
  spec.add_development_dependency "bundler", ">= 1.3"
data/lib/inquisitive.rb CHANGED
@@ -10,16 +10,18 @@ module Inquisitive
10
10
 
11
11
  def present?(object)
12
12
  case object
13
- when ::String
13
+ when ::String, String
14
14
  not object.empty?
15
- when ::Array
15
+ when ::Array, Array
16
16
  object.any? do |value|
17
17
  Inquisitive.present? value
18
18
  end
19
- when ::Hash
19
+ when ::Hash, Hash
20
20
  object.values.any? do |value|
21
21
  Inquisitive.present? value
22
22
  end
23
+ when ::NilClass, NilClass
24
+ false
23
25
  else
24
26
  !!object
25
27
  end
@@ -39,6 +41,7 @@ private
39
41
 
40
42
  end
41
43
 
44
+ require "inquisitive/nil_class"
42
45
  require "inquisitive/string"
43
46
  require "inquisitive/array"
44
47
  unless Object.const_defined? :HashWithIndifferentAccess
@@ -1,12 +1,16 @@
1
1
  module Inquisitive
2
2
  class Array < ::Array
3
3
  include Inquisitive
4
- attr_accessor :negated, :array
5
4
 
5
+ attr_accessor :negated
6
6
  def exclude
7
7
  self.dup.tap{ |a| a.negated = !a.negated }
8
8
  end
9
9
 
10
+ def === other
11
+ other.class == Class and other == ::Array or super
12
+ end
13
+
10
14
  private
11
15
 
12
16
  def respond_to_missing?(method_name, include_private = false)
@@ -2,10 +2,6 @@ module Inquisitive
2
2
  module Environment
3
3
  include Inquisitive
4
4
 
5
- def truthy
6
- /true|yes|1/i
7
- end
8
-
9
5
  def inquires_about(env_var, opts={})
10
6
 
11
7
  env_accessor = opts.fetch(:with, env_var.downcase[/(.*?)(?=(?:_$|$))/])
@@ -35,19 +31,6 @@ module Inquisitive
35
31
 
36
32
  end
37
33
 
38
- present_if = opts.fetch(:present_if, nil)
39
-
40
- @__env_presence__ ||= HashWithIndifferentAccess.new
41
- @__env_presence__["#{env_accessor}?"] = present_if if present_if
42
-
43
- define_singleton_method :"#{env_accessor}?" do
44
- if @__env_presence__.has_key? __method__
45
- @__env_presence__[__method__] === send(predication(__method__))
46
- else
47
- Inquisitive.present? send(predication(__method__))
48
- end
49
- end
50
-
51
34
  end
52
35
 
53
36
  private
@@ -56,7 +39,7 @@ module Inquisitive
56
39
  class << self
57
40
 
58
41
  def [](var_name)
59
- if ENV.has_key? var_name
42
+ result = if ENV.has_key? var_name
60
43
 
61
44
  env_var = ENV[var_name]
62
45
  if env_var.include? ','
@@ -67,14 +50,15 @@ module Inquisitive
67
50
 
68
51
  elsif env_vars = can_find_env_keys_from(var_name)
69
52
 
70
- env_vars.reduce({}) do |hash, key|
71
- hash[key_for(key, var_name)] = Inquisitive[Parser[key]]
72
- hash
53
+ Hash[].tap do |hash|
54
+ env_vars.each do |key|
55
+ set_hash_value_of hash, key
56
+ end
73
57
  end
74
58
 
75
- else
76
- ""
77
59
  end
60
+
61
+ replace_empty result
78
62
  end
79
63
 
80
64
  def can_find_env_keys_from(var_name)
@@ -88,8 +72,26 @@ module Inquisitive
88
72
  end
89
73
  end
90
74
 
91
- def key_for(env_key, var_name)
92
- env_key.gsub("#{var_name}__", '').downcase
75
+ def set_hash_value_of(hash, var)
76
+ keypath = var.split('__').map(&:downcase)
77
+ keypath.shift
78
+ hash.tap do |hash|
79
+ keypath.reduce(hash) do |namespace, key|
80
+ namespace[key] = if key == keypath.last
81
+ replace_empty Inquisitive[Parser[var]]
82
+ else
83
+ if namespace[key].respond_to? :store
84
+ namespace[key]
85
+ else
86
+ Hash.new
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def replace_empty(value)
94
+ value == "" or value.nil? ? NilClass.new(nil) : value
93
95
  end
94
96
 
95
97
  end
@@ -11,6 +11,10 @@ module Inquisitive
11
11
  super(Inquisitive[value], options)
12
12
  end
13
13
 
14
+ def === other
15
+ other.class == Class and other == ::Hash or super
16
+ end
17
+
14
18
  private
15
19
 
16
20
  def dup
@@ -27,10 +31,8 @@ module Inquisitive
27
31
  else
28
32
  false
29
33
  end ^ negated
30
- elsif has_key? method_name
31
- self[method_name]
32
34
  else
33
- super
35
+ Inquisitive[self[method_name]]
34
36
  end
35
37
  end
36
38
 
@@ -0,0 +1,48 @@
1
+ module Inquisitive
2
+ class NilClass
3
+ include Inquisitive
4
+
5
+ def initialize(object=nil); end
6
+
7
+ attr_accessor :negated
8
+ def not
9
+ self.dup.tap{ |s| s.negated = !s.negated }
10
+ end
11
+ alias_method :exclude, :not
12
+ alias_method :no, :not
13
+
14
+ undef_method :nil?, :inspect, :to_s
15
+
16
+ # Since we can't subclass NilClass
17
+ # (it has no allocate method)
18
+ # we fake its identity.
19
+ def instance_of?(klass)
20
+ klass == ::NilClass or super
21
+ end
22
+ alias_method :kind_of?, :instance_of?
23
+ alias_method :is_a?, :instance_of?
24
+
25
+ def == other
26
+ other.nil?
27
+ end
28
+ def === other
29
+ other.class == Class and other == ::NilClass or super
30
+ end
31
+
32
+ private
33
+
34
+ def respond_to_missing?(method_name, include_private = false)
35
+ true # nil.respond_to? method_name or predicate_method? method_name
36
+ end
37
+ def method_missing(method_name, *arguments)
38
+ if nil.respond_to? method_name
39
+ nil.send method_name, *arguments
40
+ elsif predicate_method? method_name
41
+ false ^ negated
42
+ else
43
+ self
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -7,6 +7,10 @@ module Inquisitive
7
7
  self.dup.tap{ |s| s.negated = !s.negated }
8
8
  end
9
9
 
10
+ def === other
11
+ other.class == Class and other == ::String or super
12
+ end
13
+
10
14
  private
11
15
 
12
16
  def respond_to_missing?(method_name, include_private = false)
@@ -4,22 +4,31 @@ class InquisitiveCombinatorialEnvironmentTest < EnvironmentTest
4
4
 
5
5
  def setup
6
6
  super
7
+ ENV['NIL_OBJECT'] = @raw_nil_object
7
8
  ENV['STRING'] = @raw_string
8
9
  ENV['ARRAY'] = @raw_array.join(',')
10
+ ENV['HASH__NOTHING'] = @raw_hash[:nothing]
9
11
  ENV['HASH__AUTHENTICATION'] = @raw_hash[:authentication].to_s
10
12
  ENV['HASH__IN'] = @raw_hash[:in]
11
13
  ENV['HASH__DATABASES'] = @raw_hash[:databases].join(',')
14
+ ENV['HASH__NESTED__KEY'] = @raw_hash[:nested][:key]
15
+ ENV['HASH__NESTED__ARRAY'] = @raw_hash[:nested][:array].join(',')
12
16
  end
13
17
  def teardown
14
18
  super
15
19
  ENV.delete 'STRING'
16
20
  ENV.delete 'ARRAY'
21
+ ENV.delete 'HASH__NOTHING'
17
22
  ENV.delete 'HASH__AUTHENTICATION'
18
23
  ENV.delete 'HASH__IN'
19
24
  ENV.delete 'HASH__DATABASES'
25
+ ENV.delete 'HASH__NESTED__KEY'
20
26
  ENV.delete 'HASH__SOMETHING_NEW'
21
27
  end
22
28
 
29
+ def change_nil_object_variable
30
+ ENV['NIL_OBJECT'] = 'something_new'
31
+ end
23
32
  def change_string_variable
24
33
  ENV['STRING'] = 'something_new'
25
34
  end
@@ -33,10 +42,10 @@ class InquisitiveCombinatorialEnvironmentTest < EnvironmentTest
33
42
  end
34
43
 
35
44
  %w[dynamic lazy static].each do |mode|
36
- %w[string array hash].each do |type|
45
+ %w[nil_object string array hash].each do |type|
37
46
 
38
47
  Inquisitive.const_set(
39
- :"Inquisitive#{mode.capitalize}#{type.capitalize}EnvironmentTest",
48
+ :"Inquisitive#{mode.capitalize}#{type.split('_').map(&:capitalize).join}EnvironmentTest",
40
49
  Class.new(InquisitiveCombinatorialEnvironmentTest) do
41
50
 
42
51
  class << self
@@ -50,6 +59,9 @@ end
50
59
  App.inquires_about @type.upcase, mode: @mode
51
60
  end
52
61
 
62
+ def nil_object
63
+ App.nil_object
64
+ end
53
65
  def string
54
66
  App.string
55
67
  end
@@ -66,7 +78,7 @@ end
66
78
  ).tap do |klass|
67
79
  klass.mode = mode
68
80
  klass.type = type
69
- end.send :include, Object.const_get(:"#{type.capitalize}Tests")
81
+ end.send :include, Object.const_get(:"#{type.split('_').map(&:capitalize).join}Tests")
70
82
  # Mixes in type-specific tests to ensure lookup behaves normally
71
83
  # when accessed through the modes of App getters
72
84
 
@@ -2,15 +2,6 @@ require 'test_helper'
2
2
 
3
3
  class InquisitiveEnvironmentTest < EnvironmentTest
4
4
 
5
- def test_missing_variable_responses
6
- App.inquires_about 'DOES_NOT_EXIST', with: :exists
7
- assert_equal "", App.exists
8
- end
9
- def test_missing_variable_predicates
10
- App.inquires_about 'DOES_NOT_EXIST', with: :exists
11
- refute App.exists?
12
- end
13
-
14
5
  def test_autonaming_of_inquirers
15
6
  App.inquires_about 'NAME_NOT_SPECIFIED'
16
7
  assert App.respond_to? :name_not_specified
@@ -25,30 +16,4 @@ class InquisitiveEnvironmentTest < EnvironmentTest
25
16
  assert App.defaults_to.static?
26
17
  end
27
18
 
28
- def test_custom_string_presence
29
- ENV['AUTHORIZABLE'] = 'false'
30
- App.inquires_about 'AUTHORIZABLE', present_if: 'true'
31
- refute App.authorizable?
32
- end
33
-
34
- def test_custom_regex_presence
35
- ENV['AUTHORIZABLE'] = 'not at all'
36
- App.inquires_about 'AUTHORIZABLE', present_if: /yes/
37
- refute App.authorizable?
38
- end
39
-
40
- def test_custom_class_presence
41
- ENV['AUTHORIZABLE'] = 'not at all'
42
- App.inquires_about 'AUTHORIZABLE', present_if: Array
43
- refute App.authorizable?
44
- end
45
-
46
- %w[true True TrUe TRUE yes Yes YeS YES 1].each do |truthy_var|
47
- define_method :"test_truthy_var_#{truthy_var}" do
48
- ENV['TRUTHY'] = truthy_var
49
- App.inquires_about 'TRUTHY', present_if: App.truthy
50
- assert App.truthy?
51
- end
52
- end
53
-
54
19
  end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ class NilObjectTest < Test
4
+
5
+ def nil_object
6
+ Inquisitive::NilClass.new
7
+ end
8
+
9
+ include NilObjectTests
10
+
11
+ end
@@ -19,9 +19,6 @@ class InquisitiveTest < Test
19
19
  ####
20
20
  # CONVERSION
21
21
  ##
22
- def test_converted_nil_equality
23
- assert_equal Inquisitive[nil], nil
24
- end
25
22
  def test_converted_false_equality
26
23
  assert_equal Inquisitive[false], false
27
24
  end
@@ -41,22 +38,45 @@ class InquisitiveTest < Test
41
38
  assert_equal Inquisitive[@object], @object
42
39
  end
43
40
 
41
+ def test_converted_nil_object_ancestry
42
+ assert_kind_of NilClass, Inquisitive[nil]
43
+ assert Inquisitive[nil] === NilClass
44
+ end
45
+ def test_converted_nil_object_instanciation
46
+ assert_kind_of Inquisitive::NilClass, Inquisitive[nil]
47
+ end
48
+ def test_converted_nil_object_equality
49
+ assert_equal Inquisitive[nil], @raw_nil_object
50
+ end
51
+
52
+ def test_converted_string_ancestry
53
+ assert_kind_of String, Inquisitive[@raw_string]
54
+ assert Inquisitive[@raw_string] === String
55
+ end
44
56
  def test_converted_string_instanciation
45
- assert_instance_of Inquisitive::String, Inquisitive[@raw_string]
57
+ assert_kind_of Inquisitive::String, Inquisitive[@raw_string]
46
58
  end
47
59
  def test_converted_string_equality
48
60
  assert_equal Inquisitive[@raw_string], @raw_string
49
61
  end
50
62
 
63
+ def test_converted_array_ancestry
64
+ assert_kind_of Array, Inquisitive[@raw_array]
65
+ assert Inquisitive[@raw_array] === Array
66
+ end
51
67
  def test_converted_array_instanciation
52
- assert_instance_of Inquisitive::Array, Inquisitive[@raw_array]
68
+ assert_kind_of Inquisitive::Array, Inquisitive[@raw_array]
53
69
  end
54
70
  def test_converted_array_equality
55
71
  assert_equal Inquisitive[@raw_array], @raw_array
56
72
  end
57
73
 
74
+ def test_converted_hash_ancestry
75
+ assert_kind_of Hash, Inquisitive[@raw_hash]
76
+ assert Inquisitive[@raw_hash] === Hash
77
+ end
58
78
  def test_converted_hash_instanciation
59
- assert_instance_of Inquisitive::Hash, Inquisitive[@raw_hash]
79
+ assert_kind_of Inquisitive::Hash, Inquisitive[@raw_hash]
60
80
  end
61
81
  def test_converted_hash_equality
62
82
  assert_equal Inquisitive[@raw_hash], HashWithIndifferentAccess.new(@raw_hash)
@@ -2,27 +2,28 @@ module ArrayTests
2
2
  def test_array_value_type
3
3
  assert_instance_of Inquisitive::Array, array
4
4
  end
5
+
5
6
  def test_array_match
6
7
  assert array.postgres?
7
8
  end
8
9
  def test_array_miss
9
10
  refute array.sql_server?
10
11
  end
12
+
11
13
  def test_array_negative_match
12
14
  assert array.exclude.sql_server?
13
15
  end
14
16
  def test_array_negative_miss
15
17
  refute array.exclude.postgres?
16
18
  end
19
+
17
20
  def test_array_double_negative_match
18
21
  assert array.exclude.exclude.postgres?
19
22
  end
20
23
  def test_array_double_negative_miss
21
24
  refute array.exclude.exclude.sql_server?
22
25
  end
23
- def test_array_missing_question_mark
24
- assert_raises(NoMethodError) { array.postgres }
25
- end
26
+
26
27
  def test_array_respond_to
27
28
  assert_respond_to array, :postgres?
28
29
  end
@@ -2,14 +2,14 @@ module CombinatorialEnvironmentTests
2
2
 
3
3
  def test_type_is_parsed_correctly
4
4
  assert_kind_of(
5
- Object.const_get(:"#{@type.capitalize}"),
5
+ Object.const_get(:"#{type_const_name}"),
6
6
  App.send(@type)
7
7
  )
8
8
  end
9
9
 
10
10
  def test_type_is_converted_correctly
11
11
  assert_kind_of(
12
- Inquisitive.const_get(:"#{@type.capitalize}"),
12
+ Inquisitive.const_get(:"#{type_const_name}"),
13
13
  App.send(@type)
14
14
  )
15
15
  end
@@ -30,4 +30,10 @@ module CombinatorialEnvironmentTests
30
30
  end
31
31
  end
32
32
 
33
+ private
34
+
35
+ def type_const_name
36
+ @type == 'nil_object' ? 'NilClass' : @type.capitalize
37
+ end
38
+
33
39
  end
@@ -1,26 +1,46 @@
1
1
  module HashTests
2
+ def test_hash_value_type
3
+ assert_instance_of Inquisitive::Hash, hash
4
+ end
5
+
2
6
  def test_hash_match
3
7
  assert hash.authentication?
4
8
  end
5
9
  def test_hash_miss
6
10
  refute hash.registration?
7
11
  end
12
+
13
+ def test_hash_access_implicit_nil
14
+ assert_instance_of Inquisitive::NilClass, hash.missing_key
15
+ end
16
+ def test_hash_access_explicit_nil
17
+ assert_instance_of Inquisitive::NilClass, hash.nothing
18
+ end
19
+ def test_hash_access_string
20
+ assert_instance_of Inquisitive::String, hash.in
21
+ end
22
+ def test_hash_access_array
23
+ assert_instance_of Inquisitive::Array, hash.databases
24
+ end
25
+ def test_hash_access_hash
26
+ assert_instance_of Inquisitive::Hash, hash.nested
27
+ end
28
+
8
29
  def test_hash_negative_match
9
30
  assert hash.no.registration?
10
31
  end
11
32
  def test_hash_negative_miss
12
33
  refute hash.no.authentication?
13
34
  end
35
+
14
36
  def test_hash_double_negative_match
15
37
  assert hash.no.no.authentication?
16
38
  end
17
39
  def test_hash_double_negative_miss
18
40
  refute hash.no.no.registration?
19
41
  end
42
+
20
43
  def test_hash_respond_to
21
44
  assert_respond_to hash, :authentication?
22
45
  end
23
- def test_hash_method_missing
24
- assert_raises(NoMethodError) { hash.undefined }
25
- end
26
46
  end
@@ -0,0 +1,56 @@
1
+ module NilObjectTests
2
+ def test_nil_object_value_type
3
+ assert_instance_of Inquisitive::NilClass, nil_object
4
+ end
5
+
6
+ def test_nil_object_chains
7
+ assert_instance_of Inquisitive::NilClass, nil_object.chain
8
+ end
9
+
10
+ def test_nil_object_match
11
+ assert nil_object.nil?
12
+ end
13
+ def test_nil_object_miss
14
+ refute nil_object.anything_else?
15
+ end
16
+
17
+ def test_nil_object_string_interface
18
+ string = nil_object
19
+ refute string.production?
20
+ end
21
+ def test_nil_object_string_interface_negative
22
+ string = nil_object
23
+ assert string.not.development?
24
+ end
25
+ def test_nil_object_string_interface_double_negative
26
+ string = nil_object
27
+ refute string.not.not.development?
28
+ end
29
+
30
+ def test_nil_object_array_interface
31
+ array = nil_object
32
+ refute array.production?
33
+ end
34
+ def test_nil_object_array_interface_negative
35
+ array = nil_object
36
+ assert array.exclude.development?
37
+ end
38
+ def test_nil_object_array_interface_double_negative
39
+ array = nil_object
40
+ refute array.exclude.exclude.development?
41
+ end
42
+
43
+ def test_nil_object_hash_interface
44
+ hash = nil_object
45
+ refute hash.production?
46
+ end
47
+ def test_nil_object_hash_interface_negative
48
+ hash = nil_object
49
+ assert hash.no.development?
50
+ end
51
+ def test_nil_object_hash_interface_double_negative
52
+ hash = nil_object
53
+ refute hash.no.no.development?
54
+ end
55
+
56
+ end
@@ -2,27 +2,28 @@ module StringTests
2
2
  def test_string_value_type
3
3
  assert_instance_of Inquisitive::String, string
4
4
  end
5
+
5
6
  def test_string_match
6
7
  assert string.production?
7
8
  end
8
9
  def test_string_miss
9
10
  refute string.development?
10
11
  end
12
+
11
13
  def test_string_negative_match
12
14
  assert string.not.development?
13
15
  end
14
16
  def test_string_negative_miss
15
17
  refute string.not.production?
16
18
  end
19
+
17
20
  def test_string_double_negative_match
18
21
  assert string.not.not.production?
19
22
  end
20
23
  def test_string_double_negative_miss
21
24
  refute string.not.not.development?
22
25
  end
23
- def test_string_missing_question_mark
24
- assert_raises(NoMethodError) { string.production }
25
- end
26
+
26
27
  def test_string_respond_to
27
28
  assert_respond_to string, :development?
28
29
  end
data/test/test_helper.rb CHANGED
@@ -1,8 +1,9 @@
1
- require "rubygems"
1
+ require 'rubygems'
2
+ require 'pry'
2
3
 
3
4
  begin
4
5
  require 'simplecov'
5
- SimpleCov.coverage_dir '.coverage'
6
+ SimpleCov.coverage_dir 'coverage'
6
7
  if ENV['CI']
7
8
  require 'coveralls'
8
9
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
@@ -12,11 +13,10 @@ begin
12
13
  end
13
14
  SimpleCov.start do
14
15
  add_filter "/test"
15
- add_filter "/vendor"
16
16
  end
17
17
  end
18
18
 
19
- require "minitest/autorun"
19
+ require 'minitest/autorun'
20
20
 
21
21
  class Test < MiniTest::Test
22
22
 
@@ -46,12 +46,15 @@ class Test < MiniTest::Test
46
46
  end
47
47
 
48
48
  def setup
49
+ @raw_nil_object = nil
49
50
  @raw_string = 'production'
50
51
  @raw_array = %w[mysql postgres sqlite]
51
52
  @raw_hash = {
53
+ nothing: @raw_nil_object,
52
54
  authentication: true,
53
55
  in: @raw_string,
54
- databases: @raw_array
56
+ databases: @raw_array,
57
+ nested: {key: 'value', array: %w[foo bar]}
55
58
  }
56
59
  end
57
60
 
@@ -71,9 +74,10 @@ class EnvironmentTest < Test
71
74
 
72
75
  end
73
76
 
74
- require "shared/string_tests"
75
- require "shared/array_tests"
76
- require "shared/hash_tests"
77
- require "shared/combinatorial_environment_tests"
77
+ require 'shared/nil_object_tests'
78
+ require 'shared/string_tests'
79
+ require 'shared/array_tests'
80
+ require 'shared/hash_tests'
81
+ require 'shared/combinatorial_environment_tests'
78
82
 
79
- require "inquisitive"
83
+ require 'inquisitive'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquisitive
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Keele
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-24 00:00:00.000000000 Z
11
+ date: 2015-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,9 +68,7 @@ extensions: []
68
68
  extra_rdoc_files: []
69
69
  files:
70
70
  - ".coveralls.yml"
71
- - ".gitignore"
72
71
  - ".travis.yml"
73
- - CHANGELOG.md
74
72
  - Gemfile
75
73
  - Gemfile.ActiveSupport
76
74
  - LICENSE.md
@@ -82,20 +80,23 @@ files:
82
80
  - lib/inquisitive/environment.rb
83
81
  - lib/inquisitive/hash.rb
84
82
  - lib/inquisitive/hash_with_indifferent_access.rb
83
+ - lib/inquisitive/nil_class.rb
85
84
  - lib/inquisitive/string.rb
86
85
  - test/inquisitive/array_test.rb
87
86
  - test/inquisitive/combinatorial_environment_test.rb
88
87
  - test/inquisitive/environment_test.rb
89
88
  - test/inquisitive/hash_test.rb
90
89
  - test/inquisitive/hash_with_indifferent_access_test.rb
90
+ - test/inquisitive/nil_object_test.rb
91
91
  - test/inquisitive/string_test.rb
92
92
  - test/inquisitive_test.rb
93
93
  - test/shared/array_tests.rb
94
94
  - test/shared/combinatorial_environment_tests.rb
95
95
  - test/shared/hash_tests.rb
96
+ - test/shared/nil_object_tests.rb
96
97
  - test/shared/string_tests.rb
97
98
  - test/test_helper.rb
98
- homepage: https://github.com/rawsugar/inquisitive
99
+ homepage: http://christhekeele.github.io/inquisitive
99
100
  licenses:
100
101
  - MIT
101
102
  metadata: {}
@@ -120,15 +121,23 @@ signing_key:
120
121
  specification_version: 4
121
122
  summary: Predicate methods for those curious about their datastructures.
122
123
  test_files:
124
+ - ".coveralls.yml"
125
+ - ".travis.yml"
126
+ - Gemfile
127
+ - Gemfile.ActiveSupport
128
+ - Rakefile
129
+ - inquisitive.gemspec
123
130
  - test/inquisitive/array_test.rb
124
131
  - test/inquisitive/combinatorial_environment_test.rb
125
132
  - test/inquisitive/environment_test.rb
126
133
  - test/inquisitive/hash_test.rb
127
134
  - test/inquisitive/hash_with_indifferent_access_test.rb
135
+ - test/inquisitive/nil_object_test.rb
128
136
  - test/inquisitive/string_test.rb
129
137
  - test/inquisitive_test.rb
130
138
  - test/shared/array_tests.rb
131
139
  - test/shared/combinatorial_environment_tests.rb
132
140
  - test/shared/hash_tests.rb
141
+ - test/shared/nil_object_tests.rb
133
142
  - test/shared/string_tests.rb
134
143
  - test/test_helper.rb
data/.gitignore DELETED
@@ -1,18 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .coverage
6
- .yardoc
7
- Gemfile.lock
8
- InstalledFiles
9
- _yardoc
10
- coverage
11
- doc/
12
- lib/bundler/man
13
- pkg
14
- rdoc
15
- spec/reports
16
- test/tmp
17
- test/version_tmp
18
- tmp
data/CHANGELOG.md DELETED
@@ -1,80 +0,0 @@
1
- Changes to Inquisitive
2
- ======================
3
-
4
- > **Please consult this file when upgrading Inquisitive for important information on bugfixes, new features, and backwards incompatible changes.**
5
-
6
- Starting with **[2.0.0](#2.0.0)**, Inquisitive follows [symantic versioning](symver.org) to help inform you of the implications of upgrades.
7
-
8
- Releases
9
- --------
10
-
11
- [2.0.1]: https://github.com/christhekeele/inquisitive/tree/2.0.1
12
- [2.0.0]: https://github.com/christhekeele/inquisitive/tree/2.0.0
13
- [1.2.0]: https://github.com/christhekeele/inquisitive/tree/f314eaf84f7c3d9a2d56ae684d031dd81d2f7b85
14
-
15
- - [2.0.0](#2.0.0)
16
- - [1.2.0](#1.2.0)
17
-
18
- 2.0.1 - [2014.09.24][2.0.1]
19
- ---------------------------
20
-
21
- ### Non-breaking
22
-
23
- - `Inquisitive::Environment.truthy`: **helper regex**
24
-
25
- The `truthy` method provides an easy way to handle various command-line representations of truthiness.
26
-
27
-
28
- 2.0.0 - [2014.06.19][2.0.0]
29
- ---------------------------
30
-
31
- ### Breaking
32
-
33
- - `Inquisitive::Environment`: **hash detection**
34
-
35
- Previously `inquires_about` needed a special syntax to detect when you want to parse a group of environment variables as a hash. This was accomplished by leaving a trailing `_` in the declaration, such as:
36
-
37
- ```ruby
38
- ENV['PREFIX_KEY1'] = "value1"
39
- ENV['PREFIX_KEY2'] = "value2"
40
- module Mine
41
- extend Inquisitive::Environment
42
- inquires_about 'PREFIX_'
43
- end
44
- Mine.prefix
45
- #=> { 'key1' => 'value1', 'key2' => 'value2' }
46
- ```
47
-
48
- Now it auto-detects hash groupings by looking for a double-`_` in the key itself:
49
-
50
- ```ruby
51
- ENV['PREFIX__KEY1'] = "value1"
52
- ENV['PREFIX__KEY2'] = "value2"
53
- module Mine
54
- extend Inquisitive::Environment
55
- inquires_about 'PREFIX'
56
- end
57
- Mine.prefix
58
- #=> { 'key1' => 'value1', 'key2' => 'value2' }
59
- ```
60
-
61
- Nested hashes (through multiple `__`'s) are not yet supported.
62
-
63
- - `Inquisitive::Environment`: **default modes**
64
-
65
- Previously the default mode was `:dynamic`. This was mostly to prevent unexpected behaviour for newcomers.
66
-
67
- Now `:static` is the default. This is because `Inquisitive::Environment` is meant to be loaded immediately after a boot script that prepares your environment variables, and queried often later. `:static` optimizes to this usecase.
68
-
69
- To reproduce the old behaviour, you must explicitly pass `mode: :dynamic` each to `inquires_about` invocation. Alternatively, `mode: :lazy` might be a viable way to get the benefits of `:static` without refactoring your boot process.
70
-
71
- ### Non-breaking
72
-
73
- - `Inquisitive::Environment`: **cached mode now lazy mode**
74
-
75
- The `:cached` environment mode is now known as `:lazy`. This is backwards compatible because all logic handling modes explicitly checks for `:static` or `:dynamic`, so any other named mode has the same behaviour as `:lazy`.
76
-
77
- 1.2.0 - [2013.11.21][1.2.0]
78
- ---------------------------
79
-
80
- Everything to date.