nice-enum 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +24 -0
- data/README.rdoc +196 -0
- data/lib/nice_enum.rb +162 -0
- data/samples/deck.rb +59 -0
- data/samples/filemodes.rb +20 -0
- data/samples/squaring_numbers.rb +16 -0
- data/test/attribute_test.rb +30 -0
- data/test/const_test.rb +47 -0
- data/test/default_attribute_test.rb +24 -0
- data/test/default_value_test.rb +22 -0
- data/test/flags_test.rb +38 -0
- metadata +78 -0
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2010, Raphael Robatsch
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
* Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
* Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
* The names of the developers or contributors must not be used to
|
12
|
+
endorse or promote products derived from this software without
|
13
|
+
specific prior written permission.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS OR CONTRIBUTORS BE LIABLE FOR ANY
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
= Nice Enumerations for Ruby
|
2
|
+
|
3
|
+
Ruby's built-in enumeration support, or the lack thereof, is somewhere in the
|
4
|
+
C/C++-Age. An enum in Ruby is usually a class or module with various
|
5
|
+
constants set to some values. Attempting to display the enum variables will
|
6
|
+
result in their values being displayed, which have no use to the end user of
|
7
|
+
the application.
|
8
|
+
|
9
|
+
module Permissions
|
10
|
+
Read = 4
|
11
|
+
Write = 2
|
12
|
+
Execute = 1
|
13
|
+
end
|
14
|
+
|
15
|
+
permissions = Permissions::Read | Permissions::Write
|
16
|
+
puts permissions
|
17
|
+
# Will output "6" - Altough correct, it won't make any sense for a
|
18
|
+
# computer-illiterate user.
|
19
|
+
|
20
|
+
Nice-Enum solves this problem by encapsulating the enum values inside an
|
21
|
+
instance of their enclosing class and making the to_s method return the
|
22
|
+
name of the constant. The above code translates to
|
23
|
+
|
24
|
+
class Permissions < Flags
|
25
|
+
enum :Read, 4
|
26
|
+
enum :Write, 2
|
27
|
+
enum :Execute, 1
|
28
|
+
end
|
29
|
+
|
30
|
+
permissions = Permissions::Read | Permissions::Write
|
31
|
+
puts permissions.join(" and ")
|
32
|
+
# Will output "Write and Read".
|
33
|
+
|
34
|
+
Nice-Enum contains two classes: Enum and Flags. Instances of Flag will
|
35
|
+
automatically figure out it's components when or'd together and provides a
|
36
|
+
different to_s method. Otherwise the classes are functionally identical.
|
37
|
+
|
38
|
+
Of course, an enum can use anything as it's value type, not only integers.
|
39
|
+
The value type must only provide a <=> operator.
|
40
|
+
|
41
|
+
= Installation
|
42
|
+
|
43
|
+
Using Rubygems:
|
44
|
+
|
45
|
+
gem install nice-enum
|
46
|
+
|
47
|
+
Manually:
|
48
|
+
|
49
|
+
git clone git://github.com/raphaelr/nice-enum
|
50
|
+
cd nice-enum
|
51
|
+
rake install
|
52
|
+
|
53
|
+
== Usage
|
54
|
+
|
55
|
+
require "nice_enum"
|
56
|
+
|
57
|
+
= Features
|
58
|
+
|
59
|
+
== From Enums to Fixnums and back
|
60
|
+
|
61
|
+
Getting the underlying value from an enum instance is usually not neccessary
|
62
|
+
because the Enumeration class will hand method calls automatically down to
|
63
|
+
the underlying value:
|
64
|
+
|
65
|
+
puts Permissions::Execute.next # => 2; Will call 1.next
|
66
|
+
|
67
|
+
You can explicitly ask for the underlying value:
|
68
|
+
|
69
|
+
puts Permissions::Execute.value # => 1
|
70
|
+
|
71
|
+
The reverse has to be done explicitly, but it's very easy:
|
72
|
+
|
73
|
+
puts Permissions.new(1) # => Execute
|
74
|
+
puts Permissions.new(3) # => Execute | Write
|
75
|
+
puts Permissions.new(80) # => 80
|
76
|
+
|
77
|
+
In the last example, the Permission instance is treated as a Permission with
|
78
|
+
the name "80" and the value 80.
|
79
|
+
|
80
|
+
== Auto-Values
|
81
|
+
|
82
|
+
Like in most languages with enum support, you don't have to explicitly provide
|
83
|
+
values for enumerations. Nice-Enum will create sequential Fixnums if you don't
|
84
|
+
specify them.
|
85
|
+
|
86
|
+
class Suit < Enum
|
87
|
+
enum :Spades # Will become 0
|
88
|
+
enum :Hearts # Will become 1
|
89
|
+
enum :Diamonds # Will become 2
|
90
|
+
enum :Clubs # Will become 3
|
91
|
+
end
|
92
|
+
|
93
|
+
You can also mix explicit and implicit values together:
|
94
|
+
|
95
|
+
class Numbers < Enum
|
96
|
+
enum :Zero
|
97
|
+
enum :One
|
98
|
+
enum :FourtyEight, 48
|
99
|
+
enum :FourtyNine
|
100
|
+
end
|
101
|
+
|
102
|
+
Note that eventual gaps aren't filled.
|
103
|
+
|
104
|
+
== Iterating over values
|
105
|
+
|
106
|
+
Suit.each { |suit| puts suit }
|
107
|
+
# Outputs: Spades
|
108
|
+
# Hearts
|
109
|
+
# Diamonds
|
110
|
+
# Clubs
|
111
|
+
|
112
|
+
The Enum class also includes the Enumerable module so you can do stuff like:
|
113
|
+
|
114
|
+
Suit.map { |suit| suit.name.chop }.each { |suit| puts suit }
|
115
|
+
# Outputs: Spade
|
116
|
+
# Heart
|
117
|
+
# Diamond
|
118
|
+
# Club
|
119
|
+
|
120
|
+
== Attributes
|
121
|
+
|
122
|
+
If that's not nice enough for you, maybe this is: You can attach any number of
|
123
|
+
attributes to enumerations. For example:
|
124
|
+
|
125
|
+
class Number < Enum
|
126
|
+
enum :Zero, 0, :squared => 0
|
127
|
+
enum :One, 1, :note => "Average number of eyes per eyehole", :squared => 1
|
128
|
+
enum :Five, 5, :note => "Number of digits per hand", :squared => 25
|
129
|
+
end
|
130
|
+
|
131
|
+
Number.each do |enum|
|
132
|
+
puts "#{enum} is squared #{enum.squared} and is special because it is the #{enum.note}."
|
133
|
+
end
|
134
|
+
# Outputs: Zero is squared 0 and is special because it is the nil.
|
135
|
+
# One is squared 1 and is special because it is the Average number of eyes per eyehole.
|
136
|
+
# Five is squared 25 and is special because it is the Number of digits per hand.
|
137
|
+
|
138
|
+
You can also provide default values for attributes:
|
139
|
+
|
140
|
+
class Number < Enum
|
141
|
+
default :note => "number which is the same if multiplied with one"
|
142
|
+
# ...
|
143
|
+
end
|
144
|
+
# Outputs: Zero is squared 0 and is special because it is the number which is the same if multiplied with one.
|
145
|
+
# One is squared 1 and is special because it is the Average number of eyes per eyehole.
|
146
|
+
# Five is squared 25 and is special because it is the Number of digits per hand.
|
147
|
+
|
148
|
+
== Instance methods
|
149
|
+
|
150
|
+
Since enum values are instances of their enclosing class, you can add methods to them:
|
151
|
+
|
152
|
+
class Number < Enum
|
153
|
+
enum :Zero, 0
|
154
|
+
enum :One, 1
|
155
|
+
enum :Two, 2
|
156
|
+
|
157
|
+
def square
|
158
|
+
value ** 2
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
numbers = Number.to_a
|
163
|
+
numbers << Number.new(3)
|
164
|
+
|
165
|
+
numbers.each { |number| puts "#{number} squared is #{number.square}." }
|
166
|
+
# Outputs: Zero squared is 0.
|
167
|
+
# One squared is 1.
|
168
|
+
# Two squared is 4.
|
169
|
+
# 3 squared is 9.
|
170
|
+
|
171
|
+
= License
|
172
|
+
|
173
|
+
Copyright (c) 2010, Raphael Robatsch
|
174
|
+
All rights reserved.
|
175
|
+
|
176
|
+
Redistribution and use in source and binary forms, with or without
|
177
|
+
modification, are permitted provided that the following conditions are met:
|
178
|
+
* Redistributions of source code must retain the above copyright
|
179
|
+
notice, this list of conditions and the following disclaimer.
|
180
|
+
* Redistributions in binary form must reproduce the above copyright
|
181
|
+
notice, this list of conditions and the following disclaimer in the
|
182
|
+
documentation and/or other materials provided with the distribution.
|
183
|
+
* The names of the developers or contributors must not be used to
|
184
|
+
endorse or promote products derived from this software without
|
185
|
+
specific prior written permission.
|
186
|
+
|
187
|
+
THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AND CONTRIBUTORS "AS IS" AND
|
188
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
189
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
190
|
+
DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS OR CONTRIBUTORS BE LIABLE FOR ANY
|
191
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
192
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
193
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
194
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
195
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
196
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/lib/nice_enum.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010, Raphael Robatsch
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
# * The names of the developers or contributors must not be used to
|
13
|
+
# endorse or promote products derived from this software without
|
14
|
+
# specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
# DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS OR CONTRIBUTORS BE LIABLE FOR ANY
|
20
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
23
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
#++
|
27
|
+
|
28
|
+
# Base class for all Enumerations. To create an Enumeration, subclass this
|
29
|
+
# class and add enum calls in the class body.
|
30
|
+
# There are many samples in README.rdoc and samples/ .
|
31
|
+
class Enum
|
32
|
+
include Comparable
|
33
|
+
|
34
|
+
# Returns the name of the enumeration member. This is the first parameter
|
35
|
+
# passed to +enum+.
|
36
|
+
attr_reader :name
|
37
|
+
|
38
|
+
# Returns the value of the enumeration member. This is the second parameter
|
39
|
+
# passed to +enum+.
|
40
|
+
attr_reader :value
|
41
|
+
|
42
|
+
# Compares the value of +self+ with the value of +other+.
|
43
|
+
def <=>(other)
|
44
|
+
other = other.value if other.is_a? self.class
|
45
|
+
return value <=> other
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the name of the enumeration member.
|
49
|
+
def to_s
|
50
|
+
@name
|
51
|
+
end
|
52
|
+
|
53
|
+
alias old_respond_to? respond_to? # :nodoc:
|
54
|
+
def respond_to?(sym) # :nodoc:
|
55
|
+
old_respond_to?(sym) || @value.respond_to?(sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(sym, *args, &block) # :nodoc:
|
59
|
+
@value.send(sym, *args, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
class << Enum
|
63
|
+
include Enumerable
|
64
|
+
|
65
|
+
# Returns the +Enum+ instance for the given value. If no enumeration
|
66
|
+
# member has been created for this value, a new instance is created,
|
67
|
+
# setting +name+ to +value.to_s+.
|
68
|
+
def new(value)
|
69
|
+
return @enumvalues[value] if @enumvalues.has_key? value
|
70
|
+
_setup_enumvalue(value, value, allocate)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the default value for the attribute +attr+. If no default
|
74
|
+
# value has been set, +nil+ is returned.
|
75
|
+
def default_value(attr)
|
76
|
+
@defaults ||= {}
|
77
|
+
@defaults[attr.to_sym]
|
78
|
+
end
|
79
|
+
|
80
|
+
# Enumerates all known enumeration members.
|
81
|
+
def each
|
82
|
+
@enumvalues ||= {}
|
83
|
+
@enumvalues.each_value { |enumvalue| yield enumvalue }
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
# Adds a new enumeration member to the current enumeration. The
|
88
|
+
# generated member is accessible using the constant +name+. If
|
89
|
+
# +value+ is +nil+, it is set to the highest integer value in
|
90
|
+
# use \+ 1.
|
91
|
+
def enum(name, value = nil, attributes = {})
|
92
|
+
@enumvalues ||= {}
|
93
|
+
value ||= (@enumvalues.values.max || -1) + 1
|
94
|
+
|
95
|
+
enumvalue = allocate
|
96
|
+
const_set(name, enumvalue)
|
97
|
+
@enumvalues[value] = enumvalue
|
98
|
+
_setup_enumvalue(name, value, enumvalue, attributes)
|
99
|
+
end
|
100
|
+
|
101
|
+
def _setup_enumvalue(name, value, enumvalue, attributes = {}) # :nodoc:
|
102
|
+
enumvalue.instance_variable_set(:@name, name.to_s)
|
103
|
+
enumvalue.instance_variable_set(:@value, value)
|
104
|
+
attributes.each do |attribute, attr_value|
|
105
|
+
_create_accessor(attribute)
|
106
|
+
enumvalue.instance_variable_set("@#{attribute}", attr_value)
|
107
|
+
end
|
108
|
+
enumvalue
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets the default values for the attributes of the enumeration members.
|
112
|
+
# There can be more than one call to +defaults+.
|
113
|
+
def defaults(defs = {})
|
114
|
+
@defaults ||= {}
|
115
|
+
@defaults.merge!(defs)
|
116
|
+
end
|
117
|
+
alias default defaults
|
118
|
+
|
119
|
+
def _create_accessor(attribute) # :nodoc:
|
120
|
+
define_method(attribute) do
|
121
|
+
instance_variable_get("@#{attribute}") || self.class.default_value(attribute)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Base class for enumerations in which members can be or'd together to create
|
128
|
+
# combinations of them. For example, Unix file permissions can be represented
|
129
|
+
# as a flag enumeration with the members <tt>Read = 4</tt>, <tt>Write = 2</tt>
|
130
|
+
# and <tt>Execute = 1</tt>. There are many samples in README.rdoc and samples/.
|
131
|
+
class Flags < Enum
|
132
|
+
# Returns the individual enumeration members that are contained in +self+.
|
133
|
+
# If the enumeration class contains a member with the value +0+, that
|
134
|
+
# member is only included in the result if there aren't any other members
|
135
|
+
# that are contained in +self+.
|
136
|
+
def flags
|
137
|
+
result = self.class.select { |flag| value & flag != 0 }.sort
|
138
|
+
result = [self.class.new(0)] if result.empty?
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
# Joins the result of +flags+ together.
|
143
|
+
def join(seperator = " | ")
|
144
|
+
flags.map { |flag| flag.name }.join(seperator)
|
145
|
+
end
|
146
|
+
alias to_s join
|
147
|
+
|
148
|
+
# Returns the combination of +self+ and +other+.
|
149
|
+
def |(other)
|
150
|
+
self.class.new(value | other)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns the intersection of +self+ and +other+.
|
154
|
+
def &(other)
|
155
|
+
self.class.new(value & other)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Bitwise-XORs +self+ with +other+.
|
159
|
+
def ^(other)
|
160
|
+
self.class.new(value ^ other)
|
161
|
+
end
|
162
|
+
end
|
data/samples/deck.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "../lib/nice_enum"
|
2
|
+
|
3
|
+
module Cards
|
4
|
+
class Suit < Enum
|
5
|
+
enum :Spades
|
6
|
+
enum :Hearts
|
7
|
+
enum :Diamonds
|
8
|
+
enum :Clubs
|
9
|
+
end
|
10
|
+
|
11
|
+
class Value < Enum
|
12
|
+
enum :Ace, 1, :score => 11 # For the sake of simplicity
|
13
|
+
enum :Two, 2, :score => 2
|
14
|
+
enum :Three, 3, :score => 3
|
15
|
+
enum :Four, nil, :score => 4
|
16
|
+
enum :Five, nil, :score => 5
|
17
|
+
enum :Six, nil, :score => 6
|
18
|
+
enum :Jack, nil, :score => 10
|
19
|
+
enum :Queen, nil, :score => 10
|
20
|
+
enum :Knight, nil, :score => 10
|
21
|
+
end
|
22
|
+
|
23
|
+
class Card
|
24
|
+
attr_accessor :suit
|
25
|
+
attr_accessor :value
|
26
|
+
|
27
|
+
def initialize(suit, value)
|
28
|
+
@suit = suit
|
29
|
+
@value = value
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
"#{value} of #{suit}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Deck
|
38
|
+
def initialize
|
39
|
+
@cards = Suit.map do |suit|
|
40
|
+
Value.map do |value|
|
41
|
+
Card.new(suit, value)
|
42
|
+
end
|
43
|
+
end.flatten.shuffle
|
44
|
+
end
|
45
|
+
|
46
|
+
def draw(n)
|
47
|
+
@cards.slice!(0, n)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
deck = Cards::Deck.new
|
53
|
+
hand = deck.draw(5)
|
54
|
+
|
55
|
+
puts "Your hand:"
|
56
|
+
hand.each do |card|
|
57
|
+
puts " - #{card}"
|
58
|
+
end
|
59
|
+
puts "Blackjack score: #{hand.inject(0) { |score, card| score + card.value.score }}"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "../lib/nice_enum"
|
2
|
+
|
3
|
+
class Permission < Flags
|
4
|
+
enum :None, 0
|
5
|
+
enum :Read, 4
|
6
|
+
enum :Write, 2
|
7
|
+
enum :Execute, 1
|
8
|
+
end
|
9
|
+
|
10
|
+
file = ARGV[0] || __FILE__
|
11
|
+
puts "Permissions on #{file}:"
|
12
|
+
|
13
|
+
mode = File.stat(file).mode
|
14
|
+
user = Permission.new((mode & 448) >> 6)
|
15
|
+
group = Permission.new((mode & 56) >> 3)
|
16
|
+
world = Permission.new(mode & 7)
|
17
|
+
|
18
|
+
puts "User: #{user}"
|
19
|
+
puts "Group: #{group}"
|
20
|
+
puts "World: #{world}"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "../lib/nice_enum"
|
2
|
+
|
3
|
+
class Number < Enum
|
4
|
+
enum :Zero, 0
|
5
|
+
enum :One, 1
|
6
|
+
enum :Two, 2
|
7
|
+
|
8
|
+
def square
|
9
|
+
value ** 2
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
numbers = Number.to_a
|
14
|
+
numbers << Number.new(3)
|
15
|
+
|
16
|
+
numbers.each { |number| puts "#{number} squared is #{number.square}." }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "nice_enum"
|
2
|
+
require "test/unit"
|
3
|
+
|
4
|
+
class AttributeTest < Test::Unit::TestCase
|
5
|
+
class Number < Enum
|
6
|
+
enum :Twenty, 20,
|
7
|
+
:note => "Exact value of e^pi - pi"
|
8
|
+
|
9
|
+
enum :Ninety, 90,
|
10
|
+
:note => "Square Root of -1"
|
11
|
+
|
12
|
+
enum :FourtyTwo, 42
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_respond_to_known_attribute
|
16
|
+
assert Number::Twenty.respond_to?(:note)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_get_attribute_from_known_value
|
20
|
+
assert_equal "Exact value of e^pi - pi", Number::Twenty.note
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_get_attribute_from_unknown_value
|
24
|
+
assert_equal nil, Number.new(8).note
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_respond_to_unknown_attribute
|
28
|
+
assert !Number::Twenty.respond_to?(:color)
|
29
|
+
end
|
30
|
+
end
|
data/test/const_test.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "nice_enum"
|
2
|
+
require "test/unit"
|
3
|
+
|
4
|
+
class ConstTest < Test::Unit::TestCase
|
5
|
+
class Number < Enum
|
6
|
+
enum :Zero, 0
|
7
|
+
enum :One, 1
|
8
|
+
enum :Two, 2
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_to_s
|
12
|
+
assert_equal "Zero", Number::Zero.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_value_equality
|
16
|
+
assert_equal 2, Number::Two.value
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_enum_equality
|
20
|
+
assert_equal Number::Zero, Number::Zero
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_mixed_equality
|
24
|
+
assert_equal Number::Zero, 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_new_stays_same
|
28
|
+
assert_same Number::Zero, Number.new(0)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_new_on_undefined_enum_value
|
32
|
+
assert_equal -13, Number.new(-13)
|
33
|
+
assert_equal "-13", Number.new(-13).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_respond_to_mirroring
|
37
|
+
assert Number::One.respond_to? :abs
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_send_mirroring
|
41
|
+
assert_equal -1, -Number::One
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_enumerable
|
45
|
+
assert_equal [Number::Zero, Number::One, Number::Two], Number.to_a
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "nice_enum"
|
2
|
+
require "test/unit"
|
3
|
+
|
4
|
+
class DefaultAttributeTest < Test::Unit::TestCase
|
5
|
+
class Number < Enum
|
6
|
+
default :note => "A boring number"
|
7
|
+
|
8
|
+
enum :Twenty, 20,
|
9
|
+
:note => "Exact value of e^pi - pi"
|
10
|
+
|
11
|
+
enum :Ninety, 90,
|
12
|
+
:note => "Square Root of -1"
|
13
|
+
|
14
|
+
enum :FourtyTwo, 42
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_get_set_attribute
|
18
|
+
assert_equal "Exact value of e^pi - pi", Number::Twenty.note
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_get_unset_attribute
|
22
|
+
assert_equal "A boring number", Number::FourtyTwo.note
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "nice_enum"
|
3
|
+
|
4
|
+
class DefaultValueTest < Test::Unit::TestCase
|
5
|
+
class Suit < Enum
|
6
|
+
enum :Spades
|
7
|
+
enum :Hearts
|
8
|
+
enum :Green, 48
|
9
|
+
enum :Diamonds
|
10
|
+
enum :Clubs
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_enum_order
|
14
|
+
assert_equal [Suit::Spades, Suit::Hearts, Suit::Green, Suit::Diamonds, Suit::Clubs], Suit.to_a.sort
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_values
|
18
|
+
assert_equal 1, Suit::Hearts.value
|
19
|
+
assert_equal 48, Suit::Green.value
|
20
|
+
assert_equal 49, Suit::Diamonds.value
|
21
|
+
end
|
22
|
+
end
|
data/test/flags_test.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "nice_enum"
|
3
|
+
|
4
|
+
class FlagsTest < Test::Unit::TestCase
|
5
|
+
class Permission < Flags
|
6
|
+
enum :Read, 4
|
7
|
+
enum :Write, 2
|
8
|
+
enum :Execute, 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_binary_operators_return_class
|
12
|
+
assert (Permission::Read | Permission::Write).is_a? Permission
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_or
|
16
|
+
assert_equal 6, Permission::Read | Permission::Write
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_and
|
20
|
+
assert_equal Permission::Write, 7 & Permission::Write
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_xor
|
24
|
+
assert_equal Permission::Read | Permission::Write, 7 ^ Permission::Execute
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_single_flag
|
28
|
+
assert_equal [Permission::Read], Permission::Read.flags
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_multi_flags
|
32
|
+
assert_equal [Permission::Write, Permission::Read], Permission.new(6).flags
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_to_s
|
36
|
+
assert_equal "Execute|Write", Permission.new(3).to_s.gsub(' ', '')
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nice-enum
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Raphael Robatsch
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-02 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: raphaelr@f-m.fm
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README.rdoc
|
29
|
+
files:
|
30
|
+
- lib/nice_enum.rb
|
31
|
+
- samples/deck.rb
|
32
|
+
- samples/filemodes.rb
|
33
|
+
- samples/squaring_numbers.rb
|
34
|
+
- README.rdoc
|
35
|
+
- LICENSE
|
36
|
+
- test/attribute_test.rb
|
37
|
+
- test/const_test.rb
|
38
|
+
- test/default_attribute_test.rb
|
39
|
+
- test/default_value_test.rb
|
40
|
+
- test/flags_test.rb
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://raphaelr.github.com/nice-enum
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.7
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Nice Enumerations for Ruby
|
73
|
+
test_files:
|
74
|
+
- test/attribute_test.rb
|
75
|
+
- test/const_test.rb
|
76
|
+
- test/default_attribute_test.rb
|
77
|
+
- test/default_value_test.rb
|
78
|
+
- test/flags_test.rb
|