ns-options 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/{README.markdown → README.md} +96 -23
- data/lib/ns-options/boolean.rb +12 -0
- data/lib/ns-options/has_options.rb +20 -30
- data/lib/ns-options/helper.rb +29 -0
- data/lib/ns-options/namespace.rb +2 -0
- data/lib/ns-options/option.rb +7 -1
- data/lib/ns-options/proxy.rb +62 -7
- data/lib/ns-options/version.rb +1 -1
- data/test/integration/app_test.rb +1 -2
- data/test/integration/proxy_test.rb +41 -0
- data/test/integration/user_test.rb +1 -2
- data/test/support/proxy.rb +21 -0
- data/test/unit/ns-options/boolean_test.rb +29 -1
- data/test/unit/ns-options/has_options_test.rb +1 -1
- data/test/unit/ns-options/helper_test.rb +12 -8
- data/test/unit/ns-options/namespace_test.rb +4 -1
- data/test/unit/ns-options/option_test.rb +70 -0
- data/test/unit/ns-options/proxy_test.rb +60 -9
- metadata +15 -10
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2011-Present Collin Redding, Kelly Redding and Team Insight
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
@@ -89,6 +89,28 @@ App.settings.server # => NoMethodError
|
|
89
89
|
App.settings.data.server # => 127.0.0.1:1234
|
90
90
|
```
|
91
91
|
|
92
|
+
### Less Verbose Definitions
|
93
|
+
|
94
|
+
As an alternative to the above definition syntax, you can use an alternate less-verbose syntax:
|
95
|
+
* `opts` for `options`
|
96
|
+
* `opt` for `option`
|
97
|
+
* `ns` for `namespace`
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
module App
|
101
|
+
include NsOptions
|
102
|
+
|
103
|
+
opts :settings do
|
104
|
+
opt :root, Pathname
|
105
|
+
opt :stage
|
106
|
+
|
107
|
+
ns :other_stuff do
|
108
|
+
opt :something
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
92
114
|
#### With Classes
|
93
115
|
|
94
116
|
Using `NsOptions` on a `Class` uses namespaces to create separate sets of options for every instance of your class created. This allows every instance to have different values for the set of options and not interfere with each other. For example with the following:
|
@@ -287,7 +309,44 @@ class Root < Pathname
|
|
287
309
|
end
|
288
310
|
```
|
289
311
|
|
290
|
-
With the revised `initialize` method, `NsOptions` will have no problems coercing values for
|
312
|
+
With the revised `initialize` method, `NsOptions` will have no problems coercing values for the type class. In some cases the above solution may not work for you, but don't worry. See the _Option Rules_ section for another way to solve this, specifically about the args rule. For an example of a custom type class, the included `NsOptions::Boolean` can be looked at. This is a special case, but it works as a type class with `NsOptions`.
|
313
|
+
|
314
|
+
### Custom type class return values
|
315
|
+
|
316
|
+
It may be useful to use a custom type class as a silent value handler. You don't necessarily care that this option is some handler class - you just want flexible ways to set its value and get a meaningful return value when you read it.
|
317
|
+
|
318
|
+
When reading option values, NsOptions will first check and see if the option value responds to the `returned_value` method. If it does, NsOptions will return that value instead of the instance of the type class. If not it will return the type class instance as normal.
|
319
|
+
|
320
|
+
The included `NsOptions::Boolean` handler class does just this to ensure it always returns either `true` or `false`. Here is another example:
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
class HostedAt
|
324
|
+
# sanitized :hosted_at config
|
325
|
+
# remove any trailing '/'
|
326
|
+
# ensure single leading '/'
|
327
|
+
|
328
|
+
def initialize(value)
|
329
|
+
@hosted_at = value.sub(/\/+$/, '').sub(/^\/*/, '/')
|
330
|
+
end
|
331
|
+
|
332
|
+
def returned_value
|
333
|
+
@hosted_at
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
class Thing
|
338
|
+
include NsOptions
|
339
|
+
|
340
|
+
options :is do
|
341
|
+
option :hosted_at, HostedAt
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
thing = Thing.new
|
346
|
+
thing.is.hosted_at # => nil
|
347
|
+
thing.is.hosted_at = "path/to/resource/"
|
348
|
+
thing.is.hosted_at # => "/path/to/resource"
|
349
|
+
```
|
291
350
|
|
292
351
|
### Ruby Classes As A Type Class
|
293
352
|
|
@@ -314,7 +373,7 @@ Example.stuff.float = "5.0"
|
|
314
373
|
Example.stuff.float # => 5.0, same as Float("5.0")
|
315
374
|
```
|
316
375
|
|
317
|
-
`Symbol`, `Hash` and `Array` work, but ruby doesn't provide
|
376
|
+
`Symbol`, `Hash` and `Array` work, but ruby doesn't provide built in type casting for these.
|
318
377
|
|
319
378
|
```ruby
|
320
379
|
Example.stuff.symbol = "awesome"
|
@@ -358,6 +417,8 @@ App.settings.required_set? # => true
|
|
358
417
|
|
359
418
|
To check if an option is set it will simply check if the value is not `nil`. If you are using a custom type class though, you can define an `is_set?` method and this will be used to check if an option is set.
|
360
419
|
|
420
|
+
The built in `required_set?` method checks to see if all the options for the namespace that have been marked `:required => true` are set. It does not recursively check any child namespaces.
|
421
|
+
|
361
422
|
#### Args
|
362
423
|
|
363
424
|
Another rule that you can specify is args. This allows you to pass more arguments to a type class.
|
@@ -387,7 +448,6 @@ Mix in NsOptions::Proxy to any module/class to make it proxy a namespace. This
|
|
387
448
|
|
388
449
|
```ruby
|
389
450
|
module Something
|
390
|
-
include NsOptions
|
391
451
|
include NsOptions::Proxy
|
392
452
|
|
393
453
|
# define options directly
|
@@ -431,27 +491,40 @@ module Something
|
|
431
491
|
end
|
432
492
|
```
|
433
493
|
|
434
|
-
|
494
|
+
### Proxy initialization
|
435
495
|
|
436
|
-
|
496
|
+
Mixing in Proxy with mixin a default initializer for you as well. This initializer allows you to call `new` on your proxy, passing it a hash of key-values. These key values will be applied to the proxy using the `Namespace#apply` logic. This allows you to use Proxy objects as option types and maintain the option type-casting and defaulting behavior.
|
437
497
|
|
438
|
-
|
439
|
-
obtaining a copy of this software and associated documentation
|
440
|
-
files (the "Software"), to deal in the Software without
|
441
|
-
restriction, including without limitation the rights to use,
|
442
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
443
|
-
copies of the Software, and to permit persons to whom the
|
444
|
-
Software is furnished to do so, subject to the following
|
445
|
-
conditions:
|
498
|
+
A Module example
|
446
499
|
|
447
|
-
|
448
|
-
|
500
|
+
```ruby
|
501
|
+
module Things
|
502
|
+
include NsOptions::Proxy
|
449
503
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
504
|
+
option :one
|
505
|
+
option :two
|
506
|
+
end
|
507
|
+
|
508
|
+
# proxy defines a `new` method that takes a hash arg and
|
509
|
+
# applies it to the proxy
|
510
|
+
t = Thing.new(:one => 1, :two => 2, :three => 3)
|
511
|
+
|
512
|
+
# the values have been applied
|
513
|
+
t.to_hash # => {:one => 1, :two => 2, :three => 3}
|
514
|
+
```
|
515
|
+
|
516
|
+
# A Class example
|
517
|
+
|
518
|
+
```
|
519
|
+
class Thing
|
520
|
+
include NsOptions::Proxy
|
521
|
+
|
522
|
+
option :one
|
523
|
+
option :two
|
524
|
+
end
|
525
|
+
|
526
|
+
# proxy defines an `initialize` method that takes a hash arg and
|
527
|
+
# applies it to the proxy
|
528
|
+
t = Thing.new(:one => 1, :two => 2, :three => 3)
|
529
|
+
t.to_hash # => {:one => 1, :two => 2, :three => 3}
|
530
|
+
```
|
data/lib/ns-options/boolean.rb
CHANGED
@@ -11,6 +11,18 @@ module NsOptions
|
|
11
11
|
@actual = self.convert(new_value)
|
12
12
|
end
|
13
13
|
|
14
|
+
def ==(other_boolean)
|
15
|
+
if other_boolean.kind_of?(Boolean)
|
16
|
+
self.actual == other_boolean.actual
|
17
|
+
else
|
18
|
+
self.actual == other_boolean
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def returned_value
|
23
|
+
self.actual
|
24
|
+
end
|
25
|
+
|
14
26
|
protected
|
15
27
|
|
16
28
|
def convert(value)
|
@@ -13,11 +13,13 @@ module NsOptions
|
|
13
13
|
|
14
14
|
module DSL
|
15
15
|
|
16
|
-
# This is the main DSL method for creating a namespace of options for your
|
17
|
-
# will define a class method for both classes and
|
18
|
-
# for classes. The namespace is
|
19
|
-
#
|
20
|
-
#
|
16
|
+
# This is the main DSL method for creating a namespace of options for your
|
17
|
+
# class/module. This will define a class method for both classes and
|
18
|
+
# modules and an additional instance method for classes. The namespace is
|
19
|
+
# then created and returned by calling the class method version. For
|
20
|
+
# classes, the instance method will build an entirely new namespace from
|
21
|
+
# the class level namespace. This is so when you define options at the
|
22
|
+
# class level:
|
21
23
|
#
|
22
24
|
# class Something
|
23
25
|
# include NsOptions
|
@@ -26,35 +28,23 @@ module NsOptions
|
|
26
28
|
# end
|
27
29
|
# end
|
28
30
|
#
|
29
|
-
# the namespaces at the instance level still get all the defined options,
|
30
|
-
# separate objects from the class and other instances.
|
31
|
-
# namespace at the module level.
|
31
|
+
# the namespaces at the instance level still get all the defined options,
|
32
|
+
# but are completely separate objects from the class and other instances.
|
33
|
+
# Modules only deal with a single namespace at the module level.
|
34
|
+
|
35
|
+
# The options method takes three args:
|
36
|
+
# * `name` : what to name the defined methods for accessing the namespace
|
37
|
+
# * `key` : (optional) what to key the created namespace objects with
|
38
|
+
# - defaults to `name`
|
39
|
+
# - useful if persisting namespaces into some key-value store
|
40
|
+
# * `block`: (optional) a predefined set of nested options and namespaces
|
41
|
+
|
32
42
|
def options(name, key = nil, &block)
|
33
43
|
NsOptions::Helper.advisor.is_this_namespace_ok?(name, caller)
|
34
|
-
|
35
|
-
method_definitions = <<-CLASS_METHOD
|
36
|
-
|
37
|
-
def self.#{name}(&block)
|
38
|
-
@#{name} ||= NsOptions::Namespace.new('#{key}', &block)
|
39
|
-
end
|
40
|
-
|
41
|
-
CLASS_METHOD
|
42
|
-
if self.kind_of?(Class)
|
43
|
-
method_definitions += <<-INSTANCE_METHOD
|
44
|
-
|
45
|
-
def #{name}(&block)
|
46
|
-
unless @#{name}
|
47
|
-
@#{name} = NsOptions::Namespace.new('#{key}', &block)
|
48
|
-
@#{name}.options.build_from(self.class.#{name}.options, @#{name})
|
49
|
-
end
|
50
|
-
@#{name}
|
51
|
-
end
|
52
|
-
|
53
|
-
INSTANCE_METHOD
|
54
|
-
end
|
55
|
-
self.class_eval(method_definitions)
|
44
|
+
NsOptions::Helper.define_root_namespace_methods(self, name, key)
|
56
45
|
self.send(name, &block)
|
57
46
|
end
|
47
|
+
alias_method :opts, :options
|
58
48
|
|
59
49
|
end
|
60
50
|
|
data/lib/ns-options/helper.rb
CHANGED
@@ -53,6 +53,35 @@ module NsOptions
|
|
53
53
|
NsOptions::Helper::Advisor.new(namespace)
|
54
54
|
end
|
55
55
|
|
56
|
+
def define_root_namespace_methods(define_on, name, key=nil)
|
57
|
+
key ||= name.to_s
|
58
|
+
|
59
|
+
# covers defining on Modules and at the class-level of Classes
|
60
|
+
method_definitions = <<-CLASS_METHOD
|
61
|
+
|
62
|
+
def self.#{name}(&block)
|
63
|
+
@#{name} ||= NsOptions::Namespace.new('#{key}', &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
CLASS_METHOD
|
67
|
+
|
68
|
+
if define_on.kind_of?(Class)
|
69
|
+
# covers defining at the instance-level of Classes
|
70
|
+
method_definitions += <<-INSTANCE_METHOD
|
71
|
+
|
72
|
+
def #{name}(&block)
|
73
|
+
unless @#{name}
|
74
|
+
@#{name} = NsOptions::Namespace.new('#{key}', &block)
|
75
|
+
@#{name}.options.build_from(self.class.#{name}.options, @#{name})
|
76
|
+
end
|
77
|
+
@#{name}
|
78
|
+
end
|
79
|
+
|
80
|
+
INSTANCE_METHOD
|
81
|
+
end
|
82
|
+
define_on.class_eval(method_definitions)
|
83
|
+
end
|
84
|
+
|
56
85
|
end
|
57
86
|
|
58
87
|
end
|
data/lib/ns-options/namespace.rb
CHANGED
@@ -37,6 +37,7 @@ module NsOptions
|
|
37
37
|
NsOptions::Helper.define_option_methods(self, option)
|
38
38
|
option
|
39
39
|
end
|
40
|
+
alias_method :opt, :option
|
40
41
|
|
41
42
|
# Define a namespace under this namespace. Firstly, a new key is constructured from this current
|
42
43
|
# namespace's key and the name for the new namespace. The namespace is then added to the
|
@@ -60,6 +61,7 @@ module NsOptions
|
|
60
61
|
NsOptions::Helper.define_namespace_methods(self, name)
|
61
62
|
namespace
|
62
63
|
end
|
64
|
+
alias_method :ns, :namespace
|
63
65
|
|
64
66
|
# The opposite of #to_hash. Takes a hash representation of options and namespaces and mass
|
65
67
|
# assigns option values.
|
data/lib/ns-options/option.rb
CHANGED
@@ -26,7 +26,13 @@ module NsOptions
|
|
26
26
|
# if reading a lazy_proc, call the proc and return its coerced return val
|
27
27
|
# otherwise, just return the stored value
|
28
28
|
def value
|
29
|
-
self.lazy_proc?(@value)
|
29
|
+
if self.lazy_proc?(@value)
|
30
|
+
self.coerce(@value.call)
|
31
|
+
elsif @value.respond_to?(:returned_value)
|
32
|
+
@value.returned_value
|
33
|
+
else
|
34
|
+
@value
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
# if setting a lazy_proc, just store the proc off to be called when read
|
data/lib/ns-options/proxy.rb
CHANGED
@@ -1,20 +1,38 @@
|
|
1
|
+
require 'ns-options'
|
2
|
+
|
1
3
|
module NsOptions::Proxy
|
2
4
|
|
3
5
|
# Mix this in to any module or class to make it proxy a namespace
|
4
6
|
# this means you can interact with the module/class/class-instance as
|
5
|
-
# if it were a namespace object itself.
|
7
|
+
# if it were a namespace object itself.
|
6
8
|
|
7
9
|
NAMESPACE = "__proxy_options__"
|
8
10
|
|
9
11
|
class << self
|
10
12
|
|
11
13
|
def included(receiver)
|
12
|
-
receiver
|
13
|
-
|
14
|
-
|
14
|
+
NsOptions::Helper.define_root_namespace_methods(receiver, NAMESPACE)
|
15
|
+
receiver.class_eval { extend ProxyMethods }
|
16
|
+
receiver.class_eval { include ProxyMethods } if receiver.kind_of?(Class)
|
17
|
+
|
18
|
+
# default initializer method
|
19
|
+
|
20
|
+
if receiver.kind_of?(Class)
|
21
|
+
receiver.class_eval do
|
22
|
+
|
23
|
+
def initialize(configs={})
|
24
|
+
self.apply(configs || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
else # Module
|
29
|
+
receiver.class_eval do
|
30
|
+
|
31
|
+
def self.new(configs={})
|
32
|
+
self.apply(configs || {})
|
33
|
+
end
|
15
34
|
|
16
|
-
|
17
|
-
include ProxyMethods
|
35
|
+
end
|
18
36
|
end
|
19
37
|
end
|
20
38
|
|
@@ -22,7 +40,44 @@ module NsOptions::Proxy
|
|
22
40
|
|
23
41
|
module ProxyMethods
|
24
42
|
|
25
|
-
#
|
43
|
+
# pass thru namespace methods to the proxied NAMESPACE handler
|
44
|
+
|
45
|
+
def option(*args, &block)
|
46
|
+
__proxy_options__.option(*args, &block)
|
47
|
+
end
|
48
|
+
alias_method :opt, :option
|
49
|
+
|
50
|
+
def namespace(*args, &block)
|
51
|
+
__proxy_options__.namespace(*args, &block)
|
52
|
+
end
|
53
|
+
alias_method :ns, :namespace
|
54
|
+
|
55
|
+
def apply(*args, &block)
|
56
|
+
__proxy_options__.apply(*args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_hash(*args, &block)
|
60
|
+
__proxy_options__.to_hash(*args, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def each(*args, &block)
|
64
|
+
__proxy_options__.each(*args, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def define(*args, &block)
|
68
|
+
__proxy_options__.define(*args, &block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def required_set?(*args, &block)
|
72
|
+
__proxy_options__.required_set?(*args, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid?(*args, &block)
|
76
|
+
__proxy_options__.valid?(*args, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
# for everything else, send to the proxied NAMESPACE handler
|
80
|
+
# at this point it really just enables setting dynamic options
|
26
81
|
|
27
82
|
def method_missing(meth, *args, &block)
|
28
83
|
if (po = self.__proxy_options__) && po.respond_to?(meth.to_s)
|
data/lib/ns-options/version.rb
CHANGED
@@ -61,8 +61,7 @@ module App
|
|
61
61
|
subject{ @module.settings.sub }
|
62
62
|
|
63
63
|
should "have set the run_commands option" do
|
64
|
-
|
65
|
-
assert_equal @run, subject.run_commands.actual
|
64
|
+
assert_equal @run, subject.run_commands
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'assert'
|
2
|
+
|
3
|
+
require 'ns-options/assert_macros'
|
4
|
+
require 'test/support/proxy'
|
5
|
+
|
6
|
+
class SomeProxyIntTests < Assert::Context
|
7
|
+
include NsOptions::AssertMacros
|
8
|
+
|
9
|
+
desc "the integration test proxy module"
|
10
|
+
setup do
|
11
|
+
@proxy = SomeProxy
|
12
|
+
end
|
13
|
+
subject { @proxy }
|
14
|
+
|
15
|
+
should have_option :some, SomeProxy::SomeThing, {
|
16
|
+
:default => {:value1 => 1}
|
17
|
+
}
|
18
|
+
|
19
|
+
should have_option :some_prime, SomeProxy::SomeThing, {
|
20
|
+
:default => {:value1 => 'one'}
|
21
|
+
}
|
22
|
+
|
23
|
+
should have_option :stuff, :default => []
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class SomeProxySomeThingTests < SomeProxyIntTests
|
28
|
+
desc ":some option"
|
29
|
+
setup do
|
30
|
+
@proxy_some = @proxy.some
|
31
|
+
end
|
32
|
+
subject { @proxy_some }
|
33
|
+
|
34
|
+
should have_namespace :more
|
35
|
+
should have_options :value1, :value2
|
36
|
+
|
37
|
+
should "have its :value1 defaulted" do
|
38
|
+
assert_equal 1, subject.value1
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -79,8 +79,7 @@ class User
|
|
79
79
|
end
|
80
80
|
|
81
81
|
should "have set show_messages" do
|
82
|
-
|
83
|
-
assert_equal false, subject.show_messages.actual
|
82
|
+
assert_equal false, subject.show_messages
|
84
83
|
end
|
85
84
|
|
86
85
|
should "have set the font_size" do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SomeProxy
|
2
|
+
include NsOptions::Proxy
|
3
|
+
|
4
|
+
class SomeThing
|
5
|
+
include NsOptions::Proxy
|
6
|
+
|
7
|
+
opt :value1
|
8
|
+
opt :value2
|
9
|
+
|
10
|
+
ns :more do
|
11
|
+
opt :other1
|
12
|
+
opt :other2
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
opt :some, SomeThing, :default => { :value1 => 1 }
|
18
|
+
opt :some_prime, SomeThing, :default => { :value1 => 'one' }
|
19
|
+
opt :stuff, :default => []
|
20
|
+
|
21
|
+
end
|
@@ -9,7 +9,17 @@ class NsOptions::Boolean
|
|
9
9
|
end
|
10
10
|
subject{ @boolean }
|
11
11
|
|
12
|
-
should
|
12
|
+
should have_accessor :actual
|
13
|
+
should have_reader :returned_value
|
14
|
+
|
15
|
+
should "return its handled value with the `actual` method" do
|
16
|
+
assert_equal true, subject.actual
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return its handled value with the `returned_value` method" do
|
20
|
+
assert_equal true, subject.returned_value
|
21
|
+
end
|
22
|
+
|
13
23
|
end
|
14
24
|
|
15
25
|
class WithTruthyValuesTest < BaseTest
|
@@ -80,4 +90,22 @@ class NsOptions::Boolean
|
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
93
|
+
class ComparatorTests < BaseTest
|
94
|
+
desc "when comparing for equality"
|
95
|
+
setup do
|
96
|
+
@true_bool = NsOptions::Boolean.new true
|
97
|
+
@false_bool = NsOptions::Boolean.new false
|
98
|
+
end
|
99
|
+
|
100
|
+
should "compare with other booleans" do
|
101
|
+
assert_equal NsOptions::Boolean.new(1), @true_bool
|
102
|
+
assert_equal NsOptions::Boolean.new(0), @false_bool
|
103
|
+
end
|
104
|
+
|
105
|
+
should "compare with true and false" do
|
106
|
+
assert_equal true, @true_bool
|
107
|
+
assert_equal false, @false_bool
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
83
111
|
end
|
@@ -9,15 +9,19 @@ module NsOptions::Helper
|
|
9
9
|
end
|
10
10
|
subject{ @module }
|
11
11
|
|
12
|
-
should
|
13
|
-
|
14
|
-
|
12
|
+
should have_instance_method :find_and_define_namespace
|
13
|
+
should have_instance_method :find_and_define_option
|
14
|
+
should have_instance_method :define_namespace_methods
|
15
|
+
should have_instance_method :define_option_methods
|
16
|
+
should have_instance_method :advisor
|
17
|
+
should have_instance_method :define_root_namespace_methods
|
18
|
+
|
15
19
|
should "return an instance of NsOptions::Helper::Advisor with a call to #advisor" do
|
16
20
|
advisor = subject.advisor(NsOptions::Namespace.new("something"))
|
17
21
|
assert_instance_of NsOptions::Helper::Advisor, advisor
|
18
22
|
end
|
19
23
|
end
|
20
|
-
|
24
|
+
|
21
25
|
class FindAndDefineOptionTest < BaseTest
|
22
26
|
desc "find_and_define_option method"
|
23
27
|
setup do
|
@@ -26,14 +30,14 @@ module NsOptions::Helper
|
|
26
30
|
@result = @module.find_and_define_option(@namespace, @option.name)
|
27
31
|
end
|
28
32
|
subject{ @namespace }
|
29
|
-
|
33
|
+
|
30
34
|
should "have defined reader/writer methods for the option and returned the option" do
|
31
35
|
assert_respond_to @option.name, subject
|
32
36
|
assert_respond_to "#{@option.name}=", subject
|
33
37
|
assert_equal @option, @result
|
34
38
|
end
|
35
|
-
end
|
36
|
-
|
39
|
+
end
|
40
|
+
|
37
41
|
class FindAndDefineNamespaceTest < BaseTest
|
38
42
|
desc "find_and_define_namespace method"
|
39
43
|
setup do
|
@@ -42,7 +46,7 @@ module NsOptions::Helper
|
|
42
46
|
@result = @module.find_and_define_namespace(@namespace, :else)
|
43
47
|
end
|
44
48
|
subject{ @namespace }
|
45
|
-
|
49
|
+
|
46
50
|
should "have defined reader method for the namespace and returned the namespace" do
|
47
51
|
assert_respond_to :else, subject
|
48
52
|
assert_equal subject.options.get_namespace(:else), @result
|
@@ -11,7 +11,10 @@ class NsOptions::Namespace
|
|
11
11
|
subject{ @namespace }
|
12
12
|
|
13
13
|
should have_accessors :metaclass, :options
|
14
|
-
should have_instance_methods :option, :
|
14
|
+
should have_instance_methods :option, :opt
|
15
|
+
should have_instance_methods :namespace, :ns
|
16
|
+
should have_instance_methods :required_set?, :valid?
|
17
|
+
should have_instance_methods :define, :apply
|
15
18
|
should have_instance_methods :to_hash, :each
|
16
19
|
|
17
20
|
should "have set it's metaclass accessor" do
|
@@ -17,18 +17,23 @@ class NsOptions::Option
|
|
17
17
|
should "have set the name" do
|
18
18
|
assert_equal "stage", subject.name
|
19
19
|
end
|
20
|
+
|
20
21
|
should "have set the type class" do
|
21
22
|
assert_equal String, subject.type_class
|
22
23
|
end
|
24
|
+
|
23
25
|
should "have set the rules" do
|
24
26
|
assert_equal(@rules, subject.rules)
|
25
27
|
end
|
28
|
+
|
26
29
|
should "have defaulted value based on the rules" do
|
27
30
|
assert_equal subject.rules[:default], subject.value
|
28
31
|
end
|
32
|
+
|
29
33
|
should "return true with a call to #required?" do
|
30
34
|
assert_equal true, subject.required?
|
31
35
|
end
|
36
|
+
|
32
37
|
should "allow setting the value to nil" do
|
33
38
|
subject.value = nil
|
34
39
|
assert_nil subject.value
|
@@ -151,11 +156,13 @@ class NsOptions::Option
|
|
151
156
|
subject.value = new_value
|
152
157
|
assert_equal new_value, subject.value
|
153
158
|
end
|
159
|
+
|
154
160
|
should "allow setting it's value with a string and convert it" do
|
155
161
|
new_value = "13.4"
|
156
162
|
subject.value = new_value
|
157
163
|
assert_equal new_value.to_f, subject.value
|
158
164
|
end
|
165
|
+
|
159
166
|
should "allow setting it's value with an integer and convert it" do
|
160
167
|
new_value = 1
|
161
168
|
subject.value = new_value
|
@@ -183,6 +190,7 @@ class NsOptions::Option
|
|
183
190
|
subject.value = value
|
184
191
|
assert_equal object_class.new.to_sym, subject.value
|
185
192
|
end
|
193
|
+
|
186
194
|
should "error on anything that doesn't define #to_sym" do
|
187
195
|
assert_raises(NoMethodError) do
|
188
196
|
subject.value = true
|
@@ -334,6 +342,68 @@ class NsOptions::Option
|
|
334
342
|
end
|
335
343
|
end
|
336
344
|
|
345
|
+
class WithReturnValueTests < BaseTest
|
346
|
+
setup do
|
347
|
+
# test control values
|
348
|
+
@string = NsOptions::Option.new(:string, String)
|
349
|
+
@symbol = NsOptions::Option.new(:symbol, Symbol)
|
350
|
+
@integer = NsOptions::Option.new(:integer, Integer)
|
351
|
+
@float = NsOptions::Option.new(:float, Float)
|
352
|
+
@hash = NsOptions::Option.new(:hash, Hash)
|
353
|
+
@array = NsOptions::Option.new(:array, Array)
|
354
|
+
@proc = NsOptions::Option.new(:proc, Proc)
|
355
|
+
@lazy_proc = NsOptions::Option.new(:lazy_proc)
|
356
|
+
|
357
|
+
# custom return value
|
358
|
+
class HostedAt
|
359
|
+
# sanitized :hosted_at config
|
360
|
+
# remove any trailing '/'
|
361
|
+
# ensure single leading '/'
|
362
|
+
|
363
|
+
def initialize(value)
|
364
|
+
@hosted_at = value.sub(/\/+$/, '').sub(/^\/*/, '/')
|
365
|
+
end
|
366
|
+
|
367
|
+
def returned_value
|
368
|
+
@hosted_at
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
@hosted_at = NsOptions::Option.new(:hosted_at, HostedAt)
|
373
|
+
end
|
374
|
+
|
375
|
+
should "return values normally when no `returned_value` is specified" do
|
376
|
+
@string.value = "test"
|
377
|
+
assert_equal "test", @string.value
|
378
|
+
|
379
|
+
@symbol.value = :test
|
380
|
+
assert_equal :test, @symbol.value
|
381
|
+
|
382
|
+
@integer.value = 1
|
383
|
+
assert_equal 1, @integer.value
|
384
|
+
|
385
|
+
@float.value = 1.1
|
386
|
+
assert_equal 1.1, @float.value
|
387
|
+
|
388
|
+
@hash.value = {:test => 'test'}
|
389
|
+
assert_equal({:test => 'test'}, @hash.value)
|
390
|
+
|
391
|
+
@array.value = ['test']
|
392
|
+
assert_equal ['test'], @array.value
|
393
|
+
|
394
|
+
@proc.value = Proc.new { 'test' }
|
395
|
+
assert_kind_of Proc, @proc.value
|
396
|
+
|
397
|
+
@lazy_proc.value = Proc.new { 'lazy test' }
|
398
|
+
assert_equal 'lazy test', @lazy_proc.value
|
399
|
+
end
|
400
|
+
|
401
|
+
should "should honor `returned_value` when returning option values" do
|
402
|
+
@hosted_at.value = "path/to/resource/"
|
403
|
+
assert_equal '/path/to/resource', @hosted_at.value
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
337
407
|
class WithArgsTest < BaseTest
|
338
408
|
desc "with args rule"
|
339
409
|
setup do
|
@@ -8,15 +8,22 @@ module NsOptions::Proxy
|
|
8
8
|
def self.proxy_a_namespace
|
9
9
|
Assert::Macro.new do
|
10
10
|
should "create a default namespace to proxy to" do
|
11
|
-
assert_respond_to
|
12
|
-
assert_kind_of NsOptions::Namespace, subject.send(
|
11
|
+
assert_respond_to '__proxy_options__', subject
|
12
|
+
assert_kind_of NsOptions::Namespace, subject.send('__proxy_options__')
|
13
13
|
end
|
14
14
|
|
15
|
-
should "respond to namespace methods" do
|
16
|
-
assert_respond_to :option,
|
17
|
-
assert_respond_to :
|
18
|
-
assert_respond_to :
|
19
|
-
assert_respond_to :
|
15
|
+
should "respond to proxied namespace methods" do
|
16
|
+
assert_respond_to :option, subject
|
17
|
+
assert_respond_to :opt, subject
|
18
|
+
assert_respond_to :namespace, subject
|
19
|
+
assert_respond_to :ns, subject
|
20
|
+
assert_respond_to :apply, subject
|
21
|
+
assert_respond_to :to_hash, subject
|
22
|
+
assert_respond_to :each, subject
|
23
|
+
assert_respond_to :define, subject
|
24
|
+
assert_respond_to :inspect, subject
|
25
|
+
assert_respond_to :required_set?, subject
|
26
|
+
assert_respond_to :valid?, subject
|
20
27
|
end
|
21
28
|
|
22
29
|
should "create options directly" do
|
@@ -41,22 +48,45 @@ module NsOptions::Proxy
|
|
41
48
|
desc "when mixed in to a module"
|
42
49
|
setup do
|
43
50
|
@mod = Module.new do
|
44
|
-
include NsOptions
|
45
51
|
include NsOptions::Proxy
|
52
|
+
|
53
|
+
option :test
|
46
54
|
end
|
47
55
|
end
|
48
56
|
subject { @mod }
|
49
57
|
|
50
58
|
should proxy_a_namespace
|
51
59
|
|
60
|
+
should "allow building from a hash of key-values" do
|
61
|
+
subject.new('test' => 1, 'more' => 2)
|
62
|
+
|
63
|
+
assert_equal 1, subject.test
|
64
|
+
assert_equal 2, subject.more
|
65
|
+
end
|
66
|
+
|
67
|
+
should "take `new` method overrides" do
|
68
|
+
@newmod = Module.new do
|
69
|
+
include NsOptions::Proxy
|
70
|
+
|
71
|
+
def self.new
|
72
|
+
# nothing
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_raises ArgumentError do
|
77
|
+
@newmod.new('test' => 1, 'more' => 2)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
52
81
|
end
|
53
82
|
|
54
83
|
class ClassTests < BaseTests
|
55
84
|
desc "when mixed into a class"
|
56
85
|
setup do
|
57
86
|
@cls = Class.new do
|
58
|
-
include NsOptions
|
59
87
|
include NsOptions::Proxy
|
88
|
+
|
89
|
+
option :test
|
60
90
|
end
|
61
91
|
end
|
62
92
|
|
@@ -72,6 +102,27 @@ module NsOptions::Proxy
|
|
72
102
|
subject { @cls.new }
|
73
103
|
should proxy_a_namespace
|
74
104
|
|
105
|
+
should "allow building from a hash of key-values" do
|
106
|
+
thing = @cls.new(:test => 1, :more => 2)
|
107
|
+
|
108
|
+
assert_equal 1, thing.test
|
109
|
+
assert_equal 2, thing.more
|
110
|
+
end
|
111
|
+
|
112
|
+
should "take init method overrides" do
|
113
|
+
@newcls = Class.new do
|
114
|
+
include NsOptions::Proxy
|
115
|
+
|
116
|
+
def initialize
|
117
|
+
# nothing
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
assert_raises ArgumentError do
|
122
|
+
@newcls.new('test' => 1, 'more' => 2)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
75
126
|
end
|
76
127
|
|
77
128
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ns-options
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Collin Redding
|
@@ -15,10 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-05-21 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :development
|
22
|
+
prerelease: false
|
22
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
24
|
none: false
|
24
25
|
requirements:
|
@@ -29,11 +30,11 @@ dependencies:
|
|
29
30
|
- 0
|
30
31
|
- 7
|
31
32
|
version: "0.7"
|
32
|
-
prerelease: false
|
33
|
-
name: assert
|
34
33
|
version_requirements: *id001
|
34
|
+
name: assert
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
type: :development
|
37
|
+
prerelease: false
|
37
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
39
|
none: false
|
39
40
|
requirements:
|
@@ -44,9 +45,8 @@ dependencies:
|
|
44
45
|
- 0
|
45
46
|
- 1
|
46
47
|
version: "0.1"
|
47
|
-
prerelease: false
|
48
|
-
name: assert-mocha
|
49
48
|
version_requirements: *id002
|
49
|
+
name: assert-mocha
|
50
50
|
description: Define and use namespaced options with a clean interface.
|
51
51
|
email:
|
52
52
|
- collin.redding@reelfx.com
|
@@ -59,7 +59,8 @@ extra_rdoc_files: []
|
|
59
59
|
files:
|
60
60
|
- .gitignore
|
61
61
|
- Gemfile
|
62
|
-
-
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
63
64
|
- Rakefile
|
64
65
|
- lib/ns-options.rb
|
65
66
|
- lib/ns-options/assert_macros.rb
|
@@ -78,9 +79,11 @@ files:
|
|
78
79
|
- ns-options.gemspec
|
79
80
|
- test/helper.rb
|
80
81
|
- test/integration/app_test.rb
|
82
|
+
- test/integration/proxy_test.rb
|
81
83
|
- test/integration/user_test.rb
|
82
84
|
- test/irb.rb
|
83
85
|
- test/support/app.rb
|
86
|
+
- test/support/proxy.rb
|
84
87
|
- test/support/user.rb
|
85
88
|
- test/unit/ns-options/assert_macros_test.rb
|
86
89
|
- test/unit/ns-options/boolean_test.rb
|
@@ -128,9 +131,11 @@ summary: Define and use namespaced options with a clean interface.
|
|
128
131
|
test_files:
|
129
132
|
- test/helper.rb
|
130
133
|
- test/integration/app_test.rb
|
134
|
+
- test/integration/proxy_test.rb
|
131
135
|
- test/integration/user_test.rb
|
132
136
|
- test/irb.rb
|
133
137
|
- test/support/app.rb
|
138
|
+
- test/support/proxy.rb
|
134
139
|
- test/support/user.rb
|
135
140
|
- test/unit/ns-options/assert_macros_test.rb
|
136
141
|
- test/unit/ns-options/boolean_test.rb
|