-
Notifications
You must be signed in to change notification settings - Fork 27
/
classy_enum.rb
78 lines (52 loc) · 1.67 KB
/
classy_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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
require "classy_enum/classy_enum_attributes"
require 'classy_enum/classy_enum_helper'
class ClassyEnumValue < Object
attr_reader :to_s, :to_sym, :index, :base_class
def initialize(base_class, option, index)
@to_s = option.to_s.downcase
@to_sym = @to_s.to_sym
@index = index + 1
@base_class = base_class
end
def name
to_s.titleize
end
def <=> other
@index <=> other.index
end
end
module ClassyEnum
module SuperClassMethods
def new(option)
self::OPTION_HASH[option] || TypeError.new("Valid #{self} options are #{self.valid_options}")
end
def all
self::OPTIONS.map {|e| self.new(e) }
end
# Uses the name field for select options
def all_with_name
self.all.map {|e| [e.name, e.to_s] }
end
def valid_options
self::OPTIONS.map(&:to_s).join(', ')
end
# Alias of new
def find(option)
new(option)
end
end
def self.included(other)
other.extend SuperClassMethods
other.const_set("OPTION_HASH", Hash.new)
other::OPTIONS.each do |option|
klass = Class.new(ClassyEnumValue) do
include other::InstanceMethods if other.const_defined?("InstanceMethods")
extend other::ClassMethods if other.const_defined?("ClassMethods")
end
Object.const_set("#{other}#{option.to_s.camelize}", klass)
instance = klass.new(other, option, other::OPTIONS.index(option))
other::OPTION_HASH[option] = other::OPTION_HASH[option.to_s.downcase] = instance
ClassyEnum.const_set(option.to_s.upcase, instance) unless ClassyEnum.const_defined?(option.to_s.upcase)
end
end
end