ns-options 0.4.1 → 1.0.0.rc1

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.
Files changed (51) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +2 -1
  3. data/LICENSE +1 -1
  4. data/README.md +187 -301
  5. data/Rakefile +1 -1
  6. data/lib/ns-options/assert_macros.rb +9 -12
  7. data/lib/ns-options/boolean.rb +2 -0
  8. data/lib/ns-options/namespace.rb +34 -134
  9. data/lib/ns-options/namespace_advisor.rb +35 -0
  10. data/lib/ns-options/namespace_data.rb +166 -0
  11. data/lib/ns-options/namespaces.rb +23 -12
  12. data/lib/ns-options/option.rb +50 -24
  13. data/lib/ns-options/options.rb +23 -49
  14. data/lib/ns-options/proxy.rb +40 -53
  15. data/lib/ns-options/proxy_method.rb +54 -0
  16. data/lib/ns-options/root_methods.rb +77 -0
  17. data/lib/ns-options/version.rb +1 -1
  18. data/lib/ns-options.rb +18 -8
  19. data/ns-options.gemspec +3 -4
  20. data/test/helper.rb +3 -10
  21. data/test/support/app.rb +3 -1
  22. data/test/support/proxy.rb +4 -0
  23. data/test/support/type_class_proxy.rb +29 -0
  24. data/test/support/user.rb +5 -5
  25. data/test/{integration/app_test.rb → system/app_tests.rb} +8 -6
  26. data/test/{integration/proxy_test.rb → system/proxy_tests.rb} +12 -0
  27. data/test/system/type_class_proxy_tests.rb +108 -0
  28. data/test/system/user_tests.rb +146 -0
  29. data/test/unit/{ns-options/boolean_test.rb → boolean_tests.rb} +5 -4
  30. data/test/unit/namespace_advisor_tests.rb +69 -0
  31. data/test/unit/namespace_data_tests.rb +336 -0
  32. data/test/unit/namespace_tests.rb +205 -0
  33. data/test/unit/namespaces_tests.rb +99 -0
  34. data/test/unit/{ns-options/option_test.rb → option_tests.rb} +155 -93
  35. data/test/unit/options_tests.rb +152 -0
  36. data/test/unit/proxy_method_tests.rb +87 -0
  37. data/test/unit/{ns-options/proxy_test.rb → proxy_tests.rb} +52 -0
  38. data/test/unit/root_methods_tests.rb +126 -0
  39. metadata +58 -63
  40. data/lib/ns-options/errors/invalid_name.rb +0 -15
  41. data/lib/ns-options/has_options.rb +0 -53
  42. data/lib/ns-options/helper/advisor.rb +0 -88
  43. data/lib/ns-options/helper.rb +0 -87
  44. data/test/integration/user_test.rb +0 -94
  45. data/test/unit/ns-options/has_options_test.rb +0 -90
  46. data/test/unit/ns-options/helper/advisor_test.rb +0 -148
  47. data/test/unit/ns-options/helper_test.rb +0 -56
  48. data/test/unit/ns-options/namespace_test.rb +0 -432
  49. data/test/unit/ns-options/namespaces_test.rb +0 -55
  50. data/test/unit/ns-options/options_test.rb +0 -221
  51. /data/test/unit/{ns-options/assert_macros_test.rb → assert_macros_tests.rb} +0 -0
@@ -141,6 +141,58 @@ module NsOptions::Proxy
141
141
  assert_equal @proxy2, @proxy1
142
142
  end
143
143
 
144
+ end
145
+
146
+ class DynamicOptionWriterTests < BaseTests
147
+ setup do
148
+ @mod = Module.new do
149
+ include NsOptions::Proxy
150
+
151
+ option :test
152
+ end
153
+ end
154
+ subject { @mod }
155
+
156
+ should "write non-pre-defined values as Object options" do
157
+ assert_not subject.has_option? :not_pre_defined
158
+ assert_responds_to :not_pre_defined=, subject
159
+ assert_not_responds_to :not_pre_defined, subject
160
+
161
+ assert_nothing_raised { subject.not_pre_defined = 123 }
162
+
163
+ assert subject.has_option? :not_pre_defined
164
+ assert_responds_to :not_pre_defined, subject
165
+
166
+ assert_equal 123, subject.not_pre_defined
167
+ assert_equal Object, subject.__data__.child_options['not_pre_defined'].type_class
168
+ end
169
+
170
+ end
171
+
172
+ class InheritedTests < BaseTests
173
+ desc "when inherited"
174
+ setup do
175
+ @a_super_class = Class.new do
176
+ include NsOptions::Proxy
177
+ option_type_class Fixnum
178
+
179
+ option :test
180
+ namespace(:other) { option :stuff }
181
+ end
182
+ end
183
+
184
+ should "pass its definition to any subclass" do
185
+ a_sub_class = Class.new(@a_super_class)
186
+
187
+ assert a_sub_class.has_option? :test
188
+ assert a_sub_class.has_namespace? :other
189
+ assert a_sub_class.other.has_option? :stuff
190
+
191
+ a_sub_ns_data = a_sub_class.__proxy_options__.__data__
192
+ assert_equal Fixnum, a_sub_ns_data.option_type_class
193
+ other_ns_data = a_sub_class.other.__data__
194
+ assert_equal Fixnum, other_ns_data.option_type_class
195
+ end
144
196
 
145
197
  end
146
198
 
@@ -0,0 +1,126 @@
1
+ require 'assert'
2
+ require 'ns-options/root_methods'
3
+ require 'ns-options/namespace'
4
+
5
+ class NsOptions::RootMethods
6
+
7
+ class BaseTests < Assert::Context
8
+ desc "NsOptions::RootMethods"
9
+ setup do
10
+ @rm = NsOptions::RootMethods.new(Module.new, 'whatever')
11
+ end
12
+ subject { @rm }
13
+
14
+ should have_imeths :define_on_class?, :define, :validate
15
+
16
+ end
17
+
18
+ class ValidateTests < BaseTests
19
+ desc "validate meth"
20
+ setup do
21
+ @io = StringIO.new(@out = "")
22
+ @caller = ["a test caller"]
23
+ end
24
+
25
+ should "return false for :options, :opts, :namespace, :ns names" do
26
+ [:options, :opts, :namespace, :ns].each do |meth|
27
+ rm = NsOptions::RootMethods.new(Module.new, meth)
28
+ assert_equal false, rm.validate(@io, @caller)
29
+ end
30
+
31
+ rm = NsOptions::RootMethods.new(Module.new, "anything_else")
32
+ assert_equal true, rm.validate(@io, @caller)
33
+ end
34
+
35
+ should "write a warning and any caller info" do
36
+ NsOptions::RootMethods.new(Module.new, :ns).validate(@io, @caller)
37
+
38
+ assert_match "WARNING: ", @out
39
+ assert_match @caller.first, @out
40
+ end
41
+
42
+ should "be called when calling `define'" do
43
+ NsOptions::RootMethods.new(Module.new, :ns).define(@io, @caller)
44
+
45
+ assert_match "WARNING: ", @out
46
+ assert_match @caller.first, @out
47
+ end
48
+
49
+ end
50
+
51
+ class ModuleTests < BaseTests
52
+ desc "defined on a module"
53
+ setup do
54
+ @rm = NsOptions::RootMethods.new(@the_module = Module.new, 'on_module')
55
+ @rm.define
56
+ end
57
+
58
+ should "know its not defining on a class" do
59
+ assert_not subject.define_on_class?
60
+ end
61
+
62
+ should "define a singleton method that builds a ns" do
63
+ assert_responds_to 'on_module', @the_module
64
+ assert_kind_of NsOptions::Namespace, @the_module.on_module
65
+ end
66
+
67
+ end
68
+
69
+ class ClassTests < BaseTests
70
+ desc "defined on a class"
71
+ setup do
72
+ @rm = NsOptions::RootMethods.new(@the_class = Class.new, 'on_class')
73
+ @rm.define
74
+ end
75
+
76
+ should "know its defining on a class" do
77
+ assert subject.define_on_class?
78
+ end
79
+
80
+ should "define a singleton method that builds a ns" do
81
+ assert_responds_to 'on_class', @the_class
82
+ ns = @the_class.on_class { option :opt1 }
83
+
84
+ assert_kind_of NsOptions::Namespace, ns
85
+ assert ns.__data__.has_option?(:opt1)
86
+ end
87
+
88
+ should "define an instance method that builds a ns from its singleton" do
89
+ @the_class.on_class { option :opt1 }
90
+ a_class = @the_class.new
91
+ assert_responds_to 'on_class', a_class
92
+ ns = a_class.on_class
93
+
94
+ assert_kind_of NsOptions::Namespace, ns
95
+ assert ns.__data__.has_option?(:opt1)
96
+ end
97
+
98
+ end
99
+
100
+ class InheritedClassTests < BaseTests
101
+ desc "when inherited"
102
+ setup do
103
+ @rm = NsOptions::RootMethods.new(@a_super_class = Class.new, 'a_ns')
104
+ @rm.define
105
+ @a_super_class.a_ns Fixnum do
106
+ option :test
107
+ namespace(:other) { option :stuff }
108
+ end
109
+ end
110
+
111
+ should "define a singleton method that builds a ns with the same def as its superclass" do
112
+ a_sub_class = Class.new(@a_super_class)
113
+
114
+ assert a_sub_class.a_ns.has_option? :test
115
+ assert a_sub_class.a_ns.has_namespace? :other
116
+ assert a_sub_class.a_ns.other.has_option? :stuff
117
+
118
+ a_sub_ns_data = a_sub_class.a_ns.__data__
119
+ assert_equal Fixnum, a_sub_ns_data.option_type_class
120
+ other_ns_data = a_sub_class.a_ns.other.__data__
121
+ assert_equal Fixnum, other_ns_data.option_type_class
122
+ end
123
+
124
+ end
125
+
126
+ end
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ns-options
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
5
- prerelease:
4
+ hash: -1692815510
5
+ prerelease: 6
6
6
  segments:
7
+ - 1
8
+ - 0
7
9
  - 0
8
- - 4
10
+ - rc
9
11
  - 1
10
- version: 0.4.1
12
+ version: 1.0.0.rc1
11
13
  platform: ruby
12
14
  authors:
13
15
  - Collin Redding
@@ -15,39 +17,24 @@ autorequire:
15
17
  bindir: bin
16
18
  cert_chain: []
17
19
 
18
- date: 2012-06-05 00:00:00 Z
20
+ date: 2012-11-19 00:00:00 Z
19
21
  dependencies:
20
22
  - !ruby/object:Gem::Dependency
21
- type: :development
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
23
+ name: assert
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
26
27
  - - ~>
27
28
  - !ruby/object:Gem::Version
28
- hash: 5
29
+ hash: 27
29
30
  segments:
30
31
  - 0
31
- - 7
32
- version: "0.7"
33
- version_requirements: *id001
34
- name: assert
35
- - !ruby/object:Gem::Dependency
32
+ - 8
33
+ version: "0.8"
36
34
  type: :development
35
+ requirement: *id001
37
36
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 9
44
- segments:
45
- - 0
46
- - 1
47
- version: "0.1"
48
- version_requirements: *id002
49
- name: assert-mocha
50
- description: Define and use namespaced options with a clean interface.
37
+ description: A DSL for defining, organizing and accessing options.
51
38
  email:
52
39
  - collin.redding@reelfx.com
53
40
  executables: []
@@ -65,36 +52,39 @@ files:
65
52
  - lib/ns-options.rb
66
53
  - lib/ns-options/assert_macros.rb
67
54
  - lib/ns-options/boolean.rb
68
- - lib/ns-options/errors/invalid_name.rb
69
- - lib/ns-options/has_options.rb
70
- - lib/ns-options/helper.rb
71
- - lib/ns-options/helper/advisor.rb
72
55
  - lib/ns-options/namespace.rb
56
+ - lib/ns-options/namespace_advisor.rb
57
+ - lib/ns-options/namespace_data.rb
73
58
  - lib/ns-options/namespaces.rb
74
59
  - lib/ns-options/option.rb
75
60
  - lib/ns-options/options.rb
76
61
  - lib/ns-options/proxy.rb
62
+ - lib/ns-options/proxy_method.rb
63
+ - lib/ns-options/root_methods.rb
77
64
  - lib/ns-options/version.rb
78
65
  - log/.gitkeep
79
66
  - ns-options.gemspec
80
67
  - test/helper.rb
81
- - test/integration/app_test.rb
82
- - test/integration/proxy_test.rb
83
- - test/integration/user_test.rb
84
68
  - test/irb.rb
85
69
  - test/support/app.rb
86
70
  - test/support/proxy.rb
71
+ - test/support/type_class_proxy.rb
87
72
  - test/support/user.rb
88
- - test/unit/ns-options/assert_macros_test.rb
89
- - test/unit/ns-options/boolean_test.rb
90
- - test/unit/ns-options/has_options_test.rb
91
- - test/unit/ns-options/helper/advisor_test.rb
92
- - test/unit/ns-options/helper_test.rb
93
- - test/unit/ns-options/namespace_test.rb
94
- - test/unit/ns-options/namespaces_test.rb
95
- - test/unit/ns-options/option_test.rb
96
- - test/unit/ns-options/options_test.rb
97
- - test/unit/ns-options/proxy_test.rb
73
+ - test/system/app_tests.rb
74
+ - test/system/proxy_tests.rb
75
+ - test/system/type_class_proxy_tests.rb
76
+ - test/system/user_tests.rb
77
+ - test/unit/assert_macros_tests.rb
78
+ - test/unit/boolean_tests.rb
79
+ - test/unit/namespace_advisor_tests.rb
80
+ - test/unit/namespace_data_tests.rb
81
+ - test/unit/namespace_tests.rb
82
+ - test/unit/namespaces_tests.rb
83
+ - test/unit/option_tests.rb
84
+ - test/unit/options_tests.rb
85
+ - test/unit/proxy_method_tests.rb
86
+ - test/unit/proxy_tests.rb
87
+ - test/unit/root_methods_tests.rb
98
88
  homepage:
99
89
  licenses: []
100
90
 
@@ -115,35 +105,40 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
105
  required_rubygems_version: !ruby/object:Gem::Requirement
116
106
  none: false
117
107
  requirements:
118
- - - ">="
108
+ - - ">"
119
109
  - !ruby/object:Gem::Version
120
- hash: 3
110
+ hash: 25
121
111
  segments:
122
- - 0
123
- version: "0"
112
+ - 1
113
+ - 3
114
+ - 1
115
+ version: 1.3.1
124
116
  requirements: []
125
117
 
126
118
  rubyforge_project:
127
- rubygems_version: 1.8.11
119
+ rubygems_version: 1.8.24
128
120
  signing_key:
129
121
  specification_version: 3
130
- summary: Define and use namespaced options with a clean interface.
122
+ summary: A DSL for defining, organizing and accessing options.
131
123
  test_files:
132
124
  - test/helper.rb
133
- - test/integration/app_test.rb
134
- - test/integration/proxy_test.rb
135
- - test/integration/user_test.rb
136
125
  - test/irb.rb
137
126
  - test/support/app.rb
138
127
  - test/support/proxy.rb
128
+ - test/support/type_class_proxy.rb
139
129
  - test/support/user.rb
140
- - test/unit/ns-options/assert_macros_test.rb
141
- - test/unit/ns-options/boolean_test.rb
142
- - test/unit/ns-options/has_options_test.rb
143
- - test/unit/ns-options/helper/advisor_test.rb
144
- - test/unit/ns-options/helper_test.rb
145
- - test/unit/ns-options/namespace_test.rb
146
- - test/unit/ns-options/namespaces_test.rb
147
- - test/unit/ns-options/option_test.rb
148
- - test/unit/ns-options/options_test.rb
149
- - test/unit/ns-options/proxy_test.rb
130
+ - test/system/app_tests.rb
131
+ - test/system/proxy_tests.rb
132
+ - test/system/type_class_proxy_tests.rb
133
+ - test/system/user_tests.rb
134
+ - test/unit/assert_macros_tests.rb
135
+ - test/unit/boolean_tests.rb
136
+ - test/unit/namespace_advisor_tests.rb
137
+ - test/unit/namespace_data_tests.rb
138
+ - test/unit/namespace_tests.rb
139
+ - test/unit/namespaces_tests.rb
140
+ - test/unit/option_tests.rb
141
+ - test/unit/options_tests.rb
142
+ - test/unit/proxy_method_tests.rb
143
+ - test/unit/proxy_tests.rb
144
+ - test/unit/root_methods_tests.rb
@@ -1,15 +0,0 @@
1
- module NsOptions
2
- module Errors
3
-
4
- class InvalidName < StandardError
5
- attr_accessor :message
6
-
7
- def initialize(message, backtrace)
8
- self.message = message
9
- self.set_backtrace(backtrace)
10
- end
11
-
12
- end
13
-
14
- end
15
- end
@@ -1,53 +0,0 @@
1
- module NsOptions
2
-
3
- module HasOptions
4
- class << self
5
-
6
- def included(klass)
7
- klass.class_eval do
8
- extend NsOptions::HasOptions::DSL
9
- end
10
- end
11
-
12
- end
13
-
14
- module DSL
15
-
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:
23
- #
24
- # class Something
25
- # include NsOptions
26
- # options(:settings) do
27
- # option :root
28
- # end
29
- # end
30
- #
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
-
42
- def options(name, key = nil, &block)
43
- NsOptions::Helper.advisor.is_this_namespace_ok?(name, caller)
44
- NsOptions::Helper.define_root_namespace_methods(self, name, key)
45
- self.send(name, &block)
46
- end
47
- alias_method :opts, :options
48
-
49
- end
50
-
51
- end
52
-
53
- end
@@ -1,88 +0,0 @@
1
- require 'ns-options/errors/invalid_name'
2
-
3
- module NsOptions
4
- module Helper
5
-
6
- class Advisor
7
- attr_accessor :namespace
8
-
9
- def initialize(namespace)
10
- self.namespace = namespace
11
- end
12
-
13
- # root namespace advisor
14
-
15
- def is_this_namespace_ok?(name, from = nil)
16
- if [:options].include?(name.to_sym)
17
- puts self.not_recommended_method_message('namespace', name)
18
- else
19
- return true
20
- end
21
- puts "From: #{(from || caller).first}"
22
- false
23
- end
24
-
25
- # sub-namespace / namespace-option advisors
26
-
27
- def is_this_sub_namespace_ok?(name, from = nil)
28
- self.is_this_ok?(:'sub-namespace', name, (from || caller))
29
- end
30
-
31
- def is_this_option_ok?(name, from = nil)
32
- self.is_this_ok?(:option, name, (from || caller))
33
- end
34
-
35
- # helper methods
36
-
37
- def is_this_ok?(kind, name, from)
38
- display = kind.to_s
39
- if self.bad_methods.include?(name.to_sym)
40
- message = self.bad_method_message(display, name)
41
- exception = NsOptions::Errors::InvalidName.new(message, from)
42
- raise(exception)
43
- elsif self.is_already_defined?(name)
44
- puts self.duplicate_message(name)
45
- elsif self.not_recommended_methods.include?(name.to_sym)
46
- puts self.not_recommended_method_message(display, name)
47
- else
48
- return true
49
- end
50
- puts "From: #{from.first}"
51
- false
52
- end
53
-
54
- def is_already_defined?(name)
55
- self.namespace.options.is_defined?(name) ||
56
- self.namespace.options.is_namespace_defined?(name)
57
- end
58
-
59
- def bad_methods
60
- @bad_methods ||= [ :option, :namespace, :define, :options ]
61
- end
62
-
63
- def not_recommended_methods
64
- @not_recommended_methods ||= NsOptions::Namespace.instance_methods(false).map(&:to_sym)
65
- end
66
-
67
- def bad_method_message(kind, name)
68
- [ "The #{kind} '#{name}' overwrites a namespace method that NsOptions depends on.",
69
- "Please choose a different name for your #{kind}."
70
- ].join(" ")
71
- end
72
-
73
- def duplicate_message(name)
74
- [ "WARNING! '#{name}' has already been defined and will be overwritten.",
75
- "It's likely that it will not behave as expected."
76
- ].join(" ")
77
- end
78
-
79
- def not_recommended_method_message(kind, name)
80
- [ "WARNING! The #{kind} '#{name}' overwrites a method NsOptions depends on.",
81
- "This will limit some of the functionality of NsOptions."
82
- ].join(" ")
83
- end
84
-
85
- end
86
-
87
- end
88
- end
@@ -1,87 +0,0 @@
1
- require 'ns-options/helper/advisor'
2
-
3
- module NsOptions
4
-
5
- module Helper
6
-
7
- module_function
8
-
9
- def find_and_define_namespace(namespace, name)
10
- sub_namespace = namespace.options.get_namespace(name)
11
- self.define_namespace_methods(namespace, name)
12
- sub_namespace
13
- end
14
-
15
- def define_namespace_methods(namespace, name)
16
- namespace.metaclass.class_eval <<-DEFINE_METHOD
17
-
18
- def #{name}(&block)
19
- namespace = self.options.namespaces.get("#{name}")
20
- namespace.define(&block) if block
21
- namespace
22
- end
23
-
24
- DEFINE_METHOD
25
- end
26
-
27
- def find_and_define_option(namespace, option_name)
28
- option = namespace.options[option_name]
29
- self.define_option_methods(namespace, option)
30
- option
31
- end
32
-
33
- def define_option_methods(namespace, option)
34
- namespace.metaclass.class_eval <<-DEFINE_METHOD
35
-
36
- def #{option.name}(*args)
37
- if !args.empty?
38
- self.send("#{option.name}=", *args)
39
- else
40
- self.options.get(:#{option.name})
41
- end
42
- end
43
-
44
- def #{option.name}=(*args)
45
- value = args.size == 1 ? args.first : args
46
- self.options.set(:#{option.name}, value)
47
- end
48
-
49
- DEFINE_METHOD
50
- end
51
-
52
- def advisor(namespace=nil)
53
- NsOptions::Helper::Advisor.new(namespace)
54
- end
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
-
85
- end
86
-
87
- end