forked from binarylogic/enumlogic
-
Notifications
You must be signed in to change notification settings - Fork 1
/
enumlogic.rb
82 lines (73 loc) · 2.58 KB
/
enumlogic.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
77
78
79
80
81
82
require "active_record"
require "active_support"
# See the enum class level method for more info.
module Enumlogic
# Allows you to easily specify enumerations for your models. Specify enumerations like:
#
# class Computer < ActiveRecord::Base
# enum :kind, ["apple", "dell", "hp"]
# enum :kind, {"apple" => "Apple", "dell" => "Dell", "hp" => "HP"}
# enum :kind, [["apple", "Apple"], ["dell", "Dell"], ["hp", "HP"]]
# end
#
# You can now do the following:
#
# Computer::KINDS # passes back the defined enum keys as array
# Computer.kind_options # gives you a friendly hash that you can easily pass into the select helper for forms
# Computer.new(:kind => "unknown").valid? # false, automatically validates inclusion of the enum field
#
# c = Computer.new(:kind => "apple")
# c.apple? # true
# c.kind_key # :apple
# c.kind_text # "apple" or "Apple" if you gave a hash with a user friendly text value
# c.enum?(:kind) # true
def enum(field, values, options = {})
values_array = []
values_hash = if values.is_a?(Array)
hash = ActiveSupport::OrderedHash.new
values.each do |value|
# Handle 2 dimensional arrays
if value.is_a?(Array)
hash[value[0]] = value[1]
values_array.push(value[0]) # Store the key
else
hash[value] = value
values_array.push(value)
end
end
hash
else
values_array = values.keys
values
end
constant_name = options[:constant] || field.to_s.pluralize.upcase
const_set constant_name, values_array unless const_defined?(constant_name)
new_hash = ActiveSupport::OrderedHash.new
values_hash.each do |key,text|
new_hash[text] = key
end
(class << self; self; end).send(:define_method, "#{field}_options") { new_hash }
define_method("#{field}_key") do
value = send(field)
return nil if value.nil?
value.to_s.gsub(/[-\s]/, '_').downcase.to_sym
end
define_method("#{field}_text") do
value = send(field)
return nil if value.nil?
values_hash[value]
end
values_array.each do |value|
method_name = value.downcase.gsub(/[-\s]/, '_')
method_name = "#{method_name}_#{field}" if options[:namespace]
define_method("#{method_name}?") do
self.send(field) == value
end
end
validates field, :inclusion => {:in => values_array}, :allow_blank => options[:allow_blank], :if => options[:if]
end
def enum?(name)
method_defined?("#{name}_key")
end
end
ActiveRecord::Base.extend(Enumlogic)