magic_enum 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/init.rb +1 -2
- data/lib/magic_enum.rb +3 -153
- data/lib/magic_enum/class_methods.rb +149 -0
- data/lib/magic_enum/version.rb +1 -1
- metadata +4 -3
data/init.rb
CHANGED
data/lib/magic_enum.rb
CHANGED
|
@@ -1,154 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
super
|
|
4
|
-
base.extend(ClassMethods)
|
|
5
|
-
end
|
|
1
|
+
require 'magic_enum/version'
|
|
2
|
+
require 'magic_enum/class_methods'
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
# Method used to define ENUM attributes in your model. Examples:
|
|
9
|
-
#
|
|
10
|
-
# Statuses = {
|
|
11
|
-
# :draft => 0,
|
|
12
|
-
# :published => 1,
|
|
13
|
-
# :approved => 2
|
|
14
|
-
# }
|
|
15
|
-
# define_enum :status
|
|
16
|
-
#
|
|
17
|
-
# Before using <tt>define_enum</tt>, you should define constant with ENUM options.
|
|
18
|
-
# Constant name would be pluralized enum attribute name. Additional constant named
|
|
19
|
-
# like <tt>YourEnumInverted</tt> would be created automatically and would contain
|
|
20
|
-
# inverted hash.
|
|
21
|
-
#
|
|
22
|
-
# <b>Please note</b>: <tt>nil</tt> and <tt>0</tt> are not the same values!
|
|
23
|
-
#
|
|
24
|
-
# You could specify additional options:
|
|
25
|
-
#
|
|
26
|
-
# * <tt>:default</tt> - value which will be used when current state of ENUM attribute is
|
|
27
|
-
# invalid or wrong value received. If it has not been specified, min value of the ENUM would
|
|
28
|
-
# be used.
|
|
29
|
-
# * <tt>:raise_on_invalid</tt> - if <tt>true</tt> an exception would be raised on invalid
|
|
30
|
-
# enum value received. If it is <tt>false</tt>, default value would be used instead of
|
|
31
|
-
# wrong one.
|
|
32
|
-
# * <tt>:simple_accessors</tt> - if <tt>true</tt>, additional methods for each ENUM value
|
|
33
|
-
# would be defined in form <tt>value?</tt>. Methods returns <tt>true</tt> when
|
|
34
|
-
# ENUM attribute has corresponding value.
|
|
35
|
-
# * <tt>:enum</tt> - string with name of the ENUM hash.
|
|
36
|
-
#
|
|
37
|
-
# Look the following example:
|
|
38
|
-
#
|
|
39
|
-
# Statuses = {
|
|
40
|
-
# :unknown => 0,
|
|
41
|
-
# :draft => 1,
|
|
42
|
-
# :published => 2,
|
|
43
|
-
# :approved => 3
|
|
44
|
-
# }
|
|
45
|
-
# define_enum :status, :default => 1, :raise_on_invalid => true, :simple_accessors => true
|
|
46
|
-
#
|
|
47
|
-
# This example is identical to:
|
|
48
|
-
#
|
|
49
|
-
# Statuses = {
|
|
50
|
-
# :unknown => 0,
|
|
51
|
-
# :draft => 1,
|
|
52
|
-
# :published => 2,
|
|
53
|
-
# :approved => 3
|
|
54
|
-
# }
|
|
55
|
-
# StatusesInverted = Statuses.invert
|
|
56
|
-
#
|
|
57
|
-
# def status
|
|
58
|
-
# return StatusesInverted[self[:status].to_i] || StatusesInverted[1]
|
|
59
|
-
# end
|
|
60
|
-
#
|
|
61
|
-
# def status=(value)
|
|
62
|
-
# raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model" if Statuses[value].nil?
|
|
63
|
-
# self[:status] = Statuses[value]
|
|
64
|
-
# end
|
|
65
|
-
#
|
|
66
|
-
# def unknown?
|
|
67
|
-
# status == :unknown
|
|
68
|
-
# end
|
|
69
|
-
#
|
|
70
|
-
# def draft?
|
|
71
|
-
# status == :draft
|
|
72
|
-
# end
|
|
73
|
-
#
|
|
74
|
-
# def published?
|
|
75
|
-
# status == :published
|
|
76
|
-
# end
|
|
77
|
-
#
|
|
78
|
-
# def approved?
|
|
79
|
-
# status == :approved
|
|
80
|
-
# end
|
|
81
|
-
#
|
|
82
|
-
def define_enum(name, opts = {})
|
|
83
|
-
default_opts = { :raise_on_invalid => false,
|
|
84
|
-
:simple_accessors => false,
|
|
85
|
-
:named_scopes => false,
|
|
86
|
-
:scope_extensions => false
|
|
87
|
-
}
|
|
88
|
-
opts = default_opts.merge(opts)
|
|
89
|
-
name = name.to_sym
|
|
90
|
-
|
|
91
|
-
# bug in Rails 1.2.2
|
|
92
|
-
opts[:enum] = name.to_s.pluralize.classify.pluralize unless opts[:enum]
|
|
93
|
-
enum = opts[:enum]
|
|
94
|
-
enum_inverted = "#{enum}Inverted"
|
|
95
|
-
|
|
96
|
-
opts[:default] = const_get(enum).values.sort do |a, b|
|
|
97
|
-
if a.nil? and b.nil?
|
|
98
|
-
0
|
|
99
|
-
elsif a.nil?
|
|
100
|
-
-1
|
|
101
|
-
elsif b.nil?
|
|
102
|
-
1
|
|
103
|
-
else
|
|
104
|
-
a <=> b
|
|
105
|
-
end
|
|
106
|
-
end.first unless opts[:default]
|
|
107
|
-
|
|
108
|
-
const_set(enum_inverted, const_get(enum).invert)
|
|
109
|
-
|
|
110
|
-
define_method name do
|
|
111
|
-
self.class.const_get(enum_inverted)[self[name]] || self.class.const_get(enum_inverted)[opts[:default]]
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
define_method "#{name}_name" do
|
|
115
|
-
send(name).to_s
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
define_method "#{name}=" do |value|
|
|
119
|
-
value = value.to_sym if value.is_a?(String)
|
|
120
|
-
raise ArgumentError, "Invalid value \"#{value}\" for :#{name} attribute of the #{self.class} model" if opts[:raise_on_invalid] and self.class.const_get(enum)[value].nil?
|
|
121
|
-
if value.is_a?(Integer)
|
|
122
|
-
self[name] = value
|
|
123
|
-
else
|
|
124
|
-
self[name] = self.class.const_get(enum)[value] || opts[:default]
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
if opts[:simple_accessors]
|
|
129
|
-
const_get(enum).keys.each do |key|
|
|
130
|
-
define_method "#{key}?" do
|
|
131
|
-
send(name) == key
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Create named scopes for each enum value
|
|
137
|
-
if opts[:named_scopes]
|
|
138
|
-
const_get(enum).keys.each do |key|
|
|
139
|
-
named_scope key.to_s.pluralize.to_sym, :conditions => ["#{name} = ?", const_get(enum)[key]] do
|
|
140
|
-
opts[:scope_extensions].each do |ext_name, ext_block|
|
|
141
|
-
define_method ext_name, ext_block
|
|
142
|
-
end if opts[:scope_extensions] and opts[:scope_extensions].is_a?(Hash)
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
named_scope "of_#{name}".to_sym, lambda { |t| { :conditions => ["#{name} = ?", const_get(enum)[t]] } } do
|
|
146
|
-
opts[:scope_extensions].each do |ext_name, ext_block|
|
|
147
|
-
define_method ext_name, ext_block
|
|
148
|
-
end if opts[:scope_extensions] and opts[:scope_extensions].is_a?(Hash)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
4
|
+
ActiveRecord::Base.extend(MagicEnum::ClassMethods)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module MagicEnum
|
|
2
|
+
module ClassMethods
|
|
3
|
+
# Method used to define ENUM attributes in your model. Examples:
|
|
4
|
+
#
|
|
5
|
+
# Statuses = {
|
|
6
|
+
# :draft => 0,
|
|
7
|
+
# :published => 1,
|
|
8
|
+
# :approved => 2
|
|
9
|
+
# }
|
|
10
|
+
# define_enum :status
|
|
11
|
+
#
|
|
12
|
+
# Before using <tt>define_enum</tt>, you should define constant with ENUM options.
|
|
13
|
+
# Constant name would be pluralized enum attribute name. Additional constant named
|
|
14
|
+
# like <tt>YourEnumInverted</tt> would be created automatically and would contain
|
|
15
|
+
# inverted hash.
|
|
16
|
+
#
|
|
17
|
+
# <b>Please note</b>: <tt>nil</tt> and <tt>0</tt> are not the same values!
|
|
18
|
+
#
|
|
19
|
+
# You could specify additional options:
|
|
20
|
+
#
|
|
21
|
+
# * <tt>:default</tt> - value which will be used when current state of ENUM attribute is
|
|
22
|
+
# invalid or wrong value received. If it has not been specified, min value of the ENUM would
|
|
23
|
+
# be used.
|
|
24
|
+
# * <tt>:raise_on_invalid</tt> - if <tt>true</tt> an exception would be raised on invalid
|
|
25
|
+
# enum value received. If it is <tt>false</tt>, default value would be used instead of
|
|
26
|
+
# wrong one.
|
|
27
|
+
# * <tt>:simple_accessors</tt> - if <tt>true</tt>, additional methods for each ENUM value
|
|
28
|
+
# would be defined in form <tt>value?</tt>. Methods returns <tt>true</tt> when
|
|
29
|
+
# ENUM attribute has corresponding value.
|
|
30
|
+
# * <tt>:enum</tt> - string with name of the ENUM hash.
|
|
31
|
+
#
|
|
32
|
+
# Look the following example:
|
|
33
|
+
#
|
|
34
|
+
# Statuses = {
|
|
35
|
+
# :unknown => 0,
|
|
36
|
+
# :draft => 1,
|
|
37
|
+
# :published => 2,
|
|
38
|
+
# :approved => 3
|
|
39
|
+
# }
|
|
40
|
+
# define_enum :status, :default => 1, :raise_on_invalid => true, :simple_accessors => true
|
|
41
|
+
#
|
|
42
|
+
# This example is identical to:
|
|
43
|
+
#
|
|
44
|
+
# Statuses = {
|
|
45
|
+
# :unknown => 0,
|
|
46
|
+
# :draft => 1,
|
|
47
|
+
# :published => 2,
|
|
48
|
+
# :approved => 3
|
|
49
|
+
# }
|
|
50
|
+
# StatusesInverted = Statuses.invert
|
|
51
|
+
#
|
|
52
|
+
# def status
|
|
53
|
+
# return StatusesInverted[self[:status].to_i] || StatusesInverted[1]
|
|
54
|
+
# end
|
|
55
|
+
#
|
|
56
|
+
# def status=(value)
|
|
57
|
+
# raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model" if Statuses[value].nil?
|
|
58
|
+
# self[:status] = Statuses[value]
|
|
59
|
+
# end
|
|
60
|
+
#
|
|
61
|
+
# def unknown?
|
|
62
|
+
# status == :unknown
|
|
63
|
+
# end
|
|
64
|
+
#
|
|
65
|
+
# def draft?
|
|
66
|
+
# status == :draft
|
|
67
|
+
# end
|
|
68
|
+
#
|
|
69
|
+
# def published?
|
|
70
|
+
# status == :published
|
|
71
|
+
# end
|
|
72
|
+
#
|
|
73
|
+
# def approved?
|
|
74
|
+
# status == :approved
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
def define_enum(name, opts = {})
|
|
78
|
+
default_opts = { :raise_on_invalid => false,
|
|
79
|
+
:simple_accessors => false,
|
|
80
|
+
:named_scopes => false,
|
|
81
|
+
:scope_extensions => false
|
|
82
|
+
}
|
|
83
|
+
opts = default_opts.merge(opts)
|
|
84
|
+
name = name.to_sym
|
|
85
|
+
|
|
86
|
+
# bug in Rails 1.2.2
|
|
87
|
+
opts[:enum] = name.to_s.pluralize.classify.pluralize unless opts[:enum]
|
|
88
|
+
enum = opts[:enum]
|
|
89
|
+
enum_inverted = "#{enum}Inverted"
|
|
90
|
+
|
|
91
|
+
opts[:default] = const_get(enum).values.sort do |a, b|
|
|
92
|
+
if a.nil? and b.nil?
|
|
93
|
+
0
|
|
94
|
+
elsif a.nil?
|
|
95
|
+
-1
|
|
96
|
+
elsif b.nil?
|
|
97
|
+
1
|
|
98
|
+
else
|
|
99
|
+
a <=> b
|
|
100
|
+
end
|
|
101
|
+
end.first unless opts[:default]
|
|
102
|
+
|
|
103
|
+
const_set(enum_inverted, const_get(enum).invert)
|
|
104
|
+
|
|
105
|
+
define_method name do
|
|
106
|
+
self.class.const_get(enum_inverted)[self[name]] || self.class.const_get(enum_inverted)[opts[:default]]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
define_method "#{name}_name" do
|
|
110
|
+
send(name).to_s
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
define_method "#{name}=" do |value|
|
|
114
|
+
value = value.to_sym if value.is_a?(String)
|
|
115
|
+
raise ArgumentError, "Invalid value \"#{value}\" for :#{name} attribute of the #{self.class} model" if opts[:raise_on_invalid] and self.class.const_get(enum)[value].nil?
|
|
116
|
+
if value.is_a?(Integer)
|
|
117
|
+
self[name] = value
|
|
118
|
+
else
|
|
119
|
+
self[name] = self.class.const_get(enum)[value] || opts[:default]
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if opts[:simple_accessors]
|
|
124
|
+
const_get(enum).keys.each do |key|
|
|
125
|
+
define_method "#{key}?" do
|
|
126
|
+
send(name) == key
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Create named scopes for each enum value
|
|
132
|
+
if opts[:named_scopes]
|
|
133
|
+
const_get(enum).keys.each do |key|
|
|
134
|
+
named_scope key.to_s.pluralize.to_sym, :conditions => ["#{name} = ?", const_get(enum)[key]] do
|
|
135
|
+
opts[:scope_extensions].each do |ext_name, ext_block|
|
|
136
|
+
define_method ext_name, ext_block
|
|
137
|
+
end if opts[:scope_extensions] and opts[:scope_extensions].is_a?(Hash)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
named_scope "of_#{name}".to_sym, lambda { |t| { :conditions => ["#{name} = ?", const_get(enum)[t]] } } do
|
|
141
|
+
opts[:scope_extensions].each do |ext_name, ext_block|
|
|
142
|
+
define_method ext_name, ext_block
|
|
143
|
+
end if opts[:scope_extensions] and opts[:scope_extensions].is_a?(Hash)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
data/lib/magic_enum/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: magic_enum
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 25
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 0.0.
|
|
9
|
+
- 3
|
|
10
|
+
version: 0.0.3
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Dmytro Shteflyuk
|
|
@@ -77,6 +77,7 @@ files:
|
|
|
77
77
|
- Rakefile
|
|
78
78
|
- init.rb
|
|
79
79
|
- lib/magic_enum.rb
|
|
80
|
+
- lib/magic_enum/class_methods.rb
|
|
80
81
|
- lib/magic_enum/version.rb
|
|
81
82
|
- magic_enum.gemspec
|
|
82
83
|
- spec/magic_enum_spec.rb
|