enumerations 1.1.0 → 1.3.0
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/Rakefile +2 -1
- data/Readme.md +98 -43
- data/enumerations.gemspec +10 -7
- data/lib/enumerations.rb +77 -113
- data/lib/enumerations/base.rb +187 -0
- data/lib/enumerations/reflection.rb +18 -0
- data/lib/enumerations/version.rb +3 -0
- data/test/base_test.rb +101 -0
- data/test/enumerations_test.rb +16 -36
- data/test/reflection_test.rb +11 -0
- data/test/test_helper.rb +14 -13
- data/test/version_test.rb +7 -0
- metadata +48 -18
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0301fc3454228a9bfb34210934af6e60396179b4
|
4
|
+
data.tar.gz: 76ea564324b2e3e79565009e6ae2182a56d84a84
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8c9a14f99e311b3e65a41bb9d03cee5788b288352270f3cbbc0b5c19b2dd4e823573613267d03c73a239a6c5b9039d2c10ccce9c4e2326e9e9f4b27427486ae7
|
7
|
+
data.tar.gz: aeff9a7fcf7ce2177831dadc13eaf940b534112a31fe51e0f2167cf31d57acf3d85ae3c409b3b5c0e670e893707216d8b85e2c52b65e7cd20b5cec29b413223b
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Rakefile
CHANGED
data/Readme.md
CHANGED
@@ -1,73 +1,128 @@
|
|
1
1
|
Enumerations
|
2
|
-
|
2
|
+
============
|
3
3
|
|
4
4
|
Rails plugin for enumerations in ActiveRecord models.
|
5
5
|
|
6
|
-
|
7
|
-
=======
|
6
|
+
[](https://travis-ci.org/infinum/enumerations)
|
8
7
|
|
9
|
-
|
8
|
+
Installation
|
9
|
+
============
|
10
10
|
|
11
|
-
|
11
|
+
Inside your `Gemfile` add the following:
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
```ruby
|
14
|
+
gem 'enumerations'
|
15
|
+
```
|
16
16
|
|
17
17
|
Usage
|
18
18
|
=====
|
19
19
|
|
20
|
-
Create a model for your enumerations
|
20
|
+
Create a model for your enumerations:
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
```ruby
|
23
|
+
class Status < Enumeration::Base
|
24
|
+
values draft: { id: 1, name: 'Draft' },
|
25
|
+
review_pending: { id: 2, name: 'Review pending' },
|
26
|
+
published: { id: 3, name: 'Published' }
|
27
|
+
end
|
28
|
+
```
|
27
29
|
|
28
|
-
|
30
|
+
Or you can use `value` method for defining your enumerations:
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
```ruby
|
33
|
+
class Status < Enumeration::Base
|
34
|
+
value :draft, id: 1, name: 'Draft'
|
35
|
+
value :review_pending, id: 2, name: 'Review pending'
|
36
|
+
value :published, id: 3, name: 'Published'
|
37
|
+
end
|
38
|
+
```
|
34
39
|
|
35
|
-
|
40
|
+
Include enumerations for integer fields in other models:
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
|
42
|
+
```ruby
|
43
|
+
class Post < ActiveRecord::Base
|
44
|
+
enumeration :status
|
45
|
+
validates :status_id, presence: true
|
46
|
+
end
|
47
|
+
```
|
40
48
|
|
41
|
-
|
49
|
+
You can pass attributes to specify which enumeratior and which column to use:
|
42
50
|
|
43
|
-
|
44
|
-
|
51
|
+
```ruby
|
52
|
+
class Post < ActiveRecord::Base
|
53
|
+
enumeration :status,
|
54
|
+
foreign_key: :post_status_id, # specifies which column to use
|
55
|
+
class_name: Post::Status # specifies the class of the enumerator
|
56
|
+
validates :post_status_id, presence: true
|
57
|
+
end
|
58
|
+
```
|
45
59
|
|
46
|
-
|
60
|
+
Set enumerations, find enumerations by `symbol`:
|
47
61
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
62
|
+
```ruby
|
63
|
+
@post = Post.first
|
64
|
+
@post.status = Status.find(:draft)
|
65
|
+
@post.save
|
66
|
+
```
|
52
67
|
|
53
|
-
|
68
|
+
Or you can set enumerations on this way:
|
54
69
|
|
55
|
-
|
70
|
+
```ruby
|
71
|
+
@post.status = Status.draft
|
72
|
+
```
|
56
73
|
|
57
|
-
|
74
|
+
Find enumerations by `id`:
|
58
75
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
76
|
+
```ruby
|
77
|
+
@post.status = Status.find(2) # => Review pending
|
78
|
+
@post.save
|
79
|
+
```
|
63
80
|
|
64
|
-
|
65
|
-
====
|
81
|
+
Compare enumerations:
|
66
82
|
|
67
|
-
|
83
|
+
```ruby
|
84
|
+
@post.status == :published # => true
|
85
|
+
@post.status == 3 # => true
|
86
|
+
@post.status == Status.find(:published) # => true
|
87
|
+
@post.status.published? # => true
|
88
|
+
```
|
89
|
+
|
90
|
+
Get all enumerations:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Status.all
|
94
|
+
```
|
95
|
+
|
96
|
+
Use in forms:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
%p
|
100
|
+
= f.label :status_id
|
101
|
+
%br
|
102
|
+
= f.collection_select :status_id, Status.all, :id, :name
|
103
|
+
```
|
104
|
+
|
105
|
+
Advance Usage
|
106
|
+
=====
|
107
|
+
|
108
|
+
Except `id` and `name` you can specify other attributes to your enumerations:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
class Status < Enumeration::Base
|
112
|
+
value :draft, id: 1, name: 'Draft'
|
113
|
+
value :review_pending, id: 2, name: 'Review pending', description: 'Some description...'
|
114
|
+
value :published, id: 3, name: 'Published'
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
Every enumeration has `id`, `name` and `description` methods. If you call method that is not in attribute list for enumeration, it will return `nil`.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
Status.review_pending.description # => 'Some description...'
|
122
|
+
Status.draft.description # => nil
|
123
|
+
```
|
68
124
|
|
69
125
|
Author
|
70
126
|
======
|
71
127
|
|
72
|
-
Copyright
|
73
|
-
|
128
|
+
Copyright © 2010 Tomislav Car, Infinum Ltd.
|
data/enumerations.gemspec
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
+
require File.expand_path('../lib/enumerations/version', __FILE__)
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = 'enumerations'
|
3
|
-
s.version =
|
5
|
+
s.version = Enumeration::VERSION
|
4
6
|
s.date = '2010-08-20'
|
5
7
|
s.summary = "Enumerations for ActiveRecord!"
|
6
|
-
s.description =
|
7
|
-
s.authors = [
|
8
|
-
s.email = [
|
8
|
+
s.description = 'Extends ActiveRecord with enumeration capabilites.'
|
9
|
+
s.authors = ['Tomislav Car', 'Nikica Jokic', 'Nikola Santic']
|
10
|
+
s.email = ['tomislav@infinum.hr', 'nikica.jokic@infinum.hr', 'nikola.santic@infinum.hr']
|
9
11
|
s.homepage = 'https://github.com/infinum/enumerations'
|
10
|
-
|
12
|
+
|
11
13
|
s.add_dependency 'activerecord'
|
12
14
|
s.add_dependency 'activesupport'
|
13
|
-
|
15
|
+
s.add_development_dependency 'pry-byebug'
|
16
|
+
|
14
17
|
s.files = `git ls-files`.split("\n")
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
19
|
end
|
data/lib/enumerations.rb
CHANGED
@@ -1,132 +1,96 @@
|
|
1
|
-
require 'active_support
|
2
|
-
require 'active_support/
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/core_ext/class/attribute'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
3
5
|
|
6
|
+
require 'enumerations/version'
|
7
|
+
require 'enumerations/base'
|
8
|
+
require 'enumerations/reflection'
|
9
|
+
|
10
|
+
# TODO: rename to Enumeration(s) in a major version change
|
4
11
|
module Enumeration
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
class_attribute :_enumerations
|
16
|
+
self._enumerations = []
|
9
17
|
end
|
10
|
-
|
18
|
+
|
11
19
|
module ClassMethods
|
12
|
-
#
|
20
|
+
# Create an enumeration for the symbol <tt>name</tt>.
|
21
|
+
# Options include <tt>foreign_key</tt> attribute and <tt>class_name</tt>
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
#
|
25
|
+
# class User < ActiveRecord::Base
|
26
|
+
# enumeration :role
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# user.role_id = 1
|
30
|
+
# user.role => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin...>
|
31
|
+
#
|
32
|
+
# user.role = Role.staff
|
33
|
+
# user.role_id => 2
|
34
|
+
#
|
35
|
+
# TODO: add documentation for foreign_key and class_name
|
13
36
|
def enumeration(name, options = {})
|
14
37
|
options[:foreign_key] ||= "#{name}_id".to_sym
|
15
38
|
options[:class_name] ||= name.to_s.camelize
|
16
|
-
|
17
|
-
|
18
|
-
define_method name do
|
19
|
-
options[:class_name].constantize.find(send(options[:foreign_key]))
|
20
|
-
end
|
21
|
-
|
22
|
-
# setter for belongs_to
|
23
|
-
define_method "#{name}=" do |other|
|
24
|
-
send("#{options[:foreign_key]}=", other.id)
|
25
|
-
end
|
26
|
-
|
27
|
-
# store a list of used enumerations
|
28
|
-
@_all_enumerations ||= []
|
29
|
-
@_all_enumerations << EnumerationReflection.new(name, options)
|
39
|
+
|
40
|
+
add_enumeration(name, options)
|
30
41
|
end
|
31
42
|
|
32
|
-
#
|
43
|
+
# Output all the enumerations that this model has defined
|
44
|
+
# Returns an array of Reflection objects for all the
|
45
|
+
# enumerations in the class.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
#
|
49
|
+
# User.reflect_on_all_enumerations => # [
|
50
|
+
# #<Enumeration::Reflection:0x007fe894724320 @name=:role...>,
|
51
|
+
# #<Enumeration::Reflection:0x007fe89471d020 @name=:status...>]
|
52
|
+
#
|
33
53
|
def reflect_on_all_enumerations
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class EnumerationReflection < Struct.new(:name, :options)
|
39
|
-
def class_name
|
40
|
-
options[:class_name]
|
41
|
-
end
|
42
|
-
|
43
|
-
def foreign_key
|
44
|
-
options[:foreign_key]
|
54
|
+
_enumerations
|
45
55
|
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# used as a base class for enumeration classes
|
49
|
-
class Base < Struct.new(:id, :name, :symbol)
|
50
|
-
class_attribute :all, :id_index, :symbol_index
|
51
|
-
|
52
|
-
def singleton_class
|
53
|
-
class << self
|
54
|
-
self
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.values(values)
|
59
|
-
# all values
|
60
|
-
self.all = []
|
61
|
-
# for id based lookup
|
62
|
-
self.id_index = {}
|
63
|
-
# for symbol based lookup
|
64
|
-
self.symbol_index = {}
|
65
|
-
|
66
|
-
values.each_pair do |symbol, attributes|
|
67
|
-
attributes[:name] ||= symbol.to_s.humanize
|
68
|
-
object = self.new(attributes[:id], attributes[:name], symbol)
|
69
56
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
self.symbol_index[id.to_sym]
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# FIXME for some reason this doesn't work for case..when expressions
|
93
|
-
def ==(object)
|
94
|
-
if object.is_a?(Fixnum)
|
95
|
-
object == self.id
|
96
|
-
elsif object.is_a?(Symbol)
|
97
|
-
object == self.symbol
|
98
|
-
elsif object.is_a?(self.class)
|
99
|
-
object.id == self.id
|
57
|
+
private
|
58
|
+
|
59
|
+
def add_enumeration(name, options)
|
60
|
+
# Getter for belongs_to
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
#
|
64
|
+
# user.role_id = 1
|
65
|
+
# user.role => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin...>
|
66
|
+
#
|
67
|
+
define_method name do
|
68
|
+
enumerator_class = if options[:class_name].is_a?(Class)
|
69
|
+
options[:class_name]
|
70
|
+
else
|
71
|
+
options[:class_name].constantize
|
72
|
+
end
|
73
|
+
|
74
|
+
enumerator_class.find(send(options[:foreign_key]))
|
100
75
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
def to_sym
|
113
|
-
symbol
|
114
|
-
end
|
115
|
-
|
116
|
-
def to_param
|
117
|
-
id
|
118
|
-
end
|
119
|
-
|
120
|
-
def method_missing(method_name, *args)
|
121
|
-
symbol = method_name.to_s.gsub(/[?]$/, '')
|
122
|
-
if self.class.find(symbol) && method_name =~ /[?]$/
|
123
|
-
self.symbol == symbol.to_sym
|
124
|
-
else
|
125
|
-
super(method_name, args)
|
76
|
+
|
77
|
+
# Setter for belongs_to
|
78
|
+
#
|
79
|
+
# Example:
|
80
|
+
#
|
81
|
+
# user.role = Role.admin
|
82
|
+
# user.role_id => 1
|
83
|
+
#
|
84
|
+
define_method "#{name}=" do |other|
|
85
|
+
send("#{options[:foreign_key]}=", other.id)
|
126
86
|
end
|
87
|
+
|
88
|
+
self._enumerations += [Reflection.new(name, options)]
|
127
89
|
end
|
128
90
|
end
|
129
91
|
end
|
130
92
|
|
131
93
|
# Extend ActiveRecord with Enumeration capabilites
|
132
|
-
|
94
|
+
ActiveSupport.on_load(:active_record) do
|
95
|
+
include Enumeration
|
96
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
require 'active_support/core_ext/string/inflections'
|
3
|
+
|
4
|
+
module Enumeration
|
5
|
+
class Base
|
6
|
+
class_attribute :_values, :_symbol_index
|
7
|
+
self._values = {}
|
8
|
+
self._symbol_index = {}
|
9
|
+
|
10
|
+
# Adding new value to enumeration
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# value :admin, id: 1, name: 'Admin', description: 'Some description...'
|
15
|
+
#
|
16
|
+
# Role.admin.id => # 1
|
17
|
+
# Role.find(:admin).name => # "Admin"
|
18
|
+
# Role.find(1).description => # "Some description..."
|
19
|
+
#
|
20
|
+
def self.value(symbol, attributes)
|
21
|
+
# TODO: make this errors better if needed
|
22
|
+
# TODO: test this errors
|
23
|
+
raise 'Enumeration id is required' if attributes[:id].nil?
|
24
|
+
raise "Duplicate symbol #{symbol}" if find(symbol)
|
25
|
+
raise "Duplicate id #{attributes[:id]}" if find(attributes[:id])
|
26
|
+
|
27
|
+
self._values = _values.merge(symbol => new(symbol, attributes))
|
28
|
+
self._symbol_index = _symbol_index.merge(symbol => attributes[:id])
|
29
|
+
|
30
|
+
# Adds name base finder methods
|
31
|
+
#
|
32
|
+
# Example:
|
33
|
+
#
|
34
|
+
# Role.admin => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin...>
|
35
|
+
# Role.staff => #<Enumeration::Value:0x007f980e9cb0a0 @base=Role, @symbol=:staff...>
|
36
|
+
#
|
37
|
+
singleton_class.send(:define_method, symbol) do
|
38
|
+
find(symbol)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Adding multiple values to enumeration
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
#
|
46
|
+
# values admin: { id: 1, name: 'Admin' },
|
47
|
+
# manager: { id: 2, name: 'Manager' },
|
48
|
+
# staff: { id: 3, name: 'Staff', description: 'Some description...' }
|
49
|
+
#
|
50
|
+
# Role.admin.id => # 1
|
51
|
+
# Role.find(:manager).name => # "Manager"
|
52
|
+
# Role.find(3).description => # "Some description..."
|
53
|
+
#
|
54
|
+
def self.values(values)
|
55
|
+
values.each do |symbol, attributes|
|
56
|
+
value(symbol, attributes)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns an array of all enumeration symbols
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
#
|
64
|
+
# Role.symbols => # [:admin, :manager, :staff]
|
65
|
+
#
|
66
|
+
def self.symbols
|
67
|
+
_values.keys
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an array of all enumeration values
|
71
|
+
#
|
72
|
+
# Example:
|
73
|
+
#
|
74
|
+
# Role.all => # [#<Enumeration::Value:0x007f8ed7f46100 @base=Role, @symbol=:admin...>,
|
75
|
+
# #<Enumeration::Value:0x007f8ed7f45de0 @base=Role, @symbol=:manager...>,
|
76
|
+
# #<Enumeration::Value:0x007f8ed7f45ae8 @base=Role, @symbol=:staff...>]
|
77
|
+
#
|
78
|
+
def self.all
|
79
|
+
_values.values
|
80
|
+
end
|
81
|
+
|
82
|
+
# Finds an enumeration by symbol, id or name
|
83
|
+
#
|
84
|
+
# Example:
|
85
|
+
#
|
86
|
+
# Role.find(:admin) => #<Enumeration::Value:0x007f8ed7f46100 @base=Role, @symbol=:admin...>
|
87
|
+
# Role.find(2) => #<Enumeration::Value:0x007f8ed7f45de0 @base=Role, @symbol=:manager...>
|
88
|
+
# Role.find('2') => #<Enumeration::Value:0x007f8ed7f45de0 @base=Role, @symbol=:manager...>
|
89
|
+
# Role.find('staff') => #<Enumeration::Value:0x007f8ed7f45ae8 @base=Role, @symbol=:staff...>
|
90
|
+
#
|
91
|
+
def self.find(key)
|
92
|
+
case key
|
93
|
+
when Symbol then find_by_key(key)
|
94
|
+
when String then find_by_key(key.to_sym) || find_by_id(key.to_i)
|
95
|
+
when Fixnum then find_by_id(key)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Finds an enumeration by defined attribute. Simmilar to AcriveRecord::FinderMethods#find_by
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
#
|
103
|
+
# Role.find_by(name: 'Admin') => #<Enumeration::Value:0x007f8ed7f46100 @base=Role, @symbol=:admin...>
|
104
|
+
#
|
105
|
+
def self.find_by(**args)
|
106
|
+
_values.values.find { |value| args.map { |k, v| value.send(k) == v }.all? }
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.find_by_key(key)
|
110
|
+
_values[key]
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.find_by_id(id)
|
114
|
+
_values[_symbol_index.key(id)]
|
115
|
+
end
|
116
|
+
|
117
|
+
def initialize(symbol, attributes)
|
118
|
+
@symbol = symbol
|
119
|
+
@attributes = attributes
|
120
|
+
create_instance_methods
|
121
|
+
end
|
122
|
+
|
123
|
+
attr_reader :symbol
|
124
|
+
|
125
|
+
def to_i
|
126
|
+
id
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_s
|
130
|
+
name
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_sym
|
134
|
+
@symbol
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_param
|
138
|
+
id
|
139
|
+
end
|
140
|
+
|
141
|
+
# Comparison by id, symbol or object
|
142
|
+
#
|
143
|
+
# Example:
|
144
|
+
#
|
145
|
+
# Role.admin == 1 => true
|
146
|
+
# Role.admin == :admin => true
|
147
|
+
# Role.admin == Role.admin => true
|
148
|
+
# Role.admin == 2 => false
|
149
|
+
# Role.admin == :staff => false
|
150
|
+
# Role.admin == Role.staff => false
|
151
|
+
#
|
152
|
+
# TODO: test if case..when is working with this
|
153
|
+
def ==(other)
|
154
|
+
case other
|
155
|
+
when Fixnum then other == id
|
156
|
+
when Symbol then other == @symbol
|
157
|
+
else super
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
# Getters for all attributes
|
164
|
+
#
|
165
|
+
# Example:
|
166
|
+
#
|
167
|
+
# Role.admin => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin,
|
168
|
+
# @attributes={:id=>1, :name=>"Admin", :description=>"Some description..."}>
|
169
|
+
# user.role.id => # 1
|
170
|
+
# user.role.name => # "Admin"
|
171
|
+
# user.role.description => # "Some description..."
|
172
|
+
# user.role.admin? => # true
|
173
|
+
# user.role.staff? => # false
|
174
|
+
#
|
175
|
+
def create_instance_methods
|
176
|
+
@attributes.each do |key, _|
|
177
|
+
self.class.send :define_method, key do
|
178
|
+
@attributes[key]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
self.class.send :define_method, "#{@symbol}?" do
|
183
|
+
__callee__[0..-2].to_sym == @symbol
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Enumeration
|
2
|
+
class Reflection
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name, options)
|
6
|
+
@name = name
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def class_name
|
11
|
+
@options[:class_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def foreign_key
|
15
|
+
@options[:foreign_key]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class BaseTest < Minitest::Test
|
4
|
+
def test_lookup_by_symbol
|
5
|
+
status = Status.find(:draft)
|
6
|
+
|
7
|
+
assert_equal :draft, status.symbol
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_lookup_fail_by_symbol
|
11
|
+
status = Status.find(:draft)
|
12
|
+
|
13
|
+
refute_same :published, status.symbol
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_find_by
|
17
|
+
status = Status.find_by(name: 'Draft')
|
18
|
+
|
19
|
+
assert_equal :draft, status.symbol
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_fail_find_by
|
23
|
+
status = Status.find_by(name: 'Draft1')
|
24
|
+
|
25
|
+
assert_equal nil, status
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_all
|
29
|
+
statuses = Status.all
|
30
|
+
|
31
|
+
assert_equal 5, statuses.size
|
32
|
+
assert_equal statuses.first, Status.draft
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_duplicated_id
|
36
|
+
assert_raises 'Duplicate id 1' do
|
37
|
+
Class.new.values draft: { id: 1, name: 'Draft' },
|
38
|
+
test: { id: 1, name: 'Draft' }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_duplicated_symbol
|
43
|
+
assert_raises 'Duplicate symbol draft' do
|
44
|
+
obj = Class.new
|
45
|
+
|
46
|
+
obj.value :draft, id: 1, name: 'Draft'
|
47
|
+
obj.value :draft, id: 2, name: 'Draft Again'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_all_has_custom_attributes
|
52
|
+
statuses = Status.all
|
53
|
+
|
54
|
+
assert_silent do
|
55
|
+
statuses.map(&:visible)
|
56
|
+
statuses.map(&:deleted)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_with_defined_custom_attributes_visible
|
61
|
+
status = Status.find(:none)
|
62
|
+
|
63
|
+
assert_equal true, status.visible
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_with_defined_custom_attributes_deleted
|
67
|
+
status = Status.find(:deleted)
|
68
|
+
|
69
|
+
assert_equal true, status.deleted
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_without_defined_custom_attributes
|
73
|
+
status = Status.find(:draft)
|
74
|
+
|
75
|
+
assert_equal nil, status.visible
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_equal_by_id
|
79
|
+
status = Status.find(:draft)
|
80
|
+
|
81
|
+
assert_equal true, status == 1
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_equal_by_symbol
|
85
|
+
status = Status.draft
|
86
|
+
|
87
|
+
assert_equal true, status == :draft
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_equal_by_enumeration
|
91
|
+
status = Status.draft
|
92
|
+
|
93
|
+
assert_equal true, status == Status.draft
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_not_equal_by_enumeration
|
97
|
+
status = Status.draft
|
98
|
+
|
99
|
+
assert_equal false, status == Status.published
|
100
|
+
end
|
101
|
+
end
|
data/test/enumerations_test.rb
CHANGED
@@ -1,61 +1,41 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
2
|
|
3
|
-
class EnumerationsTest < Test
|
4
|
-
|
5
|
-
def test_lookup_by_symbol
|
6
|
-
status = Status.find(:draft)
|
7
|
-
|
8
|
-
assert_equal :draft, status.symbol
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_lookup_fail_by_symbol
|
12
|
-
status = Status.find(:draft)
|
13
|
-
|
14
|
-
assert_not_equal :published, status.symbol
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_all
|
18
|
-
statuses = Status.all
|
19
|
-
|
20
|
-
assert_equal 3, statuses.size
|
21
|
-
assert_equal statuses.first, Status.draft
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_reflections
|
3
|
+
class EnumerationsTest < Minitest::Test
|
4
|
+
def test_reflect_on_all_enumerations
|
25
5
|
enumerations = Post.reflect_on_all_enumerations
|
26
6
|
|
27
7
|
assert_equal 2, enumerations.size
|
28
8
|
assert_equal :status, enumerations.first.name
|
29
9
|
assert_equal 'Status', enumerations.first.class_name
|
30
|
-
|
10
|
+
|
31
11
|
assert_equal :some_other_status_id, enumerations[1].foreign_key
|
32
12
|
end
|
33
|
-
|
13
|
+
|
34
14
|
def test_model_enumeration_assignment
|
35
15
|
p = Post.new
|
36
|
-
p.status = Status.draft
|
37
|
-
|
38
|
-
assert_equal
|
16
|
+
p.status = Status.draft
|
17
|
+
|
18
|
+
assert_equal 'Draft', p.status.to_s
|
39
19
|
end
|
40
|
-
|
20
|
+
|
41
21
|
def test_model_via_id_assignment
|
42
|
-
p = Post.new
|
22
|
+
p = Post.new
|
43
23
|
p.some_other_status_id = Status.published.id
|
44
|
-
|
45
|
-
assert_equal
|
24
|
+
|
25
|
+
assert_equal 'Published', p.different_status.to_s
|
46
26
|
end
|
47
|
-
|
27
|
+
|
48
28
|
def test_boolean_lookup
|
49
29
|
p = Post.new
|
50
30
|
p.status = Status.draft
|
51
|
-
|
31
|
+
|
52
32
|
assert_equal true, p.status.draft?
|
53
33
|
end
|
54
|
-
|
34
|
+
|
55
35
|
def test_false_boolean_lookup
|
56
36
|
p = Post.new
|
57
37
|
p.status = Status.draft
|
58
|
-
|
38
|
+
|
59
39
|
assert_equal false, p.status.published?
|
60
40
|
end
|
61
|
-
end
|
41
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class ReflectionTest < Minitest::Test
|
4
|
+
def test_reflections
|
5
|
+
reflection = Enumeration::Reflection.new(:role, class_name: 'Role', foreign_key: :role_id)
|
6
|
+
|
7
|
+
assert_equal :role, reflection.name
|
8
|
+
assert_equal 'Role', reflection.class_name
|
9
|
+
assert_equal :role_id, reflection.foreign_key
|
10
|
+
end
|
11
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
-
|
1
|
+
# TODO: improve tests
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'enumerations'
|
4
|
+
require 'pry'
|
2
5
|
|
3
|
-
#
|
4
|
-
|
5
|
-
require 'test/unit'
|
6
|
-
require 'enumerations'
|
7
|
-
|
8
|
-
# faking activerecord
|
6
|
+
# Faking ActiveRecord
|
9
7
|
class MockActiveRecordBase
|
10
8
|
include Enumeration
|
11
9
|
end
|
12
10
|
|
13
11
|
class Status < Enumeration::Base
|
14
|
-
values :
|
15
|
-
:
|
16
|
-
:
|
12
|
+
values draft: { id: 1, name: 'Draft' },
|
13
|
+
review_pending: { id: 2, name: 'Review pending' },
|
14
|
+
published: { id: 3, name: 'Published' }
|
15
|
+
|
16
|
+
value :none, id: 4, name: 'None', visible: true
|
17
|
+
value :deleted, id: 5, deleted: true
|
17
18
|
end
|
18
19
|
|
19
20
|
class Post < MockActiveRecordBase
|
20
21
|
attr_accessor :status_id, :some_other_status_id
|
21
|
-
|
22
|
+
|
22
23
|
enumeration :status
|
23
|
-
enumeration :different_status, :
|
24
|
-
end
|
24
|
+
enumeration :different_status, foreign_key: :some_other_status_id, class_name: 'Status'
|
25
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: enumerations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Tomislav Car
|
@@ -11,30 +10,50 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date: 2010-08-20 00:00:00.
|
13
|
+
date: 2010-08-20 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: activerecord
|
18
|
-
requirement:
|
19
|
-
none: false
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
20
18
|
requirements:
|
21
|
-
- -
|
19
|
+
- - ">="
|
22
20
|
- !ruby/object:Gem::Version
|
23
21
|
version: '0'
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
27
29
|
- !ruby/object:Gem::Dependency
|
28
30
|
name: activesupport
|
29
|
-
requirement:
|
30
|
-
none: false
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
31
32
|
requirements:
|
32
|
-
- -
|
33
|
+
- - ">="
|
33
34
|
- !ruby/object:Gem::Version
|
34
35
|
version: '0'
|
35
36
|
type: :runtime
|
36
37
|
prerelease: false
|
37
|
-
version_requirements:
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: pry-byebug
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
38
57
|
description: Extends ActiveRecord with enumeration capabilites.
|
39
58
|
email:
|
40
59
|
- tomislav@infinum.hr
|
@@ -44,37 +63,48 @@ executables: []
|
|
44
63
|
extensions: []
|
45
64
|
extra_rdoc_files: []
|
46
65
|
files:
|
47
|
-
- .gitignore
|
66
|
+
- ".gitignore"
|
67
|
+
- ".travis.yml"
|
68
|
+
- Gemfile
|
48
69
|
- Rakefile
|
49
70
|
- Readme.md
|
50
71
|
- enumerations.gemspec
|
51
72
|
- lib/enumerations.rb
|
73
|
+
- lib/enumerations/base.rb
|
74
|
+
- lib/enumerations/reflection.rb
|
75
|
+
- lib/enumerations/version.rb
|
76
|
+
- test/base_test.rb
|
52
77
|
- test/enumerations_test.rb
|
78
|
+
- test/reflection_test.rb
|
53
79
|
- test/test_helper.rb
|
80
|
+
- test/version_test.rb
|
54
81
|
homepage: https://github.com/infinum/enumerations
|
55
82
|
licenses: []
|
83
|
+
metadata: {}
|
56
84
|
post_install_message:
|
57
85
|
rdoc_options: []
|
58
86
|
require_paths:
|
59
87
|
- lib
|
60
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
89
|
requirements:
|
63
|
-
- -
|
90
|
+
- - ">="
|
64
91
|
- !ruby/object:Gem::Version
|
65
92
|
version: '0'
|
66
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
-
none: false
|
68
94
|
requirements:
|
69
|
-
- -
|
95
|
+
- - ">="
|
70
96
|
- !ruby/object:Gem::Version
|
71
97
|
version: '0'
|
72
98
|
requirements: []
|
73
99
|
rubyforge_project:
|
74
|
-
rubygems_version:
|
100
|
+
rubygems_version: 2.5.1
|
75
101
|
signing_key:
|
76
|
-
specification_version:
|
102
|
+
specification_version: 4
|
77
103
|
summary: Enumerations for ActiveRecord!
|
78
104
|
test_files:
|
105
|
+
- test/base_test.rb
|
79
106
|
- test/enumerations_test.rb
|
107
|
+
- test/reflection_test.rb
|
80
108
|
- test/test_helper.rb
|
109
|
+
- test/version_test.rb
|
110
|
+
has_rdoc:
|