enumerations 1.3.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 6c202450cd19bc9f524f6ef5756c44bd304a4ef6047d274abda8d165601b6e64
4
- data.tar.gz: 61977fd20143ade7cb63242cc0b6098a981861783b412b62fa6b36e28b195f35
2
+ SHA1:
3
+ metadata.gz: a75cec2684b73e9e83a7b60ddd48b95ac01fd991
4
+ data.tar.gz: 822d8484b921612c31deadd8491994ad1e22a66d
5
5
  SHA512:
6
- metadata.gz: 60cb0a9f041e566e090e7b26b5a099f912e6a63a94a652a165b1e83f1d71fd5b7d280c25ebe13e1bca12d16c4dd0407f8db736ad7893ec2ed491a21ef199ffbc
7
- data.tar.gz: 04f4aff2e90b826b5e47022083c919d28f561b9370963b9c37251c83eb1101c68b1500624c3ef0e4e039c88465da46a1afe707cd5cda15778dfb47a4bae16ed4
6
+ metadata.gz: 3df5039cf8d021b312058982c26edee6d8e24c56bd05a4f9cba6db2f55adef3f311d3181a544e774cd3607750d0c813e4935fcbf3079608eec3a7a142a546d4d
7
+ data.tar.gz: 04c31625eecf7f4276bf11d673aa66d2290ca086d49d728502cde004166a32c7a2ff051367356299feeee8399afc0b486551b00694b51fe47b69d1e72aaf05d1
data/Readme.md CHANGED
@@ -1,9 +1,12 @@
1
1
  Enumerations
2
2
  ============
3
3
 
4
- Rails plugin for enumerations in ActiveRecord models.
4
+ [![Gem Version](https://badge.fury.io/rb/enumerations.svg)](https://badge.fury.io/rb/enumerations)
5
+ [![Code Climate](https://codeclimate.com/github/infinum/enumerations/badges/gpa.svg)](https://codeclimate.com/github/infinum/enumerations)
6
+ [![Build Status](https://semaphoreci.com/api/v1/infinum/enumerations/branches/master/shields_badge.svg)](https://semaphoreci.com/infinum/enumerations)
7
+ [![Test Coverage](https://codeclimate.com/github/infinum/enumerations/badges/coverage.svg)](https://codeclimate.com/github/infinum/enumerations/coverage)
5
8
 
6
- [![Build Status](https://travis-ci.org/infinum/enumerations.svg?branch=master)](https://travis-ci.org/infinum/enumerations)
9
+ Rails plugin for enumerations in ActiveRecord models.
7
10
 
8
11
  Installation
9
12
  ============
@@ -17,10 +20,12 @@ gem 'enumerations'
17
20
  Usage
18
21
  =====
19
22
 
23
+ ## Defining enumerations
24
+
20
25
  Create a model for your enumerations:
21
26
 
22
27
  ```ruby
23
- class Status < Enumeration::Base
28
+ class Status < Enumerations::Base
24
29
  values draft: { id: 1, name: 'Draft' },
25
30
  review_pending: { id: 2, name: 'Review pending' },
26
31
  published: { id: 3, name: 'Published' }
@@ -30,7 +35,7 @@ end
30
35
  Or you can use `value` method for defining your enumerations:
31
36
 
32
37
  ```ruby
33
- class Status < Enumeration::Base
38
+ class Status < Enumerations::Base
34
39
  value :draft, id: 1, name: 'Draft'
35
40
  value :review_pending, id: 2, name: 'Review pending'
36
41
  value :published, id: 3, name: 'Published'
@@ -46,16 +51,21 @@ class Post < ActiveRecord::Base
46
51
  end
47
52
  ```
48
53
 
49
- You can pass attributes to specify which enumeratior and which column to use:
54
+ You can pass attributes to specify which enumeration and which column to use:
50
55
 
51
56
  ```ruby
52
57
  class Post < ActiveRecord::Base
53
58
  enumeration :status,
54
- foreign_key: :post_status_id, # specifies which column to use
55
- class_name: Post::Status # specifies the class of the enumerator
59
+ foreign_key: :post_status_id, # specifies which column to use
60
+ class_name: Post::Status # specifies the class of the enumerator
56
61
  validates :post_status_id, presence: true
57
62
  end
58
63
  ```
64
+ Attribute `foreign_key` you can pass as a `String` or a `Symbol`. Attribute `class_name` can be set as a `String`, a `Symbol` or a `String`.
65
+
66
+
67
+
68
+ ## Setting enumeration value to objects
59
69
 
60
70
  Set enumerations, find enumerations by `symbol`:
61
71
 
@@ -71,20 +81,56 @@ Or you can set enumerations on this way:
71
81
  @post.status = Status.draft
72
82
  ```
73
83
 
84
+ Also, you can set enumeration value like this:
85
+
86
+ ```ruby
87
+ @post.status_draft!
88
+ ```
89
+
90
+ > When you include enumerations into your model, you'll get methods for setting each enumeration value. Each method name is consists from enumeration name and enumeration value name with **!** at the end. Examples:
91
+
92
+ ```ruby
93
+ class Post < ActiveRecord::Base
94
+ enumeration :status
95
+ end
96
+
97
+ @post.status_draft!
98
+ ```
99
+
100
+ ```ruby
101
+ class User < ActiveRecord::Base
102
+ enumeration :role
103
+ end
104
+
105
+ @user.role_admin!
106
+ ```
107
+
108
+ ```ruby
109
+ class User < ActiveRecord::Base
110
+ enumeration :type, class_name: Role
111
+ end
112
+
113
+ @user.type_editor!
114
+ ```
115
+
116
+
117
+
118
+ ## Finder methods
119
+
74
120
  Find enumerations by `id`:
75
121
 
76
122
  ```ruby
77
- @post.status = Status.find(2) # => Review pending
123
+ @post.status = Status.find(2) # => Review pending
78
124
  @post.save
79
125
  ```
80
126
 
81
127
  Compare enumerations:
82
128
 
83
129
  ```ruby
84
- @post.status == :published # => true
85
- @post.status == 3 # => true
86
- @post.status == Status.find(:published) # => true
87
- @post.status.published? # => true
130
+ @post.status == :published # => true
131
+ @post.status == 3 # => true
132
+ @post.status == Status.find(:published) # => true
133
+ @post.status.published? # => true
88
134
  ```
89
135
 
90
136
  Get all enumerations:
@@ -93,6 +139,43 @@ Get all enumerations:
93
139
  Status.all
94
140
  ```
95
141
 
142
+
143
+
144
+ ## Scopes on model
145
+
146
+ With enumerations, you'll get scope for each enumeration value in the
147
+ following format:
148
+
149
+ ```ruby
150
+ with_#{enumeration_name}_#{enumeration_value_name}
151
+ ```
152
+
153
+ Examples:
154
+
155
+ ```ruby
156
+ class Post < ActiveRecord::Base
157
+ enumeration :status
158
+ end
159
+
160
+ Post.with_status_draft # => <#ActiveRecord::Relation []>
161
+ Post.with_status_review_pending # => <#ActiveRecord::Relation []>
162
+ ```
163
+
164
+ ```ruby
165
+ class Post < ActiveRecord::Base
166
+ enumeration :my_status, class_name: Status
167
+ end
168
+
169
+ Post.with_my_status_draft # => <#ActiveRecord::Relation []>
170
+ Post.with_my_status_review_pending # => <#ActiveRecord::Relation []>
171
+ ```
172
+
173
+ Each scope returns all records with specified enumeration value.
174
+
175
+
176
+
177
+ ## Forms usage
178
+
96
179
  Use in forms:
97
180
 
98
181
  ```ruby
@@ -108,7 +191,7 @@ Advance Usage
108
191
  Except `id` and `name` you can specify other attributes to your enumerations:
109
192
 
110
193
  ```ruby
111
- class Status < Enumeration::Base
194
+ class Status < Enumerations::Base
112
195
  value :draft, id: 1, name: 'Draft'
113
196
  value :review_pending, id: 2, name: 'Review pending', description: 'Some description...'
114
197
  value :published, id: 3, name: 'Published'
@@ -118,8 +201,8 @@ end
118
201
  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
202
 
120
203
  ```ruby
121
- Status.review_pending.description # => 'Some description...'
122
- Status.draft.description # => nil
204
+ Status.review_pending.description # => 'Some description...'
205
+ Status.draft.description # => nil
123
206
  ```
124
207
 
125
208
  Author
data/enumerations.gemspec CHANGED
@@ -2,9 +2,9 @@ require File.expand_path('../lib/enumerations/version', __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'enumerations'
5
- s.version = Enumeration::VERSION
6
- s.date = '2010-08-20'
7
- s.summary = "Enumerations for ActiveRecord!"
5
+ s.version = Enumerations::VERSION
6
+ s.date = '2016-08-15'
7
+ s.summary = 'Enumerations for ActiveRecord!'
8
8
  s.description = 'Extends ActiveRecord with enumeration capabilites.'
9
9
  s.authors = ['Tomislav Car', 'Nikica Jokic', 'Nikola Santic']
10
10
  s.email = ['tomislav@infinum.hr', 'nikica.jokic@infinum.hr', 'nikola.santic@infinum.hr']
@@ -13,6 +13,9 @@ Gem::Specification.new do |s|
13
13
  s.add_dependency 'activerecord'
14
14
  s.add_dependency 'activesupport'
15
15
  s.add_development_dependency 'pry-byebug'
16
+ s.add_development_dependency 'rake'
17
+ s.add_development_dependency 'codeclimate-test-reporter'
18
+ s.add_development_dependency 'sqlite3'
16
19
 
17
20
  s.files = `git ls-files`.split("\n")
18
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
data/lib/enumerations.rb CHANGED
@@ -7,8 +7,7 @@ require 'enumerations/version'
7
7
  require 'enumerations/base'
8
8
  require 'enumerations/reflection'
9
9
 
10
- # TODO: rename to Enumeration(s) in a major version change
11
- module Enumeration
10
+ module Enumerations
12
11
  extend ActiveSupport::Concern
13
12
 
14
13
  included do
@@ -27,17 +26,15 @@ module Enumeration
27
26
  # end
28
27
  #
29
28
  # user.role_id = 1
30
- # user.role => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin...>
29
+ # user.role => #<Enumerations::Value: @base=Role, @symbol=:admin...>
31
30
  #
32
31
  # user.role = Role.staff
33
32
  # user.role_id => 2
34
33
  #
35
- # TODO: add documentation for foreign_key and class_name
36
34
  def enumeration(name, options = {})
37
- options[:foreign_key] ||= "#{name}_id".to_sym
38
- options[:class_name] ||= name.to_s.camelize
35
+ reflection = Reflection.new(name, options)
39
36
 
40
- add_enumeration(name, options)
37
+ add_enumeration(reflection)
41
38
  end
42
39
 
43
40
  # Output all the enumerations that this model has defined
@@ -47,8 +44,9 @@ module Enumeration
47
44
  # Example:
48
45
  #
49
46
  # User.reflect_on_all_enumerations => # [
50
- # #<Enumeration::Reflection:0x007fe894724320 @name=:role...>,
51
- # #<Enumeration::Reflection:0x007fe89471d020 @name=:status...>]
47
+ # #<Enumerations::Reflection: @name=:role...>,
48
+ # #<Enumerations::Reflection: @name=:status...>
49
+ # ]
52
50
  #
53
51
  def reflect_on_all_enumerations
54
52
  _enumerations
@@ -56,41 +54,75 @@ module Enumeration
56
54
 
57
55
  private
58
56
 
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
57
+ def add_enumeration(reflection)
58
+ define_getter_method(reflection)
59
+ define_setter_method(reflection)
60
+ define_bang_methods(reflection)
61
+ define_scopes(reflection)
73
62
 
74
- enumerator_class.find(send(options[:foreign_key]))
63
+ self._enumerations += [reflection]
64
+ end
65
+
66
+ # Getter for belongs_to
67
+ #
68
+ # Example:
69
+ #
70
+ # user.role_id = 1
71
+ # user.role => #<Enumerations::Value: @base=Role, @symbol=:admin...>
72
+ #
73
+ def define_getter_method(reflection)
74
+ define_method(reflection.name) do
75
+ reflection.enumerator_class.find(send(reflection.foreign_key))
76
+ end
77
+ end
78
+
79
+ # Setter for belongs_to
80
+ #
81
+ # Example:
82
+ #
83
+ # user.role = Role.admin
84
+ # user.role_id => 1
85
+ #
86
+ def define_setter_method(reflection)
87
+ define_method("#{reflection.name}=") do |other|
88
+ send("#{reflection.foreign_key}=", other.id)
75
89
  end
90
+ end
76
91
 
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)
92
+ # Add bang methods for setting all enumeration values.
93
+ # All methods are prefixed with enumeration name.
94
+ #
95
+ # Example:
96
+ #
97
+ # user.role_admin!
98
+ # user.role => #<Enumerations::Value: @base=Role, @symbol=:admin...>
99
+ #
100
+ def define_bang_methods(reflection)
101
+ reflection.enumerator_class.all.each do |enumeration|
102
+ define_method("#{reflection.name}_#{enumeration.to_sym}!") do
103
+ send("#{reflection.name}=", enumeration)
104
+ end
86
105
  end
106
+ end
87
107
 
88
- self._enumerations += [Reflection.new(name, options)]
108
+ # Scopes for enumerated ActiveRecord model.
109
+ # Format of scope name is with_#{enumeration_name}_#{enumeration_value_name}.
110
+ #
111
+ # Example:
112
+ #
113
+ # User.with_role_admin => <#ActiveRecord::Relation []>
114
+ # User.with_role_editor => <#ActiveRecord::Relation []>
115
+ #
116
+ def define_scopes(reflection)
117
+ reflection.enumerator_class.all.each do |enumeration|
118
+ scope "with_#{reflection.name}_#{enumeration.symbol}",
119
+ -> { where(reflection.foreign_key => enumeration.id) }
120
+ end
89
121
  end
90
122
  end
91
123
  end
92
124
 
93
125
  # Extend ActiveRecord with Enumeration capabilites
94
126
  ActiveSupport.on_load(:active_record) do
95
- include Enumeration
127
+ include Enumerations
96
128
  end
@@ -1,8 +1,13 @@
1
1
  require 'active_support/core_ext/class/attribute'
2
2
  require 'active_support/core_ext/string/inflections'
3
+ require 'enumerations/value'
4
+ require 'enumerations/finder_methods'
3
5
 
4
- module Enumeration
6
+ module Enumerations
5
7
  class Base
8
+ extend Enumerations::FinderMethods
9
+ include Enumerations::Value
10
+
6
11
  class_attribute :_values, :_symbol_index
7
12
  self._values = {}
8
13
  self._symbol_index = {}
@@ -13,13 +18,11 @@ module Enumeration
13
18
  #
14
19
  # value :admin, id: 1, name: 'Admin', description: 'Some description...'
15
20
  #
16
- # Role.admin.id => # 1
17
- # Role.find(:admin).name => # "Admin"
18
- # Role.find(1).description => # "Some description..."
21
+ # Role.admin.id => # 1
22
+ # Role.find(:admin).name => # "Admin"
23
+ # Role.find(1).description => # "Some description..."
19
24
  #
20
25
  def self.value(symbol, attributes)
21
- # TODO: make this errors better if needed
22
- # TODO: test this errors
23
26
  raise 'Enumeration id is required' if attributes[:id].nil?
24
27
  raise "Duplicate symbol #{symbol}" if find(symbol)
25
28
  raise "Duplicate id #{attributes[:id]}" if find(attributes[:id])
@@ -31,8 +34,8 @@ module Enumeration
31
34
  #
32
35
  # Example:
33
36
  #
34
- # Role.admin => #<Enumeration::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin...>
35
- # Role.staff => #<Enumeration::Value:0x007f980e9cb0a0 @base=Role, @symbol=:staff...>
37
+ # Role.admin => #<Enumerations::Value: @base=Role, @symbol=:admin...>
38
+ # Role.staff => #<Enumerations::Value: @base=Role, @symbol=:staff...>
36
39
  #
37
40
  singleton_class.send(:define_method, symbol) do
38
41
  find(symbol)
@@ -71,117 +74,21 @@ module Enumeration
71
74
  #
72
75
  # Example:
73
76
  #
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
+ # Role.all => # [#<Enumerations::Value: @base=Role, @symbol=:admin...>,
78
+ # #<Enumerations::Value: @base=Role, @symbol=:manager...>,
79
+ # #<Enumerations::Value: @base=Role, @symbol=:staff...>]
77
80
  #
78
81
  def self.all
79
82
  _values.values
80
83
  end
81
84
 
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 Integer 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
85
+ attr_reader :symbol
116
86
 
117
87
  def initialize(symbol, attributes)
118
88
  @symbol = symbol
119
89
  @attributes = attributes
120
- create_instance_methods
121
- end
122
90
 
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 Integer 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
91
+ create_instance_methods
185
92
  end
186
93
  end
187
94
  end
@@ -0,0 +1,38 @@
1
+ module Enumerations
2
+ module FinderMethods
3
+ # Finds an enumeration by symbol, id or name
4
+ #
5
+ # Example:
6
+ #
7
+ # Role.find(:admin) => #<Enumerations::Value: @base=Role, @symbol=:admin...>
8
+ # Role.find(2) => #<Enumerations::Value: @base=Role, @symbol=:manager...>
9
+ # Role.find('2') => #<Enumerations::Value: @base=Role, @symbol=:manager...>
10
+ # Role.find('staff') => #<Enumerations::Value: @base=Role, @symbol=:staff...>
11
+ #
12
+ def find(key)
13
+ case key
14
+ when Symbol then find_by_key(key)
15
+ when String then find_by_key(key.to_sym) || find_by_id(key.to_i)
16
+ when Fixnum then find_by_id(key)
17
+ end
18
+ end
19
+
20
+ # Finds an enumeration by defined attribute. Similar to ActiveRecord::FinderMethods#find_by
21
+ #
22
+ # Example:
23
+ #
24
+ # Role.find_by(name: 'Admin') => #<Enumerations::Value: @base=Role, @symbol=:admin...>
25
+ #
26
+ def find_by(**args)
27
+ _values.values.find { |value| args.map { |k, v| value.send(k) == v }.all? }
28
+ end
29
+
30
+ def find_by_key(key)
31
+ _values[key]
32
+ end
33
+
34
+ def find_by_id(id)
35
+ _values[_symbol_index.key(id)]
36
+ end
37
+ end
38
+ end
@@ -1,18 +1,22 @@
1
- module Enumeration
1
+ module Enumerations
2
2
  class Reflection
3
3
  attr_reader :name
4
4
 
5
- def initialize(name, options)
5
+ def initialize(name, options = {})
6
6
  @name = name
7
7
  @options = options
8
8
  end
9
9
 
10
10
  def class_name
11
- @options[:class_name]
11
+ @class_name ||= (@options[:class_name] || name).to_s.camelize
12
12
  end
13
13
 
14
14
  def foreign_key
15
- @options[:foreign_key]
15
+ @foreign_key ||= (@options[:foreign_key] || "#{name}_id").to_sym
16
+ end
17
+
18
+ def enumerator_class
19
+ @enumerator_class ||= class_name.constantize
16
20
  end
17
21
  end
18
22
  end
@@ -0,0 +1,80 @@
1
+ module Enumerations
2
+ module Value
3
+ def to_i
4
+ id
5
+ end
6
+
7
+ def to_s
8
+ name
9
+ end
10
+
11
+ def to_sym
12
+ symbol
13
+ end
14
+
15
+ def to_param
16
+ id
17
+ end
18
+
19
+ # Comparison by id, symbol or object
20
+ #
21
+ # Example:
22
+ #
23
+ # Role.admin == 1 => true
24
+ # Role.admin == :admin => true
25
+ # Role.admin == Role.admin => true
26
+ # Role.admin == 2 => false
27
+ # Role.admin == :staff => false
28
+ # Role.admin == Role.staff => false
29
+ #
30
+ # TODO: test if case..when is working with this
31
+ def ==(other)
32
+ case other
33
+ when Fixnum then other == id
34
+ when Symbol then other == symbol
35
+ else super
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def create_instance_methods
42
+ define_attributes_getters
43
+ define_value_checking_method
44
+ end
45
+
46
+ # Getters for all attributes
47
+ #
48
+ # Example:
49
+ #
50
+ # Role.admin => #<Enumerations::Value:0x007fff45d7ec30 @base=Role, @symbol=:admin,
51
+ # @attributes={:id=>1, :name=>"Admin", :description=>"Some description..."}>
52
+ # user.role.id => # 1
53
+ # user.role.name => # "Admin"
54
+ # user.role.description => # "Some description..."
55
+ #
56
+ def define_attributes_getters
57
+ @attributes.each do |key, _|
58
+ next if respond_to?(key)
59
+
60
+ self.class.send :define_method, key do
61
+ @attributes[key]
62
+ end
63
+ end
64
+ end
65
+
66
+ # Predicate methods for values
67
+ #
68
+ # Example:
69
+ #
70
+ # user.role = Role.admin
71
+ # user.role.admin? => # true
72
+ # user.role.staff? => # false
73
+ #
74
+ def define_value_checking_method
75
+ self.class.send :define_method, "#{symbol}?" do
76
+ __callee__[0..-2].to_sym == symbol
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
- module Enumeration
2
- VERSION = '1.3.2'
1
+ module Enumerations
2
+ VERSION = '2.0.0'
3
3
  end
data/test/base_test.rb CHANGED
@@ -13,6 +13,18 @@ class BaseTest < Minitest::Test
13
13
  refute_same :published, status.symbol
14
14
  end
15
15
 
16
+ def test_lookup_by_string_id
17
+ status = Status.find('1')
18
+
19
+ assert_equal :draft, status.symbol
20
+ end
21
+
22
+ def test_lookup_by_string_key
23
+ status = Status.find('draft')
24
+
25
+ assert_equal :draft, status.symbol
26
+ end
27
+
16
28
  def test_find_by
17
29
  status = Status.find_by(name: 'Draft')
18
30
 
@@ -32,6 +44,19 @@ class BaseTest < Minitest::Test
32
44
  assert_equal statuses.first, Status.draft
33
45
  end
34
46
 
47
+ def test_symbols
48
+ status_symbols = Status.symbols
49
+
50
+ assert_equal 5, status_symbols.size
51
+ assert_equal status_symbols.first, Status.draft.to_sym
52
+ end
53
+
54
+ def test_required_id
55
+ assert_raises 'Enumeration id is required' do
56
+ Class.new.value draft: { name: 'Draft' }
57
+ end
58
+ end
59
+
35
60
  def test_duplicated_id
36
61
  assert_raises 'Duplicate id 1' do
37
62
  Class.new.values draft: { id: 1, name: 'Draft' },
@@ -57,45 +82,17 @@ class BaseTest < Minitest::Test
57
82
  end
58
83
  end
59
84
 
60
- def test_with_defined_custom_attributes_visible
61
- status = Status.find(:none)
85
+ def test_enumerations_custom_instance_method
86
+ role = Role.find(:admin)
62
87
 
63
- assert_equal true, status.visible
88
+ assert_equal 'user_Admin', role.my_custom_name
64
89
  end
65
90
 
66
- def test_with_defined_custom_attributes_deleted
67
- status = Status.find(:deleted)
68
-
69
- assert_equal true, status.deleted
70
- end
91
+ def test_all_enumerations_has_custom_instance_methods
92
+ roles = Role.all
71
93
 
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
94
+ assert_silent do
95
+ roles.map(&:my_custom_name)
96
+ end
100
97
  end
101
98
  end
@@ -0,0 +1,15 @@
1
+ require 'logger'
2
+
3
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
4
+
5
+ ActiveRecord::Schema.define do
6
+ create_table :posts, force: true do |t|
7
+ t.integer :status_id
8
+ t.integer :some_other_status_id
9
+ end
10
+
11
+ create_table :users, force: true do |t|
12
+ t.integer :role_id
13
+ t.string :status_id
14
+ end
15
+ end
@@ -18,6 +18,20 @@ class EnumerationsTest < Minitest::Test
18
18
  assert_equal 'Draft', p.status.to_s
19
19
  end
20
20
 
21
+ def test_model_bang_assignment
22
+ p = Post.new
23
+ p.status_draft!
24
+
25
+ assert_equal 'Draft', p.status.to_s
26
+ end
27
+
28
+ def test_model_bang_assignment_with_custom_name
29
+ p = Post.new
30
+ p.different_status_draft!
31
+
32
+ assert_equal 'Draft', p.different_status.to_s
33
+ end
34
+
21
35
  def test_model_via_id_assignment
22
36
  p = Post.new
23
37
  p.some_other_status_id = Status.published.id
@@ -38,4 +52,37 @@ class EnumerationsTest < Minitest::Test
38
52
 
39
53
  assert_equal false, p.status.published?
40
54
  end
55
+
56
+ def test_multiple_enumerations_on_model
57
+ enumerations = User.reflect_on_all_enumerations
58
+
59
+ assert_equal 2, enumerations.size
60
+
61
+ assert_equal :role, enumerations.first.name
62
+ assert_equal :role_id, enumerations.first.foreign_key
63
+
64
+ assert_equal :status, enumerations[1].name
65
+ assert_equal :status_id, enumerations[1].foreign_key
66
+ end
67
+
68
+ def test_multiple_enumeration_assignments_on_model
69
+ u = User.new
70
+ u.role = Role.admin
71
+ u.status = Status.published
72
+
73
+ assert_equal 'Admin', u.role.to_s
74
+ assert_equal 'Published', u.status.to_s
75
+ end
76
+
77
+ def test_enumerated_class_has_scopes
78
+ Role.all do |role|
79
+ assert_respond_to User, ['with_role', role.name].join('_').to_sym
80
+ end
81
+ end
82
+
83
+ def test_enumerated_class_scope_hash_value
84
+ query_hash = User.with_role_admin.where_values_hash.symbolize_keys
85
+
86
+ assert_equal query_hash, role_id: 1
87
+ end
41
88
  end
@@ -1,11 +1,38 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  class ReflectionTest < Minitest::Test
4
- def test_reflections
5
- reflection = Enumeration::Reflection.new(:role, class_name: 'Role', foreign_key: :role_id)
4
+ def test_reflection_with_all_attributes
5
+ reflection = Enumerations::Reflection.new(:status, class_name: 'Status',
6
+ foreign_key: :status_id)
6
7
 
7
- assert_equal :role, reflection.name
8
- assert_equal 'Role', reflection.class_name
9
- assert_equal :role_id, reflection.foreign_key
8
+ assert_equal :status, reflection.name
9
+ assert_equal 'Status', reflection.class_name
10
+ assert_equal :status_id, reflection.foreign_key
11
+ assert_equal ::Status, reflection.enumerator_class
12
+ end
13
+
14
+ def test_reflection_without_class_name_and_foreign_key
15
+ reflection = Enumerations::Reflection.new(:status)
16
+
17
+ assert_equal :status, reflection.name
18
+ assert_equal 'Status', reflection.class_name
19
+ assert_equal :status_id, reflection.foreign_key
20
+ assert_equal ::Status, reflection.enumerator_class
21
+ end
22
+
23
+ def test_reflection_with_custom_name_and_without_foreign_key
24
+ reflection = Enumerations::Reflection.new(:my_status, class_name: 'Status')
25
+
26
+ assert_equal :my_status, reflection.name
27
+ assert_equal 'Status', reflection.class_name
28
+ assert_equal :my_status_id, reflection.foreign_key
29
+ assert_equal ::Status, reflection.enumerator_class
30
+ end
31
+
32
+ def test_reflection_with_class_name_as_constant
33
+ reflection = Enumerations::Reflection.new(:status, class_name: Status)
34
+
35
+ assert_equal 'Status', reflection.class_name
36
+ assert_equal ::Status, reflection.enumerator_class
10
37
  end
11
38
  end
data/test/test_helper.rb CHANGED
@@ -1,14 +1,14 @@
1
- # TODO: improve tests
1
+ require 'codeclimate-test-reporter'
2
+ CodeClimate::TestReporter.start
3
+
2
4
  require 'minitest/autorun'
3
5
  require 'enumerations'
6
+ require 'active_record'
4
7
  require 'pry'
5
8
 
6
- # Faking ActiveRecord
7
- class MockActiveRecordBase
8
- include Enumeration
9
- end
9
+ require_relative 'database_helper'
10
10
 
11
- class Status < Enumeration::Base
11
+ class Status < Enumerations::Base
12
12
  values draft: { id: 1, name: 'Draft' },
13
13
  review_pending: { id: 2, name: 'Review pending' },
14
14
  published: { id: 3, name: 'Published' }
@@ -17,9 +17,26 @@ class Status < Enumeration::Base
17
17
  value :deleted, id: 5, deleted: true
18
18
  end
19
19
 
20
- class Post < MockActiveRecordBase
20
+ class Role < Enumerations::Base
21
+ value :admin, id: 1, name: 'Admin', admin: true
22
+ value :editor, id: 2, name: 'Editor'
23
+ value :author, id: 3, name: 'Author'
24
+
25
+ def my_custom_name
26
+ ['user', name].join('_')
27
+ end
28
+ end
29
+
30
+ class Post < ActiveRecord::Base
21
31
  attr_accessor :status_id, :some_other_status_id
22
32
 
23
33
  enumeration :status
24
34
  enumeration :different_status, foreign_key: :some_other_status_id, class_name: 'Status'
25
35
  end
36
+
37
+ class User < ActiveRecord::Base
38
+ attr_accessor :role_id, :status_id
39
+
40
+ enumeration :role
41
+ enumeration :status
42
+ end
@@ -0,0 +1,63 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ValueTest < Minitest::Test
4
+ def test_equal_by_id
5
+ status = Status.find(:draft)
6
+
7
+ assert_equal true, status == 1
8
+ end
9
+
10
+ def test_equal_by_symbol
11
+ status = Status.draft
12
+
13
+ assert_equal true, status == :draft
14
+ end
15
+
16
+ def test_equal_by_enumeration
17
+ status = Status.draft
18
+
19
+ assert_equal true, status == Status.draft
20
+ end
21
+
22
+ def test_not_equal_by_enumeration
23
+ status = Status.draft
24
+
25
+ assert_equal false, status == Status.published
26
+ end
27
+
28
+ def test_with_defined_custom_attributes_visible
29
+ status = Status.find(:none)
30
+
31
+ assert_equal true, status.visible
32
+ end
33
+
34
+ def test_with_defined_custom_attributes_deleted
35
+ status = Status.find(:deleted)
36
+
37
+ assert_equal true, status.deleted
38
+ end
39
+
40
+ def test_without_defined_custom_attributes
41
+ status = Status.find(:draft)
42
+
43
+ assert_equal nil, status.visible
44
+ end
45
+
46
+ def test_enumeration_to_i
47
+ status = Status.find(:draft)
48
+
49
+ assert_equal status.to_i, 1
50
+ end
51
+
52
+ def test_enumeration_to_sym
53
+ status = Status.find(:draft)
54
+
55
+ assert_equal status.to_sym, :draft
56
+ end
57
+
58
+ def test_enumeration_to_param
59
+ status = Status.find(:draft)
60
+
61
+ assert_equal status.to_param, 1
62
+ end
63
+ end
data/test/version_test.rb CHANGED
@@ -2,6 +2,6 @@ require_relative 'test_helper'
2
2
 
3
3
  class VersionTest < Minitest::Test
4
4
  def test_version
5
- assert_equal '1.3.0', Enumeration::VERSION
5
+ assert_equal '2.0.0', Enumerations::VERSION
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumerations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomislav Car
8
8
  - Nikica Jokic
9
9
  - Nikola Santic
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2010-08-20 00:00:00.000000000 Z
13
+ date: 2016-08-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -54,6 +54,48 @@ dependencies:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: codeclimate-test-reporter
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: sqlite3
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
57
99
  description: Extends ActiveRecord with enumeration capabilites.
58
100
  email:
59
101
  - tomislav@infinum.hr
@@ -64,24 +106,27 @@ extensions: []
64
106
  extra_rdoc_files: []
65
107
  files:
66
108
  - ".gitignore"
67
- - ".travis.yml"
68
109
  - Gemfile
69
110
  - Rakefile
70
111
  - Readme.md
71
112
  - enumerations.gemspec
72
113
  - lib/enumerations.rb
73
114
  - lib/enumerations/base.rb
115
+ - lib/enumerations/finder_methods.rb
74
116
  - lib/enumerations/reflection.rb
117
+ - lib/enumerations/value.rb
75
118
  - lib/enumerations/version.rb
76
119
  - test/base_test.rb
120
+ - test/database_helper.rb
77
121
  - test/enumerations_test.rb
78
122
  - test/reflection_test.rb
79
123
  - test/test_helper.rb
124
+ - test/value_test.rb
80
125
  - test/version_test.rb
81
126
  homepage: https://github.com/infinum/enumerations
82
127
  licenses: []
83
128
  metadata: {}
84
- post_install_message:
129
+ post_install_message:
85
130
  rdoc_options: []
86
131
  require_paths:
87
132
  - lib
@@ -96,13 +141,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
141
  - !ruby/object:Gem::Version
97
142
  version: '0'
98
143
  requirements: []
99
- rubygems_version: 3.0.3
100
- signing_key:
144
+ rubyforge_project:
145
+ rubygems_version: 2.5.1
146
+ signing_key:
101
147
  specification_version: 4
102
148
  summary: Enumerations for ActiveRecord!
103
149
  test_files:
104
150
  - test/base_test.rb
151
+ - test/database_helper.rb
105
152
  - test/enumerations_test.rb
106
153
  - test/reflection_test.rb
107
154
  - test/test_helper.rb
155
+ - test/value_test.rb
108
156
  - test/version_test.rb
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.0
4
- - 2.3.1
5
- script: rake