option_list 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +15 -0
  2. data/option_list.rb +260 -0
  3. data/option_list_test.rb +244 -0
  4. metadata +49 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTZjYWUzNDczZmFlZTFhNTNlNTU0YmEzZjYzNGM1OTUzZDJmNTdjNw==
5
+ data.tar.gz: !binary |-
6
+ OTljOTcyODI0MDIyNzgxYjE3ZTkzNjQyOWUwZDk5NTgyZGVjYTAzMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ODg1OWYxZGU0YmU1MmYyYjRmMTZlOGE1NGZlYWYzMDlmOTY2MjRlZmM1NzM3
10
+ YTRjODM2ZDUyYzk2MDRiOGY3OWY3MmM4Zjk4ZTJiMWU3ZTRkMDcyZDQwZmZk
11
+ OWUwMzRiYTMyNjcyZmZmNzYzOGYyMGZmMWNmZmQ3OWQyM2JhMGU=
12
+ data.tar.gz: !binary |-
13
+ Y2VhZjdhNDFhMjlhNDdlZjRjNTJhMmFkM2NlMTE4YTg5YzE4YmVkYWY5M2I0
14
+ NmVmMWFhMWE0OWQ1YTdlZDEyNmZkZDNkZWI3MjM4NjFhYmEwNjFlNGIxZWJi
15
+ MDU0OTMwODUyNDQzZDI5ZGQzN2MyYmUyZGU2ZGRiODk3MWIxNzA=
data/option_list.rb ADDED
@@ -0,0 +1,260 @@
1
+ require 'set'
2
+
3
+ #=== The MIT License (MIT).
4
+ #
5
+ #Copyright (c) 2013 Peter Camilleri
6
+ #
7
+ #Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ #of this software and associated documentation files (the "Software"), to deal
9
+ #in the Software without restriction, including without limitation the rights
10
+ #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ #copies of the Software, and to permit persons to whom the Software is
12
+ #furnished to do so, subject to the following conditions:
13
+ #
14
+ #The above copyright notice and this permission notice shall be included in
15
+ #all copies or substantial portions of the Software.
16
+ #
17
+ #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ #THE SOFTWARE.
24
+ #
25
+ #=== The file option_list.rb and the class \OptionList.
26
+ #This file contains the code for the \OptionList class that implements smart
27
+ #and easy options for functions. It has the virtue of defining function
28
+ #options clearly in a single place instead of spread out in complex code.
29
+ #A classic but unclear sequence in many functions is the use of boolean values
30
+ #to control or switch on or off some option. For example consider the well
31
+ #known readline function:
32
+ # cmd = readline(">", false)
33
+ #See the boolean at the end? It says "false". What is "false"? Who knows? You
34
+ #need to dig deeper or guess or just cut and paste without understanding. What
35
+ #if, instead, the code looked like:
36
+ # cmd = readline(">", :nohistory)
37
+ #The boolean has been replaced by something a lot clearer. The problem with
38
+ #such clarity is that it involves a lot more effort than the lazy boolean. The
39
+ #\OptionList class aims to solve that issue by making useful, flexible options
40
+ #just about as easy to use as the lazy way.
41
+ #==== Warning: This code is most opinionated! ;-)
42
+ #The philosophy and opinion expressed through this code is that errors should
43
+ #be detected as close to the point of error as possible and that an error is
44
+ #preferable to running with potentially incorrect results. As a result, it
45
+ #will be noted that the programmer does not hesitate to use the fAE, a wrapper
46
+ #of the "fail" keyword, liberally throughout the code to achieve this end.
47
+ #Complimentary to this is the idea that the library (gem) writer should do as
48
+ #much of the "heavy lifting" as possible, with clear, detailed documentation so
49
+ #that the library (gem) user does not have to work hard or be lost or confused.
50
+ #Only time will tell to what extent these lofty goals have been achieved.
51
+ #Hopefully, with good feedback, this and other code libraries will improve.
52
+ class OptionList
53
+ #An internal marker for value entries.
54
+ VALUE_ENTRY = 'A value entry.'
55
+
56
+ #Create an option list from an array of option specs. These specs consist of
57
+ #a number of array specifications and hash specifications.
58
+ #==== Array Specification
59
+ #In the array form of specification, the first element of the array is the
60
+ #category of the option, and the subsequent entries are the allowed values
61
+ #for that category. The first of these values is the default value for the
62
+ #category. This may be nil to have no default value. The symbols used in each
63
+ #category must be unique. Duplicates will fail with an ArgumentError.
64
+ #==== Hash Specification
65
+ #In the hash form of specification, the key is the category and the value
66
+ #is the default value. There is no list of allowed values in this case.
67
+ #==== Example:
68
+ # @opt_list = OptionList.new([:history, :history, :nohistory], {:page_len => 42})
69
+ #==== Parameters:
70
+ #* option_specs - The comma separated option specs, made into an array by the
71
+ # splat operator.
72
+ #==== Dynamic Methods:
73
+ #As option specs are added, new methods are created to allow for easy access
74
+ #to the option information. If the above example were processed, the following
75
+ #methods would be added:
76
+ #* history - would return the value of the :history category.
77
+ #* history? - would return true if the :history option where active.
78
+ #* nohistory? - would return true if the :nohistory option were active.
79
+ #* page_len - would return the value of the :page_len category.
80
+ #==== Exceptions:
81
+ #* ArgumentError for a number of invalid argument conditions.
82
+ def initialize(*option_specs)
83
+ @categories = Hash.new
84
+ @default = Hash.new
85
+ @selected = Hash.new
86
+ do_add_specs(option_specs)
87
+ end
88
+
89
+ #Add additonal option specifications to the option list. See the method new
90
+ #for more information on those specifications.
91
+ def add_specs(*option_specs)
92
+ do_add_specs(option_specs)
93
+ end
94
+
95
+ private #Private methods follow.
96
+
97
+ #Iterate over the array of specs, adding them to the option list.
98
+ def do_add_specs(option_specs)
99
+ option_specs.each do |spec|
100
+ if spec.is_a?(Hash)
101
+ hash_spec(spec)
102
+ elsif spec.is_a?(Array)
103
+ array_spec(spec)
104
+ else
105
+ fAE "Found #{spec.class} instead of Hash or Array."
106
+ end
107
+ end
108
+ end
109
+
110
+ #Process an array spec that lists all the valid values for an option. See
111
+ #the new method for more information on these specs.
112
+ def array_spec(spec)
113
+ cat = spec.delete_at(0)
114
+ fAE "Found #{cat.class}, expected Symbol." unless cat.is_a?(Symbol)
115
+ fAE "Duplicate category: #{cat}" if @default.has_key?(cat)
116
+ fAE "Invalid number of entries for #{cat}." unless spec.length > 1
117
+ define_singleton_method(cat) { @selected[cat] }
118
+
119
+ spec.each_with_index do |opt, index|
120
+ if opt != nil
121
+ fAE "Found #{opt.class}, expected Symbol." unless opt.is_a?(Symbol)
122
+ fAE "Duplicate option: #{opt}" if @categories.has_key?(opt)
123
+
124
+ @categories[opt] = cat
125
+ qry = (opt.to_s + '?').to_sym
126
+ define_singleton_method(qry) { @selected[cat] == opt }
127
+ @selected[cat] = @default[cat] = opt if index == 0
128
+ elsif index == 0
129
+ @selected[cat] = @default[cat] = nil
130
+ else
131
+ fAE "The value nil is only allowed as the default option."
132
+ end
133
+ end
134
+ end
135
+
136
+ #Process a hash spec that lists only the default value for an option. See
137
+ #the new method for more information on these specs.
138
+ def hash_spec(spec)
139
+ fAE "Hash contains no specs." unless spec.length > 0
140
+
141
+ spec.each do |cat, value|
142
+ fAE "Found #{cat.class}, expected Symbol." unless cat.is_a?(Symbol)
143
+ fAE "Duplicate category: #{cat}" if @default.has_key?(cat)
144
+
145
+ define_singleton_method(cat) { @selected[cat] }
146
+ @categories[cat] = VALUE_ENTRY
147
+ @selected[cat] = @default[cat] = value
148
+ end
149
+ end
150
+
151
+ public #Back to public methods.
152
+
153
+ #From the possible options, select the actual, in force, options for use in
154
+ #the code. These options may take several forms:
155
+ #=== Types of option data:
156
+ #* A symbol - For categories with a specified symbol list, simply list one
157
+ # of the allowed symbols.
158
+ #* A hash - For any type of category, a hash may be used in the the form
159
+ # {category => value}. Note that for categories with a specified symbol list
160
+ # the value must be a symbol in the list.
161
+ #* Mixed - Symbols and hashes can be mixed in an array (see below on how this
162
+ # is done) Note: Option order does not matter.
163
+ #Some examples:
164
+ # foo(:sedan, :turbo)
165
+ # foo({:style=>:sedan})
166
+ # foo({:page_len=>60})
167
+ # foo(:sedan, :turbo, {:page_len=>60})
168
+ # foo({:style=>:sedan, :page_len=>60})
169
+ # foo({:style=>:sedan}, {:page_len=>60})
170
+ #=== Passing in option data:
171
+ #The caller of this method may pass these options in a number of ways:
172
+ #==== Array (via a splat)
173
+ #Given the example shown in the new method, consider:
174
+ # def test(count, *opt)
175
+ # @opt_list.select(opt)
176
+ # #etc, etc, etc...
177
+ # end
178
+ #With the caller now looking like:
179
+ # test(43, :history)
180
+ #==== Array (explicit)
181
+ #An alternative strategy, where the use of splat is not desired, is to simply
182
+ #have an array argument, as below:
183
+ # def test(*arg1, opt)
184
+ # @opt_list.select(opt)
185
+ # #etc, etc, etc...
186
+ # end
187
+ #With the caller now looking like:
188
+ # test(34, 53, 76, 'hike!', [:history])
189
+ #==== Hash
190
+ #Options may also be passed via a hash.
191
+ # test(34, 53, 76, 'hike!', {:history=>:history, :page_len=>55})
192
+ #==== Symbol
193
+ #If only a single option is required, it can be passed simply as:
194
+ # test(34, 53, 76, 'hike!', :history)
195
+ #==== Parameters:
196
+ #* selections - An array of the options passed into the client function, usually
197
+ # with the splat operator. Note that if select is called with no arguments,
198
+ # all of the default values will be selected.
199
+ #==== Exceptions:
200
+ #* ArgumentError for a number of invalid argument conditions.
201
+ def select(selections=[])
202
+ @selected = @default.clone
203
+ add_selections(selections)
204
+ end
205
+
206
+ #Add/override additional selections to the option_list. See the select method
207
+ #for more information about those selection values.
208
+ def add_selections(selections=[])
209
+ selections = [selections] unless selections.is_a?(Array)
210
+ dup = Set.new
211
+
212
+ selections.each do |opt|
213
+ if opt.is_a?(Symbol)
214
+ symbolic_selection(opt, dup)
215
+ elsif opt.is_a?(Hash)
216
+ hash_selections(opt, dup)
217
+ else
218
+ fAE "Found #{opt.class} instead of Hash or Symbol."
219
+ end
220
+ end
221
+ end
222
+
223
+ private #Some more privacy, please!
224
+
225
+ #Process a symbolic option selection.
226
+ #==== Parameters:
227
+ #* option - a symbol to process.
228
+ #* dup - a set of categories that have been set. Used to detect duplicates.
229
+ def symbolic_selection(option, dup)
230
+ fAE "Unknown option: #{option}." unless @categories.has_key?(option)
231
+ cat = @categories[option]
232
+ fAE "Category #{cat} has multiple values." if dup.include?(cat)
233
+ dup.add(cat)
234
+ @selected[cat] = option
235
+ end
236
+
237
+ #Process a hash of option selection values.
238
+ #==== Parameters:
239
+ #* options - a hash of options to process.
240
+ #* dup - a set of categories that have been set. Used to detect duplicates.
241
+ def hash_selections(options, dup)
242
+ options.each do |cat, value|
243
+ fAE "Not a category: #{cat}." unless @default.has_key?(cat)
244
+ fAE "Category #{cat} has multiple values." if dup.include?(cat)
245
+
246
+ unless (@categories[cat] == VALUE_ENTRY) || value.nil?
247
+ fAE "Found #{opt.class}, expected Symbol." unless value.is_a?(Symbol)
248
+ fAE "Invalid option: #{value}." unless @categories[value] == cat
249
+ end
250
+
251
+ dup.add(cat)
252
+ @selected[cat] = value
253
+ end
254
+ end
255
+
256
+ #Fail with an argument error.
257
+ def fAE(msg)
258
+ fail(ArgumentError, msg, caller)
259
+ end
260
+ end
@@ -0,0 +1,244 @@
1
+ #A formal testing frame for the option list class.
2
+ #Execute this file to perform the tests.
3
+
4
+ require_relative 'option_list'
5
+ require 'minitest/autorun'
6
+
7
+ class OptionListTester < MiniTest::Unit::TestCase
8
+ def setup
9
+ @ol1 = OptionList.new([:history, :history, :nohistory], {:pg_len => 42})
10
+ @ol2 = OptionList.new([:history, nil, :history, :nohistory])
11
+ end
12
+
13
+ def test_that_it_rejects_bad_specs
14
+ #Reject empty argument lists.
15
+ assert_raises(ArgumentError) { @x = OptionList.new([])}
16
+ assert_raises(ArgumentError) { @x = OptionList.new({})}
17
+
18
+ #Reject if not an array or a hash.
19
+ assert_raises(ArgumentError) { @x = OptionList.new(4) }
20
+ assert_raises(ArgumentError) { @x = OptionList.new('foobar') }
21
+
22
+ #Reject for too few arguments.
23
+ assert_raises(ArgumentError) { @x = OptionList.new([]) }
24
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo]) }
25
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :bar]) }
26
+
27
+ #Reject for the wrong types of arguments.
28
+ assert_raises(ArgumentError) { @x = OptionList.new(['foo', :foo, :bar] )}
29
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, 'foo', :bar] )}
30
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :foo, 'bar'])}
31
+ assert_raises(ArgumentError) { @x = OptionList.new({'foo' => 42})}
32
+
33
+ #Reject for duplicate categories.
34
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :lala, :bar], [:foo, :kung, :east]) }
35
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :lala, :bar], {:foo => :kung}) }
36
+ assert_raises(ArgumentError) { @x = OptionList.new({:foo => :lala}, {:foo => :kung}) }
37
+ #The following is not detectable since :foo => :kung overwrites :foo => :lala
38
+ #assert_raises(ArgumentError) { @x = OptionList.new({:foo => :lala, :foo => :kung}) }
39
+
40
+ #Reject for duplicate options.
41
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :bar, :bar]) }
42
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :foo, :bar], [:bla, :food, :bar]) }
43
+
44
+ #Reject for nil in the wrong position.
45
+ assert_raises(ArgumentError) { @x = OptionList.new([:foo, :bar, nil]) }
46
+ end
47
+
48
+ def test_that_the_methods_were_added
49
+ assert_respond_to(@ol1, :history)
50
+ assert_respond_to(@ol1, :history? )
51
+ assert_respond_to(@ol1, :nohistory? )
52
+ assert_respond_to(@ol1, :pg_len)
53
+
54
+ assert_respond_to(@ol2, :history)
55
+ assert_respond_to(@ol2, :history? )
56
+ assert_respond_to(@ol2, :nohistory? )
57
+ assert_raises(NoMethodError) { @ol2.send((nil.to_s+'?').to_sym) }
58
+ end
59
+
60
+ def test_that_it_rejects_bad_added_specs
61
+ #reject a bad addition...
62
+ assert_raises(ArgumentError) {@ol1.add_specs({:history=>'fun'})}
63
+ #but don't mess up.
64
+ assert(@ol1.history?)
65
+ refute(@ol1.nohistory?)
66
+ assert_equal(@ol1.history, :history)
67
+ assert_equal(@ol1.pg_len, 42)
68
+
69
+ #reject a bad addition...
70
+ assert_raises(ArgumentError) {@ol1.add_specs({:pg_len=>66})}
71
+ #but don't mess up.
72
+ assert(@ol1.history?)
73
+ refute(@ol1.nohistory?)
74
+ assert_equal(@ol1.history, :history)
75
+ assert_equal(@ol1.pg_len, 42)
76
+ end
77
+
78
+ def test_that_it_rejects_bad_selections
79
+ #Reject if options are not an array or a hash.
80
+ assert_raises(ArgumentError) { @ol1.select(45) }
81
+
82
+ #Reject if the option is not a symbol.
83
+ assert_raises(ArgumentError) { @ol1.select([34]) }
84
+
85
+ #Reject if the category is not a symbol.
86
+ assert_raises(ArgumentError) { @ol1.select({'page_len'=>77}) }
87
+
88
+ #Reject if the symbol is not one defined.
89
+ assert_raises(ArgumentError) { @ol1.select([:foobar]) }
90
+ assert_raises(ArgumentError) { @ol1.select({:history=>:foobar}) }
91
+
92
+ #Reject on duplicate symbol from the same category.
93
+ assert_raises(ArgumentError) { @ol1.select([:history, :history]) }
94
+ assert_raises(ArgumentError) { @ol1.select([:history, :nohistory]) }
95
+ assert_raises(ArgumentError) { @ol1.select([:history, {:history=>:nohistory}]) }
96
+ assert_raises(ArgumentError) { @ol1.select([{:history=>:history}, {:history=>:nohistory}]) }
97
+
98
+ #Reject on an undefined category.
99
+ assert_raises(ArgumentError) { @ol1.select({:zoo => 999})}
100
+ end
101
+
102
+ def test_that_it_handles_good_options
103
+ #ol1 test series.
104
+ assert(@ol1.history?)
105
+ refute(@ol1.nohistory?)
106
+ assert_equal(@ol1.history, :history)
107
+ assert_equal(@ol1.pg_len, 42)
108
+
109
+ @ol1.select
110
+ assert(@ol1.history?)
111
+ refute(@ol1.nohistory?)
112
+ assert_equal(@ol1.history, :history)
113
+ assert_equal(@ol1.pg_len, 42)
114
+
115
+ @ol1.select([])
116
+ assert(@ol1.history?)
117
+ refute(@ol1.nohistory?)
118
+ assert_equal(@ol1.history, :history)
119
+ assert_equal(@ol1.pg_len, 42)
120
+
121
+ @ol1.select([:history])
122
+ assert(@ol1.history?)
123
+ refute(@ol1.nohistory?)
124
+ assert_equal(@ol1.history, :history)
125
+ assert_equal(@ol1.pg_len, 42)
126
+
127
+ @ol1.select([:nohistory])
128
+ assert(@ol1.nohistory?)
129
+ refute(@ol1.history?)
130
+ assert_equal(@ol1.history, :nohistory)
131
+ assert_equal(@ol1.pg_len, 42)
132
+
133
+ @ol1.select({:history=>:history})
134
+ assert(@ol1.history?)
135
+ refute(@ol1.nohistory?)
136
+ assert_equal(@ol1.history, :history)
137
+ assert_equal(@ol1.pg_len, 42)
138
+
139
+ @ol1.select({:history=>:nohistory})
140
+ assert(@ol1.nohistory?)
141
+ refute(@ol1.history?)
142
+ assert_equal(@ol1.history, :nohistory)
143
+ assert_equal(@ol1.pg_len, 42)
144
+
145
+ @ol1.select({:pg_len=>55})
146
+ assert(@ol1.history?)
147
+ refute(@ol1.nohistory?)
148
+ assert_equal(@ol1.history, :history)
149
+ assert_equal(@ol1.pg_len, 55)
150
+
151
+ @ol1.select({:history=>:history, :pg_len=>55})
152
+ assert(@ol1.history?)
153
+ refute(@ol1.nohistory?)
154
+ assert_equal(@ol1.history, :history)
155
+ assert_equal(@ol1.pg_len, 55)
156
+
157
+ @ol1.select({:history=>:nohistory, :pg_len=>55})
158
+ assert(@ol1.nohistory?)
159
+ refute(@ol1.history?)
160
+ assert_equal(@ol1.history, :nohistory)
161
+ assert_equal(@ol1.pg_len, 55)
162
+
163
+ @ol1.select([:history, {:pg_len=>55}])
164
+ assert(@ol1.history?)
165
+ refute(@ol1.nohistory?)
166
+ assert_equal(@ol1.history, :history)
167
+ assert_equal(@ol1.pg_len, 55)
168
+
169
+ @ol1.select([:nohistory, {:pg_len=>55}])
170
+ assert(@ol1.nohistory?)
171
+ refute(@ol1.history?)
172
+ assert_equal(@ol1.history, :nohistory)
173
+ assert_equal(@ol1.pg_len, 55)
174
+
175
+ @ol1.add_specs([:temp, nil, :hot, :nice, :cold])
176
+ @ol1.select #Restore to default values.
177
+ assert(@ol1.history?)
178
+ refute(@ol1.nohistory?)
179
+ assert_equal(@ol1.history, :history)
180
+ assert_equal(@ol1.pg_len, 42)
181
+ refute(@ol1.hot?)
182
+ refute(@ol1.nice?)
183
+ refute(@ol1.cold?)
184
+ assert_equal(@ol1.temp, nil)
185
+ @ol1.select(:hot)
186
+ assert(@ol1.history?)
187
+ refute(@ol1.nohistory?)
188
+ assert_equal(@ol1.history, :history)
189
+ assert_equal(@ol1.pg_len, 42)
190
+ assert(@ol1.hot?)
191
+ refute(@ol1.nice?)
192
+ refute(@ol1.cold?)
193
+ assert_equal(@ol1.temp, :hot)
194
+
195
+ #Adding selections.
196
+ @ol1.select #Restore to default values.
197
+ assert(@ol1.history?)
198
+ refute(@ol1.nohistory?)
199
+ assert_equal(@ol1.history, :history)
200
+ assert_equal(@ol1.pg_len, 42)
201
+ refute(@ol1.hot?)
202
+ refute(@ol1.nice?)
203
+ refute(@ol1.cold?)
204
+ assert_equal(@ol1.temp, nil)
205
+ @ol1.add_selections({:temp=>:hot})
206
+ assert(@ol1.history?)
207
+ refute(@ol1.nohistory?)
208
+ assert_equal(@ol1.history, :history)
209
+ assert_equal(@ol1.pg_len, 42)
210
+ assert(@ol1.hot?)
211
+ refute(@ol1.nice?)
212
+ refute(@ol1.cold?)
213
+ assert_equal(@ol1.temp, :hot)
214
+ @ol1.add_selections([:cold, :nohistory])
215
+ assert(@ol1.nohistory?)
216
+ refute(@ol1.history?)
217
+ assert_equal(@ol1.history, :nohistory)
218
+ refute(@ol1.hot?)
219
+ refute(@ol1.nice?)
220
+ assert(@ol1.cold?)
221
+ assert_equal(@ol1.temp, :cold)
222
+
223
+
224
+ #ol2 test series.
225
+ refute(@ol2.history?)
226
+ refute(@ol2.nohistory?)
227
+ assert(@ol2.history.nil?)
228
+
229
+ @ol2.select([:history])
230
+ assert(@ol2.history?)
231
+ refute(@ol2.nohistory?)
232
+ assert_equal(@ol2.history, :history)
233
+
234
+ @ol2.select([:nohistory])
235
+ assert(@ol2.nohistory?)
236
+ refute(@ol2.history?)
237
+ assert_equal(@ol2.history, :nohistory)
238
+
239
+ @ol2.select([])
240
+ refute(@ol2.history?)
241
+ refute(@ol2.nohistory?)
242
+ assert(@ol2.history.nil?)
243
+ end
244
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: option_list
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.6
5
+ platform: ruby
6
+ authors:
7
+ - Peter Camilleri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A unified handler for flexible function option parameters.
14
+ email: peter.c.camilleri@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - option_list.rb
20
+ - option_list_test.rb
21
+ homepage: http://teuthida-technologies.com/
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options:
27
+ - --output=doc
28
+ - option_list.rb
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 1.9.3
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements:
42
+ - No special requirements.
43
+ rubyforge_project:
44
+ rubygems_version: 2.0.7
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: A unified handler for flexible function option parameters.
48
+ test_files:
49
+ - option_list_test.rb