Sometimes you just want to use an Enum. Unfortunately, if you’re a Ruby developer, Ruby does not offer a native enum structure.
Here’s a simple approach using a mixin module:
Enum.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| module Enum
def const_missing(key)
@enum_hash[key]
end
def add_enum(key, value)
@enum_hash ||= {}
@enum_hash[key] = NameValuePair.new(value, key.to_s.downcase)
end
def each
@enum_hash.each {|key, value| yield(key, value) }
end
def enums
@enum_hash.keys
end
def enum_values
@enum_hash.values
end
def get_enum_hash
@enum_hash
end
def find_by_key(key)
@enum_hash[key.upcase.to_sym]
end
end
|
The Enum
mixin depends on a NameValuePair
class to hold the data:
NameValuePair.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| class NameValuePair
attr_reader :label, :value
def initialize(label, value)
@label = label
@value = value
end
def first
@label
end
def last
@value
end
end
|
I included first and last methods to better support the select
and options_for_select
helper methods in Rails. Here’s how you might use it:
1
2
3
4
5
6
7
8
9
10
11
12
| class FooEnum
extend Enum
self.add_enum(:APPLE, "Apple")
self.add_enum(:PEAR, "Pear")
self.add_enum(:ALL, "All Fruit")
end
FooEnum::APPLE ==> #<NameValuePair @value="apple", @label="Apple">
FooEnum::ALL.value ==> "all"
FooEnum::ALL.label ==> "All Fruit"
FooEnum.find_by_key('apple') ==> #<NameValuePair @value="apple", @label="Apple">
|