magic_enum 0.9.0 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +81 -0
- data/README.md +103 -0
- data/lib/magic_enum/class_methods.rb +81 -56
- data/lib/magic_enum/version.rb +3 -3
- data/magic_enum.gemspec +1 -1
- data/spec/magic_enum_spec.rb +109 -61
- metadata +21 -32
- data/README.rdoc +0 -79
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cdd3250404ebdecd1fdb9aeb525cfdc5bbdf8a94
|
4
|
+
data.tar.gz: 6df523ae0550f389ef112b0d9d598d8e477819a8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 80c0eefee215b74e86e003ebf4962fa4f35a513309197f10ecab2822ad574c84bbcc0da3e11ddfed334f9e205033188a56a0090c1956ea100b1fd7c7aeb43d93
|
7
|
+
data.tar.gz: a42a06ade03d296c9fb75cf46e42c06ad1c0d58f4cb9e28778bfbfacb60c1bdbbb114fb59c79e438fc5e0702ae644c7368d0d3763f3d59f6f7fa1a270495b30a
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
## 1.0.0 (in development)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- Added "enum_value" (returns value) instance method in addition to "enum_name" (returns stringified enum key)
|
6
|
+
- Added class methods "enum_value" (returns value by key) and "enum_by_value" (returns key by value)
|
7
|
+
- Performance improvement: use `class_eval` with string instead of blocks
|
8
|
+
|
9
|
+
Bugfixes:
|
10
|
+
|
11
|
+
- Fixed const naming: use `SIMPLE_STATUSES` and `SIMPLE_STATUSES_INVERTED` instead of `SimpleStatuses` and `SimpleStatusesInverted`
|
12
|
+
|
13
|
+
## 0.9.0 (August 8, 2013)
|
14
|
+
|
15
|
+
Bugfixes:
|
16
|
+
|
17
|
+
- Allow `nil` values
|
18
|
+
- Updated specs to RSpec 1.2 syntax
|
19
|
+
|
20
|
+
Features:
|
21
|
+
|
22
|
+
- Rails 4.0.0 support
|
23
|
+
|
24
|
+
## 0.0.3 (January 29, 2012)
|
25
|
+
|
26
|
+
Features:
|
27
|
+
|
28
|
+
- Files re-organization
|
29
|
+
|
30
|
+
## 0.0.2 (January 29, 2012)
|
31
|
+
|
32
|
+
Features:
|
33
|
+
|
34
|
+
- Rails < 3.3 support
|
35
|
+
|
36
|
+
## 0.0.1 (January 29, 2012)
|
37
|
+
|
38
|
+
Features:
|
39
|
+
|
40
|
+
- First gem version
|
41
|
+
|
42
|
+
## 0.0.0 (January 16, 2009)
|
43
|
+
|
44
|
+
Features:
|
45
|
+
|
46
|
+
- Setter method symbolizes strings
|
47
|
+
|
48
|
+
Bugfixes:
|
49
|
+
|
50
|
+
- Added tests for named scopes
|
51
|
+
|
52
|
+
## 0.0.0 (September 21, 2008)
|
53
|
+
|
54
|
+
Features:
|
55
|
+
|
56
|
+
- Added a special named scope "of_name", which accepts symbol
|
57
|
+
- Added scope extensions
|
58
|
+
|
59
|
+
## 0.0.0 (September 1, 2008)
|
60
|
+
|
61
|
+
Features:
|
62
|
+
|
63
|
+
- Setter method accepts integer values in addition to symbols
|
64
|
+
|
65
|
+
## 0.0.0 (August 30, 2008)
|
66
|
+
|
67
|
+
Features:
|
68
|
+
|
69
|
+
- Added support of named scopes
|
70
|
+
|
71
|
+
## 0.0.0 (August 30, 2008)
|
72
|
+
|
73
|
+
Features:
|
74
|
+
|
75
|
+
- Added support of named scopes
|
76
|
+
|
77
|
+
## 0.0.0 (May 12, 2008)
|
78
|
+
|
79
|
+
Features:
|
80
|
+
|
81
|
+
- Basic ENUM functionality
|
data/README.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# MagicEnum
|
2
|
+
|
3
|
+
[![Travis-CI build status](https://secure.travis-ci.org/kovyrin/magic-enum.png)](http://travis-ci.org/kovyrin/magic-enum)
|
4
|
+
|
5
|
+
MagicEnum is a simple ActiveRecord plugin that makes it easier to maintain ENUM-like attributes in your models.
|
6
|
+
|
7
|
+
Examples:
|
8
|
+
|
9
|
+
STATUSES = {
|
10
|
+
:draft => 0,
|
11
|
+
:published => 1,
|
12
|
+
:approved => 2,
|
13
|
+
}
|
14
|
+
define_enum :status
|
15
|
+
|
16
|
+
## Please note: breaking changes in 1.0.0
|
17
|
+
|
18
|
+
Before version 1.0.0, the hash with ENUM values was camel-cased. We decided to change it to more rubyish upper-cased constant names. If you're upgrading from pre-1.0.0, please
|
19
|
+
change you constants accordingly. Examples:
|
20
|
+
|
21
|
+
Statuses => STATUSES
|
22
|
+
SimpleStatuses => SIMPLE_STATUSES
|
23
|
+
|
24
|
+
Name of inverted hash was changed as well:
|
25
|
+
|
26
|
+
StatusesInverted => STATUSES_INVERTED
|
27
|
+
SimpleStatusesInverted => SIMPLE_STATUSES_INVERTED
|
28
|
+
|
29
|
+
## How to Use
|
30
|
+
|
31
|
+
Before using `define_enum`, you should define constant with ENUM options.
|
32
|
+
Constant name would be pluralized enum attribute name (e.g. `SIMPLE_STATUSES`
|
33
|
+
`simple_status` enum). Additional constant named like `YOUR_ENUM_INVERTED`
|
34
|
+
would be created automatically and would contain inverted hash.
|
35
|
+
|
36
|
+
**Please note**: `nil` and `0` are not the same values!
|
37
|
+
|
38
|
+
You could specify additional options:
|
39
|
+
|
40
|
+
* `:default` — value which will be used when current state of ENUM attribute is invalid or wrong value received. If it has not been specified, min value of the ENUM would be used. Could be specified as a symbol;
|
41
|
+
* `:raise_on_invalid` — if `true` an exception would be raised on invalid enum value received. If it is `false`, default value would be used instead of wrong one;
|
42
|
+
* `:simple_accessors` — if `true`, additional methods for each ENUM value would be defined in form `value?`. Methods returns `true` when ENUM attribute has corresponding value;
|
43
|
+
* `:enum` — string with name of the ENUM hash;
|
44
|
+
* `:named_scopes` — whether to generate named scopes for values of ENUM (pluralized key names). In addition to per-key named scope, `of_name` scope will be generated, which accepts a symbol corresponding to ENUM value.
|
45
|
+
|
46
|
+
Look the following example:
|
47
|
+
|
48
|
+
STATUSES = {
|
49
|
+
:unknown => 0,
|
50
|
+
:draft => 1,
|
51
|
+
:published => 2,
|
52
|
+
:approved => 3,
|
53
|
+
}
|
54
|
+
define_enum :status, :default => 1, :raise_on_invalid => true, :simple_accessors => true
|
55
|
+
|
56
|
+
This example is identical to:
|
57
|
+
|
58
|
+
STATUSES = {
|
59
|
+
:unknown => 0,
|
60
|
+
:draft => 1,
|
61
|
+
:published => 2,
|
62
|
+
:approved => 3,
|
63
|
+
}
|
64
|
+
STATUSES_INVERTED = STATUSES.invert
|
65
|
+
|
66
|
+
def self.status_value(status)
|
67
|
+
STATUSES[status]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.status_by_value(value)
|
71
|
+
STATUSES_INVERTED[value]
|
72
|
+
end
|
73
|
+
|
74
|
+
def status
|
75
|
+
self.class.status_by_value(self[:status]) || self.class.status_by_value(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
def status=(value)
|
79
|
+
raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model" unless STATUSES.key?(value)
|
80
|
+
self[:status] = STATUSES[value]
|
81
|
+
end
|
82
|
+
|
83
|
+
def unknown?
|
84
|
+
status == :unknown
|
85
|
+
end
|
86
|
+
|
87
|
+
def draft?
|
88
|
+
status == :draft
|
89
|
+
end
|
90
|
+
|
91
|
+
def published?
|
92
|
+
status == :published
|
93
|
+
end
|
94
|
+
|
95
|
+
def approved?
|
96
|
+
status == :approved
|
97
|
+
end
|
98
|
+
|
99
|
+
## Who are the authors?
|
100
|
+
|
101
|
+
This plugin was originally developed for [BestTechVideos project](http://www.bestechvideos.com) by [Dmytro Shteflyuk](http://kpumuk.info)
|
102
|
+
and later cleaned up in Scribd repository and released to the public by [Oleksiy Kovyrin](http://kovyrin.net). All the code in this package is released under
|
103
|
+
the MIT license. For more details, see the LICENSE file.
|
@@ -2,10 +2,10 @@ module MagicEnum
|
|
2
2
|
module ClassMethods
|
3
3
|
# Method used to define ENUM attributes in your model. Examples:
|
4
4
|
#
|
5
|
-
#
|
6
|
-
# :draft
|
5
|
+
# STATUSES = {
|
6
|
+
# :draft => 0,
|
7
7
|
# :published => 1,
|
8
|
-
# :approved
|
8
|
+
# :approved => 2,
|
9
9
|
# }
|
10
10
|
# define_enum :status
|
11
11
|
#
|
@@ -31,31 +31,39 @@ module MagicEnum
|
|
31
31
|
#
|
32
32
|
# Look the following example:
|
33
33
|
#
|
34
|
-
#
|
35
|
-
# :unknown
|
36
|
-
# :draft
|
34
|
+
# STATUSES = {
|
35
|
+
# :unknown => 0,
|
36
|
+
# :draft => 1,
|
37
37
|
# :published => 2,
|
38
|
-
# :approved
|
38
|
+
# :approved => 3,
|
39
39
|
# }
|
40
40
|
# define_enum :status, :default => 1, :raise_on_invalid => true, :simple_accessors => true
|
41
41
|
#
|
42
42
|
# This example is identical to:
|
43
43
|
#
|
44
|
-
#
|
45
|
-
# :unknown
|
46
|
-
# :draft
|
44
|
+
# STATUSES = {
|
45
|
+
# :unknown => 0,
|
46
|
+
# :draft => 1,
|
47
47
|
# :published => 2,
|
48
|
-
# :approved
|
48
|
+
# :approved => 3,
|
49
49
|
# }
|
50
|
-
#
|
50
|
+
# STATUSES_INVERTED = STATUSES.invert
|
51
|
+
#
|
52
|
+
# def self.status_value(status)
|
53
|
+
# STATUSES[status]
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# def self.status_by_value(value)
|
57
|
+
# STATUSES_INVERTED[value]
|
58
|
+
# end
|
51
59
|
#
|
52
60
|
# def status
|
53
|
-
#
|
61
|
+
# self.class.status_by_value(self[:status]) || self.class.status_by_value(1)
|
54
62
|
# end
|
55
63
|
#
|
56
64
|
# def status=(value)
|
57
|
-
# raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model"
|
58
|
-
# self[:status] =
|
65
|
+
# raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model" unless STATUSES.key?(value)
|
66
|
+
# self[:status] = STATUSES[value]
|
59
67
|
# end
|
60
68
|
#
|
61
69
|
# def unknown?
|
@@ -75,65 +83,82 @@ module MagicEnum
|
|
75
83
|
# end
|
76
84
|
#
|
77
85
|
def define_enum(name, opts = {})
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
opts = opts.reverse_merge({
|
87
|
+
:raise_on_invalid => false,
|
88
|
+
:simple_accessors => false,
|
89
|
+
:named_scopes => false,
|
90
|
+
:scope_extensions => false,
|
91
|
+
})
|
84
92
|
name = name.to_sym
|
85
93
|
|
86
|
-
|
87
|
-
opts[:enum] = name.to_s.pluralize.classify.pluralize unless opts[:enum]
|
94
|
+
opts[:enum] ||= name.to_s.pluralize.upcase
|
88
95
|
enum = opts[:enum]
|
89
|
-
enum_inverted = "#{enum}
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
enum_inverted = "#{enum}_INVERTED"
|
97
|
+
enum_value = const_get(enum)
|
98
|
+
|
99
|
+
if opts.key?(:default)
|
100
|
+
opts[:default] = enum_value[opts[:default]] if opts[:default].is_a?(Symbol)
|
101
|
+
else
|
102
|
+
opts[:default] = enum_value.values.sort do |a, b|
|
103
|
+
if a.nil? and b.nil?
|
104
|
+
0
|
105
|
+
elsif a.nil?
|
106
|
+
-1
|
107
|
+
elsif b.nil?
|
108
|
+
1
|
109
|
+
else
|
110
|
+
a <=> b
|
111
|
+
end
|
112
|
+
end.first
|
113
|
+
end
|
114
|
+
|
115
|
+
const_set(enum_inverted, enum_value.invert)
|
116
|
+
|
117
|
+
class_eval <<-RUBY
|
118
|
+
def self.#{name}_value(name)
|
119
|
+
name = name.to_sym if name.is_a?(String)
|
120
|
+
#{enum}[name]
|
100
121
|
end
|
101
|
-
end.first unless opts.key?(:default)
|
102
122
|
|
103
|
-
|
123
|
+
def self.#{name}_by_value(value)
|
124
|
+
#{enum_inverted}[value]
|
125
|
+
end
|
104
126
|
|
105
|
-
|
106
|
-
|
107
|
-
|
127
|
+
def #{name}
|
128
|
+
self.class.#{name}_by_value(self[:#{name}]) || self.class.#{name}_by_value(#{opts[:default].inspect})
|
129
|
+
end
|
108
130
|
|
109
|
-
|
110
|
-
|
111
|
-
|
131
|
+
def #{name}_name
|
132
|
+
self.#{name}.to_s
|
133
|
+
end
|
112
134
|
|
113
|
-
|
114
|
-
|
115
|
-
if value.is_a?(Integer)
|
116
|
-
raise ArgumentError, "Invalid value \"#{value}\" for :#{name} attribute of the #{self.class} model" if opts[:raise_on_invalid] and !self.class.const_get(enum_inverted).key?(value)
|
117
|
-
self[name] = value
|
118
|
-
else
|
119
|
-
raise ArgumentError, "Invalid value \"#{value}\" for :#{name} attribute of the #{self.class} model" if opts[:raise_on_invalid] and !self.class.const_get(enum).key?(value)
|
120
|
-
self[name] = self.class.const_get(enum)[value] || opts[:default]
|
135
|
+
def #{name}_value
|
136
|
+
self[:#{name}] || #{opts[:default].inspect}
|
121
137
|
end
|
122
|
-
end
|
123
138
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
139
|
+
def #{name}=(value)
|
140
|
+
value = value.to_sym if value.is_a?(String)
|
141
|
+
if value.is_a?(Integer)
|
142
|
+
raise ArgumentError, "Invalid value \\"\#{value}\\" for :#{name} attribute of the #{self.name} model" if #{!!opts[:raise_on_invalid]} and !#{enum_inverted}.key?(value)
|
143
|
+
self[:#{name}] = value
|
144
|
+
else
|
145
|
+
raise ArgumentError, "Invalid value \\"\#{value}\\" for :#{name} attribute of the #{self.name} model" if #{!!opts[:raise_on_invalid]} and !#{enum}.key?(value)
|
146
|
+
self[:#{name}] = self.class.#{name}_value(value) || #{opts[:default].inspect}
|
128
147
|
end
|
129
148
|
end
|
149
|
+
RUBY
|
150
|
+
|
151
|
+
if opts[:simple_accessors]
|
152
|
+
enum_value.keys.each do |key|
|
153
|
+
class_eval "def #{key}?() #{name} == :#{key} end"
|
154
|
+
end
|
130
155
|
end
|
131
156
|
|
132
157
|
# Create named scopes for each enum value
|
133
158
|
if opts[:named_scopes]
|
134
159
|
scope_definition_method = respond_to?(:named_scope) ? :named_scope : :scope
|
135
160
|
|
136
|
-
|
161
|
+
enum_value.keys.each do |key|
|
137
162
|
define_enum_scope(enum, key.to_s.pluralize, name, key, opts[:scope_extensions])
|
138
163
|
end
|
139
164
|
|
data/lib/magic_enum/version.rb
CHANGED
data/magic_enum.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.files = `git ls-files`.split("\n")
|
19
19
|
s.require_paths = [ 'lib' ]
|
20
|
-
s.extra_rdoc_files = [ 'LICENSE', 'README.
|
20
|
+
s.extra_rdoc_files = [ 'LICENSE', 'README.md' ]
|
21
21
|
|
22
22
|
# Dependencies
|
23
23
|
s.add_dependency 'activerecord'
|
data/spec/magic_enum_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'magic_enum'
|
|
4
4
|
module MagicEnumHelper
|
5
5
|
class TestModelBase
|
6
6
|
extend MagicEnum::ClassMethods
|
7
|
-
|
7
|
+
STATUSES = { :unknown => 0, :draft => 1, :published => 2 }
|
8
8
|
|
9
9
|
def [](attr_name)
|
10
10
|
@status
|
@@ -27,69 +27,85 @@ describe 'Model with magic enum' do
|
|
27
27
|
@model = TestModelSimple.new
|
28
28
|
end
|
29
29
|
|
30
|
+
it 'should define helper class methods' do
|
31
|
+
expect(TestModelSimple.status_value(:draft)).to eq(1)
|
32
|
+
expect(TestModelSimple.status_value('draft')).to eq(1)
|
33
|
+
expect(TestModelSimple.status_value(:invalid)).to be_nil
|
34
|
+
|
35
|
+
expect(TestModelSimple.status_by_value(1)).to eq(:draft)
|
36
|
+
expect(TestModelSimple.status_by_value(-1)).to be_nil
|
37
|
+
end
|
38
|
+
|
30
39
|
it 'should define methods to get and set enum field' do
|
31
|
-
TestModelSimple.
|
32
|
-
TestModelSimple.
|
40
|
+
expect(TestModelSimple.method_defined?(:status)).to be_true
|
41
|
+
expect(TestModelSimple.method_defined?(:status=)).to be_true
|
42
|
+
expect(TestModelSimple.method_defined?(:status_name)).to be_true
|
43
|
+
expect(TestModelSimple.method_defined?(:status_value)).to be_true
|
33
44
|
end
|
34
45
|
|
35
46
|
it 'should store enum value using [] operation on model' do
|
36
47
|
@model.status = :draft
|
37
|
-
@model[:status].
|
38
|
-
@model.status.
|
48
|
+
expect(@model[:status]).to eq(1)
|
49
|
+
expect(@model.status).to eq(:draft)
|
39
50
|
@model.status = :unknown
|
40
|
-
@model[:status].
|
41
|
-
@model.status.
|
51
|
+
expect(@model[:status]).to eq(0)
|
52
|
+
expect(@model.status).to eq(:unknown)
|
42
53
|
end
|
43
54
|
|
44
55
|
it 'should store enum value if key is given as string' do
|
45
56
|
@model.status = 'draft'
|
46
|
-
@model[:status].
|
47
|
-
@model.status.
|
57
|
+
expect(@model[:status]).to eq(1)
|
58
|
+
expect(@model.status).to eq(:draft)
|
48
59
|
@model.status = 'unknown'
|
49
|
-
@model[:status].
|
50
|
-
@model.status.
|
60
|
+
expect(@model[:status]).to eq(0)
|
61
|
+
expect(@model.status).to eq(:unknown)
|
51
62
|
end
|
52
63
|
|
53
64
|
it 'should store enum value if key is given as integer equivalent' do
|
54
65
|
@model.status = 1
|
55
|
-
@model[:status].
|
56
|
-
@model.status.
|
66
|
+
expect(@model[:status]).to eq(1)
|
67
|
+
expect(@model.status).to eq(:draft)
|
57
68
|
@model.status = 0
|
58
|
-
@model[:status].
|
59
|
-
@model.status.
|
69
|
+
expect(@model[:status]).to eq(0)
|
70
|
+
expect(@model.status).to eq(:unknown)
|
60
71
|
end
|
61
72
|
|
62
73
|
it 'should not define simple accessors by default' do
|
63
|
-
@model.
|
64
|
-
@model.
|
65
|
-
@model.
|
74
|
+
expect(@model).to_not respond_to(:unknown?)
|
75
|
+
expect(@model).to_not respond_to(:draft?)
|
76
|
+
expect(@model).to_not respond_to(:published?)
|
66
77
|
end
|
67
78
|
|
68
79
|
it 'should not raise error when invalid value received' do
|
69
|
-
|
80
|
+
expect { @model.status = :invalid }.to_not raise_error
|
70
81
|
end
|
71
82
|
|
72
83
|
it 'should use default value 0 when invalid value received or current state invalid' do
|
73
84
|
@model[:status] = -1
|
74
|
-
@model.status.
|
85
|
+
expect(@model.status).to eq(:unknown)
|
75
86
|
@model.status = :published
|
76
|
-
@model.status.
|
87
|
+
expect(@model.status).to eq(:published)
|
77
88
|
@model.status = :invalid
|
78
|
-
@model[:status].
|
79
|
-
@model.status.
|
89
|
+
expect(@model[:status]).to eq(0)
|
90
|
+
expect(@model.status).to eq(:unknown)
|
80
91
|
end
|
81
92
|
|
82
93
|
it 'should return string value when _name method called' do
|
83
|
-
@model.status_name.
|
94
|
+
expect(@model.status_name).to eq('unknown')
|
95
|
+
@model.status = :published
|
96
|
+
expect(@model.status_name).to eq('published')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should return value when _value method called' do
|
100
|
+
expect(@model.status_value).to eq(0)
|
84
101
|
@model.status = :published
|
85
|
-
@model.
|
102
|
+
expect(@model.status_value).to eq(2)
|
86
103
|
end
|
87
104
|
|
88
105
|
it 'should not define named scopes by default' do
|
89
106
|
TestModelSimple.should_not_receive(:named_scope)
|
90
107
|
TestModelSimple.should_not_receive(:scope)
|
91
108
|
end
|
92
|
-
|
93
109
|
end
|
94
110
|
|
95
111
|
describe 'Model with magic enum and default value specified' do
|
@@ -105,22 +121,54 @@ describe 'Model with magic enum and default value specified' do
|
|
105
121
|
|
106
122
|
it 'should use default value when current state is invalid' do
|
107
123
|
@model[:status] = -1
|
108
|
-
@model.status.
|
124
|
+
expect(@model.status).to eq(:published)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should use default value when invalid value received' do
|
128
|
+
@model.status = nil
|
129
|
+
expect(@model.status).to eq(:published)
|
130
|
+
@model.status = :invalid
|
131
|
+
expect(@model.status).to eq(:published)
|
132
|
+
expect(@model[:status]).to eq(2)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should not interpret nil in the same way as 0' do
|
136
|
+
expect(@model[:status]).to be_nil
|
137
|
+
expect(@model.status).to eq(:published)
|
138
|
+
@model[:status] = 0
|
139
|
+
expect(@model.status).to eq(:unknown)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'Model with magic enum and default value specified as a symbol' do
|
144
|
+
include MagicEnumHelper
|
145
|
+
|
146
|
+
class TestModelWithDefault < MagicEnumHelper::TestModelBase
|
147
|
+
define_enum :status, :default => :published
|
148
|
+
end
|
149
|
+
|
150
|
+
before do
|
151
|
+
@model = TestModelWithDefault.new
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should use default value when current state is invalid' do
|
155
|
+
@model[:status] = -1
|
156
|
+
expect(@model.status).to eq(:published)
|
109
157
|
end
|
110
158
|
|
111
159
|
it 'should use default value when invalid value received' do
|
112
160
|
@model.status = nil
|
113
|
-
@model.status.
|
161
|
+
expect(@model.status).to eq(:published)
|
114
162
|
@model.status = :invalid
|
115
|
-
@model.status.
|
116
|
-
@model[:status].
|
163
|
+
expect(@model.status).to eq(:published)
|
164
|
+
expect(@model[:status]).to eq(2)
|
117
165
|
end
|
118
166
|
|
119
167
|
it 'should not interpret nil in the same way as 0' do
|
120
|
-
@model[:status].
|
121
|
-
@model.status.
|
168
|
+
expect(@model[:status]).to be_nil
|
169
|
+
expect(@model.status).to eq(:published)
|
122
170
|
@model[:status] = 0
|
123
|
-
@model.status.
|
171
|
+
expect(@model.status).to eq(:unknown)
|
124
172
|
end
|
125
173
|
end
|
126
174
|
|
@@ -128,7 +176,7 @@ describe 'Model with magic enum and default value specified as nil' do
|
|
128
176
|
include MagicEnumHelper
|
129
177
|
|
130
178
|
class TestModelWithDefaultNil < MagicEnumHelper::TestModelBase
|
131
|
-
|
179
|
+
SIMPLE_STATUSES = { :unknown => 0, :draft => 1, :published => 2, :simple => nil }
|
132
180
|
define_enum :simple_status, :default => nil
|
133
181
|
end
|
134
182
|
|
@@ -138,22 +186,22 @@ describe 'Model with magic enum and default value specified as nil' do
|
|
138
186
|
|
139
187
|
it 'should use default value when current state is invalid' do
|
140
188
|
@model[:simple_status] = -1
|
141
|
-
@model.simple_status.
|
189
|
+
expect(@model.simple_status).to eq(:simple)
|
142
190
|
end
|
143
191
|
|
144
192
|
it 'should use default value when invalid value received' do
|
145
193
|
@model.simple_status = nil
|
146
|
-
@model.simple_status.
|
194
|
+
expect(@model.simple_status).to eq(:simple)
|
147
195
|
@model.simple_status = :invalid
|
148
|
-
@model.simple_status.
|
149
|
-
@model[:simple_status].
|
196
|
+
expect(@model.simple_status).to eq(:simple)
|
197
|
+
expect(@model[:simple_status]).to be_nil
|
150
198
|
end
|
151
199
|
|
152
200
|
it 'should not interpret nil in the same way as 0' do
|
153
|
-
@model[:simple_status].
|
154
|
-
@model.simple_status.
|
201
|
+
expect(@model[:simple_status]).to be_nil
|
202
|
+
expect(@model.simple_status).to eq(:simple)
|
155
203
|
@model[:simple_status] = 0
|
156
|
-
@model.simple_status.
|
204
|
+
expect(@model.simple_status).to eq(:unknown)
|
157
205
|
end
|
158
206
|
end
|
159
207
|
|
@@ -170,36 +218,36 @@ describe 'Model with magic enum and raise_on_invalid option specified' do
|
|
170
218
|
|
171
219
|
context 'with symbol value' do
|
172
220
|
it 'should not raise error when valid value received' do
|
173
|
-
|
221
|
+
expect { @model.status = :draft }.to_not raise_error
|
174
222
|
end
|
175
223
|
|
176
224
|
it 'should raise error when invalid value received' do
|
177
|
-
|
225
|
+
expect { @model.status = :invalid }.to raise_error(ArgumentError)
|
178
226
|
end
|
179
227
|
|
180
228
|
it 'should show error description when invalid value received' do
|
181
229
|
begin
|
182
230
|
@model.status = :invalid
|
183
231
|
rescue => e
|
184
|
-
e.message.
|
232
|
+
expect(e.message).to eq('Invalid value "invalid" for :status attribute of the TestModelWithRaiseOnInvalid model')
|
185
233
|
end
|
186
234
|
end
|
187
235
|
end
|
188
236
|
|
189
237
|
context 'with integer value' do
|
190
238
|
it 'should not raise error when valid value received' do
|
191
|
-
|
239
|
+
expect { @model.status = 1 }.to_not raise_error
|
192
240
|
end
|
193
241
|
|
194
242
|
it 'should raise error when invalid value received' do
|
195
|
-
|
243
|
+
expect { @model.status = 4 }.to raise_error(ArgumentError)
|
196
244
|
end
|
197
245
|
|
198
246
|
it 'should show error description when invalid value received' do
|
199
247
|
begin
|
200
248
|
@model.status = 4
|
201
249
|
rescue => e
|
202
|
-
e.message.
|
250
|
+
expect(e.message).to eq('Invalid value "4" for :status attribute of the TestModelWithRaiseOnInvalid model')
|
203
251
|
end
|
204
252
|
end
|
205
253
|
end
|
@@ -218,9 +266,9 @@ describe 'Model with magic enum and simple_accessors option specified' do
|
|
218
266
|
end
|
219
267
|
|
220
268
|
it 'should define simple accessors by default' do
|
221
|
-
@model.
|
222
|
-
@model.
|
223
|
-
@model.
|
269
|
+
expect(@model).to respond_to(:unknown?)
|
270
|
+
expect(@model).to respond_to(:draft?)
|
271
|
+
expect(@model).to respond_to(:published?)
|
224
272
|
end
|
225
273
|
end
|
226
274
|
|
@@ -228,15 +276,15 @@ describe 'Model with magic enum and named_scopes option specified' do
|
|
228
276
|
include MagicEnumHelper
|
229
277
|
|
230
278
|
class TestModelWithNamedScopes < ActiveRecord::Base
|
231
|
-
|
279
|
+
STATUSES = { :unknown => 0, :draft => 1, :published => 2 }
|
232
280
|
define_enum :status, :named_scopes => true
|
233
281
|
end
|
234
282
|
|
235
283
|
it 'should define named_scopes' do
|
236
|
-
TestModelWithNamedScopes.
|
237
|
-
TestModelWithNamedScopes.
|
238
|
-
TestModelWithNamedScopes.
|
239
|
-
TestModelWithNamedScopes.
|
284
|
+
expect(TestModelWithNamedScopes).to respond_to(:unknowns)
|
285
|
+
expect(TestModelWithNamedScopes).to respond_to(:drafts)
|
286
|
+
expect(TestModelWithNamedScopes).to respond_to(:publisheds)
|
287
|
+
expect(TestModelWithNamedScopes).to respond_to(:of_status)
|
240
288
|
end
|
241
289
|
end
|
242
290
|
|
@@ -257,21 +305,21 @@ describe 'Model with magic enum and enum option specified' do
|
|
257
305
|
|
258
306
|
it 'should use custom enum' do
|
259
307
|
@model.status = :user
|
260
|
-
@model.status.
|
261
|
-
@model[:status].
|
308
|
+
expect(@model.status).to eq(:user)
|
309
|
+
expect(@model[:status]).to eq('u')
|
262
310
|
@model.status = :admin
|
263
|
-
@model.status.
|
264
|
-
@model[:status].
|
311
|
+
expect(@model.status).to eq(:admin)
|
312
|
+
expect(@model[:status]).to eq('a')
|
265
313
|
end
|
266
314
|
|
267
315
|
it 'should use option with min value as default' do
|
268
316
|
@model.status = :invalid
|
269
|
-
@model.status.
|
317
|
+
expect(@model.status).to eq(:admin)
|
270
318
|
end
|
271
319
|
end
|
272
320
|
|
273
321
|
describe 'ActiveRecord::Base class' do
|
274
322
|
it 'should include MagicEnum methods' do
|
275
|
-
ActiveRecord::Base.
|
323
|
+
expect(ActiveRecord::Base).to respond_to(:define_enum)
|
276
324
|
end
|
277
325
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: magic_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.beta1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Dmytro Shteflyuk
|
@@ -10,86 +9,76 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-
|
12
|
+
date: 2013-11-12 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: activerecord
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: rspec
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rake
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: rdoc
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - '>='
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - '>='
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: yard
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - '>='
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - '>='
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
description: MagicEnum is a simple ActiveRecord plugin that makes it easier to maintain
|
@@ -99,13 +88,14 @@ executables: []
|
|
99
88
|
extensions: []
|
100
89
|
extra_rdoc_files:
|
101
90
|
- LICENSE
|
102
|
-
- README.
|
91
|
+
- README.md
|
103
92
|
files:
|
104
93
|
- .gitignore
|
105
94
|
- .travis.yml
|
95
|
+
- CHANGELOG.md
|
106
96
|
- Gemfile
|
107
97
|
- LICENSE
|
108
|
-
- README.
|
98
|
+
- README.md
|
109
99
|
- Rakefile
|
110
100
|
- lib/magic_enum.rb
|
111
101
|
- lib/magic_enum/class_methods.rb
|
@@ -114,28 +104,27 @@ files:
|
|
114
104
|
- spec/magic_enum_spec.rb
|
115
105
|
homepage: https://github.com/kovyrin/magic-enum
|
116
106
|
licenses: []
|
107
|
+
metadata: {}
|
117
108
|
post_install_message:
|
118
109
|
rdoc_options:
|
119
110
|
- --charset=UTF-8
|
120
111
|
require_paths:
|
121
112
|
- lib
|
122
113
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
114
|
requirements:
|
125
|
-
- -
|
115
|
+
- - '>='
|
126
116
|
- !ruby/object:Gem::Version
|
127
117
|
version: '0'
|
128
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
119
|
requirements:
|
131
|
-
- -
|
120
|
+
- - '>'
|
132
121
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
122
|
+
version: 1.3.1
|
134
123
|
requirements: []
|
135
124
|
rubyforge_project:
|
136
|
-
rubygems_version: 1.
|
125
|
+
rubygems_version: 2.1.9
|
137
126
|
signing_key:
|
138
|
-
specification_version:
|
127
|
+
specification_version: 4
|
139
128
|
summary: ActiveRecord plugin that makes it easier to maintain ENUM-like attributes
|
140
129
|
in your models
|
141
130
|
test_files: []
|
data/README.rdoc
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
= MagicEnum
|
2
|
-
|
3
|
-
MagicEnum is a simple ActiveRecord plugin that makes it easier to maintain ENUM-like attributes in your models.
|
4
|
-
|
5
|
-
Examples:
|
6
|
-
|
7
|
-
Statuses = {
|
8
|
-
:draft => 0,
|
9
|
-
:published => 1,
|
10
|
-
:approved => 2
|
11
|
-
}
|
12
|
-
define_enum :status
|
13
|
-
|
14
|
-
== How to Use
|
15
|
-
|
16
|
-
Before using <tt>define_enum</tt>, you should define constant with ENUM options.
|
17
|
-
Constant name would be pluralized enum attribute name. Additional constant named
|
18
|
-
like YourEnumInverted would be created automatically and would contain
|
19
|
-
inverted hash.
|
20
|
-
|
21
|
-
<b>Please note</b>: nil and 0 are not the same values!
|
22
|
-
|
23
|
-
You could specify additional options:
|
24
|
-
|
25
|
-
* <tt>:default</tt> - value which will be used when current state of ENUM attribute is invalid or wrong value received. If it has not been specified, min value of the ENUM would be used.
|
26
|
-
* <tt>:raise_on_invalid</tt> - if +true+ an exception would be raised on invalid enum value received. If it is +false+, default value would be used instead of wrong one.
|
27
|
-
* <tt>:simple_accessors</tt> - if +true+, additional methods for each ENUM value would be defined in form value?. Methods returns +true+ when ENUM attribute has corresponding value.
|
28
|
-
* <tt>:enum</tt> - string with name of the ENUM hash.
|
29
|
-
|
30
|
-
Look the following example:
|
31
|
-
|
32
|
-
Statuses = {
|
33
|
-
:unknown => 0,
|
34
|
-
:draft => 1,
|
35
|
-
:published => 2,
|
36
|
-
:approved => 3
|
37
|
-
}
|
38
|
-
define_enum :status, :default => 1, :raise_on_invalid => true, :simple_accessors => true
|
39
|
-
|
40
|
-
This example is identical to:
|
41
|
-
|
42
|
-
Statuses = {
|
43
|
-
:unknown => 0,
|
44
|
-
:draft => 1,
|
45
|
-
:published => 2,
|
46
|
-
:approved => 3
|
47
|
-
}
|
48
|
-
StatusesInverted = Statuses.invert
|
49
|
-
|
50
|
-
def status
|
51
|
-
return StatusesInverted[self[:status].to_i] || StatusesInverted[1]
|
52
|
-
end
|
53
|
-
|
54
|
-
def status=(value)
|
55
|
-
raise ArgumentError, "Invalid value \"#{value}\" for :status attribute of the #{self.class} model" if Statuses[value].nil?
|
56
|
-
self[:status] = Statuses[value]
|
57
|
-
end
|
58
|
-
|
59
|
-
def unknown?
|
60
|
-
status == :unknown
|
61
|
-
end
|
62
|
-
|
63
|
-
def draft?
|
64
|
-
status == :draft
|
65
|
-
end
|
66
|
-
|
67
|
-
def published?
|
68
|
-
status == :published
|
69
|
-
end
|
70
|
-
|
71
|
-
def approved?
|
72
|
-
status == :approved
|
73
|
-
end
|
74
|
-
|
75
|
-
== Who are the authors?
|
76
|
-
|
77
|
-
This plugin was originally developed for BestTechVideos project (http://www.bestechvideos.com) by Dmytro Shteflyuk (http://kpumuk.info)
|
78
|
-
and later cleaned up in Scribd repository and released to the public by Oleksiy Kovyrin. All the code in this package is released under
|
79
|
-
the MIT license. For more details, see the LICENSE file.
|