enumerate_it 1.2.8 → 1.2.9
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 +4 -4
- data/.gitignore +3 -24
- data/{spec/spec.opts → .rspec} +0 -0
- data/.travis.yml +17 -0
- data/Appraisals +6 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile.lock +33 -30
- data/{README.markdown → README.md} +96 -104
- data/Rakefile +1 -1
- data/enumerate_it.gemspec +22 -0
- data/gemfiles/activesupport_3_0.gemfile +8 -0
- data/gemfiles/activesupport_3_1.gemfile +8 -0
- data/gemfiles/activesupport_3_2.gemfile +8 -0
- data/gemfiles/activesupport_4_0.gemfile +8 -0
- data/gemfiles/activesupport_4_1.gemfile +8 -0
- data/gemfiles/activesupport_4_2.gemfile +8 -0
- data/lib/enumerate_it.rb +4 -266
- data/lib/enumerate_it/base.rb +3 -2
- data/lib/enumerate_it/version.rb +1 -1
- data/spec/enumerate_it/base_spec.rb +35 -5
- data/spec/enumerate_it_spec.rb +4 -1
- data/spec/spec_helper.rb +12 -12
- data/spec/support/test_classes.rb +1 -1
- metadata +26 -33
data/Rakefile
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path('../lib/enumerate_it/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ['Cássio Marques', 'Lucas Caton']
|
5
|
+
gem.description = 'Enumerations for Ruby with some magic powers!'
|
6
|
+
gem.summary = 'Ruby Enumerations'
|
7
|
+
gem.homepage = 'https://github.com/lucascaton/enumerate_it'
|
8
|
+
|
9
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
10
|
+
gem.files = `git ls-files`.split("\n")
|
11
|
+
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
12
|
+
gem.name = 'enumerate_it'
|
13
|
+
gem.require_paths = ['lib']
|
14
|
+
gem.version = EnumerateIt::VERSION
|
15
|
+
|
16
|
+
gem.add_dependency 'activesupport', '>= 3.0.0'
|
17
|
+
|
18
|
+
gem.add_development_dependency 'appraisal'
|
19
|
+
gem.add_development_dependency 'pry'
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec', '~> 2.14.1'
|
22
|
+
end
|
data/lib/enumerate_it.rb
CHANGED
@@ -1,276 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
# = Description
|
8
|
-
#
|
9
|
-
# Ok, I know there are a lot of different solutions to this problem. But none of them solved my problem,
|
10
|
-
# so here's EnumerateIt. I needed to build a Rails application around a legacy database and this database was
|
11
|
-
# filled with those small, unchangeable tables used to create foreign key constraints everywhere.
|
12
|
-
#
|
13
|
-
# == For example:
|
14
|
-
#
|
15
|
-
# Table "public.relationshipstatus"
|
16
|
-
# Column | Type | Modifiers
|
17
|
-
# -------------+---------------+-----------
|
18
|
-
# code | character(1) | not null
|
19
|
-
# description | character(11) |
|
20
|
-
# Indexes:
|
21
|
-
# "relationshipstatus_pkey" PRIMARY KEY, btree (code)
|
22
|
-
#
|
23
|
-
# select * from relationshipstatus;
|
24
|
-
# code | description
|
25
|
-
# --------+--------------
|
26
|
-
# 1 | Single
|
27
|
-
# 2 | Married
|
28
|
-
# 3 | Widow
|
29
|
-
# 4 | Divorced
|
30
|
-
#
|
31
|
-
# And then I had things like a people table with a 'relationship_status' column with a foreign key
|
32
|
-
# pointing to the relationshipstatus table.
|
33
|
-
#
|
34
|
-
# While this is a good thing from the database normalization perspective, managing this values in
|
35
|
-
# my tests was very hard. More than this, referencing them in my code using magic numbers was terrible
|
36
|
-
# and meaningless: What's does it mean when we say that someone or something is '2'?
|
37
|
-
#
|
38
|
-
# Enter EnumerateIt.
|
39
|
-
#
|
40
|
-
# = Creating enumerations
|
41
|
-
#
|
42
|
-
# Enumerations are created as models, but you can put then anywhere in your application. In Rails
|
43
|
-
# applications, I put them inside models/.
|
44
|
-
#
|
45
|
-
# class RelationshipStatus < EnumerateIt::Base
|
46
|
-
# associate_values(
|
47
|
-
# :single => [1, 'Single'],
|
48
|
-
# :married => [2, 'Married'],
|
49
|
-
# :widow => [3, 'Widow'],
|
50
|
-
# :divorced => [4, 'Divorced'],
|
51
|
-
# )
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# This will create some nice stuff:
|
55
|
-
#
|
56
|
-
# - Each enumeration's value will turn into a constant:
|
57
|
-
#
|
58
|
-
# RelationshipsStatus::SINGLE # returns 1
|
59
|
-
# RelationshipStatus::MARRIED # returns 2 and so on...
|
60
|
-
#
|
61
|
-
# - You can retrieve a list with all the enumeration codes:
|
62
|
-
#
|
63
|
-
# RelationshipStatus.list # [1,2,3,4]
|
64
|
-
#
|
65
|
-
# You can get an array of options, ready to use with the 'select', 'select_tag', etc family of Rails helpers.
|
66
|
-
#
|
67
|
-
# RelationshipStatus.to_a # [["Divorced", 4],["Married", 2],["Single", 1],["Widow", 3]]
|
68
|
-
#
|
69
|
-
# You can retrive a list with values for a group of enumeration constants
|
70
|
-
#
|
71
|
-
# RelationshipStatus.values_for %w(MARRIED SINGLE) # [2, 1]
|
72
|
-
#
|
73
|
-
# You can retrieve the value for a specific enumeration constant:
|
74
|
-
#
|
75
|
-
# RelationshipStatus.value_for("MARRIED") # 2
|
76
|
-
#
|
77
|
-
# You can iterate over the list of the enumeration's values:
|
78
|
-
#
|
79
|
-
# RelationshipStatus.each_value { |value| # ... }
|
80
|
-
#
|
81
|
-
# You can iterate over the list of the enumeration's translations:
|
82
|
-
#
|
83
|
-
# RelationshipStatus.each_translation { |translation| # ... }
|
84
|
-
#
|
85
|
-
# You can retrieve the symbol used to declare a specific enumeration value:
|
86
|
-
#
|
87
|
-
# RelationshipStatus.key_for(RelationshioStatus::MARRIED) # :married
|
88
|
-
#
|
89
|
-
# - You can manipulate the hash used to create the enumeration:
|
90
|
-
#
|
91
|
-
# RelationshipStatus.enumeration # returns the exact hash used to define the enumeration
|
92
|
-
#
|
93
|
-
# You can also create enumerations in the following ways:
|
94
|
-
#
|
95
|
-
# * Passing an array of symbols, so that the respective value for each symbol will be the stringified version of the symbol itself:
|
96
|
-
#
|
97
|
-
# class RelationshipStatus < EnumerateIt::Base
|
98
|
-
# associate_values :married, :single
|
99
|
-
# end
|
100
|
-
#
|
101
|
-
# RelationshipStatus::MARRIED # returns "married" and so on
|
102
|
-
#
|
103
|
-
# * Passing hashes where the value for each key/pair does not include a translation. In this case, the I18n feature will be used (more on this below):
|
104
|
-
#
|
105
|
-
# class RelationshipStatus < EnumerateIt::Base
|
106
|
-
# associate_values :married => 1, :single => 2
|
107
|
-
# end
|
108
|
-
#
|
109
|
-
# = Using enumerations
|
110
|
-
#
|
111
|
-
# The cool part is that you can use these enumerations with any class, be it an ActiveRecord instance
|
112
|
-
# or not.
|
113
|
-
#
|
114
|
-
# class Person
|
115
|
-
# extend EnumerateIt
|
116
|
-
# attr_accessor :relationship_status
|
117
|
-
#
|
118
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus
|
119
|
-
# end
|
120
|
-
#
|
121
|
-
# The :with option is not required. If you ommit it, EnumerateIt will try to load an
|
122
|
-
# enumeration class based on the camelized attribute name.
|
123
|
-
#
|
124
|
-
# This will create:
|
125
|
-
#
|
126
|
-
# - A humanized description for the values of the enumerated attribute:
|
127
|
-
#
|
128
|
-
# p = Person.new
|
129
|
-
# p.relationship_status = RelationshipStatus::DIVORCED
|
130
|
-
# p.relationship_status_humanize # => 'Divorced'
|
131
|
-
#
|
132
|
-
# - If you don't supply a humanized string to represent an option, EnumerateIt will use a 'humanized'
|
133
|
-
# version of the hash's key to humanize the attribute's value
|
134
|
-
#
|
135
|
-
# class RelationshipStatus < EnumerateIt::Base
|
136
|
-
# associate_values(
|
137
|
-
# :married => 1,
|
138
|
-
# :single => 2
|
139
|
-
# )
|
140
|
-
# end
|
141
|
-
#
|
142
|
-
# p = Person.new
|
143
|
-
# p.relationship_status = RelationshipStatus::MARRIED
|
144
|
-
# p.relationship_status_humanize # => 'Married'
|
145
|
-
#
|
146
|
-
# - The associated enumerations can be retrieved with the 'enumerations' class method.
|
147
|
-
# Person.enumerations[:relationship_status] # => RelationshipStatus
|
148
|
-
#
|
149
|
-
# - If you pass the :create_helpers option as 'true', it will create a helper method for each enumeration
|
150
|
-
# option (this option defaults to false):
|
151
|
-
#
|
152
|
-
# class Person < ActiveRecord::Base
|
153
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
|
154
|
-
# end
|
155
|
-
#
|
156
|
-
# p = Person.new
|
157
|
-
# p.relationship_status = RelationshipStatus::MARRIED
|
158
|
-
# p.married? #=> true
|
159
|
-
# p.divorced? #=> false
|
160
|
-
#
|
161
|
-
# - It's also possible to "namespace" the created helper methods, passing a hash to the :create_helpers option.
|
162
|
-
# This can be useful when two or more of the enumerations used share the same constants.
|
163
|
-
#
|
164
|
-
# class Person < ActiveRecord::Base
|
165
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :prefix => true }
|
166
|
-
# end
|
167
|
-
#
|
168
|
-
# p = Person.new
|
169
|
-
# p.relationship_status = RelationshipStatus::MARRIED
|
170
|
-
# p.relationship_status_married? #=> true
|
171
|
-
# p.relationship_status_divoced? #=> false
|
172
|
-
#
|
173
|
-
# - You can define polymorphic behavior for the enum values, so you can define a class for each of
|
174
|
-
# them:
|
175
|
-
#
|
176
|
-
# class RelationshipStatus < EnumerateIt::Base
|
177
|
-
# associate_values :married, :single
|
178
|
-
#
|
179
|
-
# class Married
|
180
|
-
# def saturday_night
|
181
|
-
# "At home with the kids"
|
182
|
-
# end
|
183
|
-
# end
|
184
|
-
#
|
185
|
-
# class Single
|
186
|
-
# def saturday_night
|
187
|
-
# "Party Hard!"
|
188
|
-
# end
|
189
|
-
# end
|
190
|
-
# end
|
191
|
-
#
|
192
|
-
# class Person < ActiveRecord::Base
|
193
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => true }
|
194
|
-
# end
|
195
|
-
#
|
196
|
-
# p = Person.new
|
197
|
-
# p.relationship_status = RelationshipStatus::MARRIED
|
198
|
-
# p.relationship_status_object.saturday_night # => "At home with the kids"
|
199
|
-
#
|
200
|
-
# p.relationship_status = RelationshipStatus::SINGLE
|
201
|
-
# p.relationship_status_object.saturday_night # => "Party Hard!"
|
202
|
-
#
|
203
|
-
# You can also change the suffix '_object', using the :suffix option:
|
204
|
-
#
|
205
|
-
# class Person < ActiveRecord::Base
|
206
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => { :suffix => "_mode" } }
|
207
|
-
# end
|
208
|
-
#
|
209
|
-
# p.relationship_status_mode.saturday_night
|
210
|
-
#
|
211
|
-
# - If you pass the :create_scopes option as 'true', it will create a scope method for each enumeration option (this option defaults to false):
|
212
|
-
#
|
213
|
-
# class Person < ActiveRecord::Base
|
214
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_scopes => true
|
215
|
-
# end
|
216
|
-
#
|
217
|
-
# Person.married.to_sql # => SELECT "people".* FROM "people" WHERE "people"."relationship_status" = 1
|
218
|
-
#
|
219
|
-
# NOTE: The :create_scopes option can only be used for Rails.version >= 3.0.0.
|
220
|
-
#
|
221
|
-
# - If your class can manage validations and responds to :validates_inclusion_of, it will create this
|
222
|
-
# validation:
|
223
|
-
#
|
224
|
-
# class Person < ActiveRecord::Base
|
225
|
-
# has_enumeration_for :relationship_status, :with => RelationshipStatus
|
226
|
-
# end
|
227
|
-
#
|
228
|
-
# p = Person.new :relationship_status => 6 # => there is no '6' value in the enumeration
|
229
|
-
# p.valid? # => false
|
230
|
-
# p.errors[:relationship_status] # => "is not included in the list"
|
231
|
-
#
|
232
|
-
# - Also, if your class responds to :validates_presence_of, you can pass an :required option and this validation
|
233
|
-
# will be added to your attribute:
|
234
|
-
#
|
235
|
-
# class Person < ActiveRecord::Base
|
236
|
-
# has_enumeration_for :relationship_status, :required => true # => defaults to false
|
237
|
-
# end
|
238
|
-
#
|
239
|
-
# Remember that in Rails 3 you can add validations to any kind of class and not only to those derived from
|
240
|
-
# ActiveRecord::Base.
|
241
|
-
#
|
242
|
-
# = Using with Rails/ActiveRecord
|
243
|
-
#
|
244
|
-
# * Create an initializer with the following code:
|
245
|
-
#
|
246
|
-
# ActiveRecord::Base.extend EnumerateIt
|
247
|
-
#
|
248
|
-
# * Add the 'enumerate_it' gem as a dependency in your environment.rb (Rails 2.3.x) or Gemfile (if you're using Bundler)
|
249
|
-
#
|
250
|
-
# = Why did you reinvent the wheel?
|
251
|
-
#
|
252
|
-
# There are other similar solutions to the problem out there, but I could not find one that
|
253
|
-
# worked both with strings and integers as the enumerations' codes. I had both situations in
|
254
|
-
# my legacy database.
|
255
|
-
#
|
256
|
-
# = Why defining enumerations outside the class that used it?
|
257
|
-
#
|
258
|
-
# - I think it's cleaner.
|
259
|
-
# - You can add behaviour to the enumeration class.
|
260
|
-
# - You can reuse the enumeration inside other classes.
|
261
|
-
#
|
262
|
-
|
263
|
-
require "active_support/core_ext/class/attribute"
|
264
|
-
require "enumerate_it/base"
|
265
|
-
require "enumerate_it/class_methods"
|
3
|
+
require 'active_support/core_ext/class/attribute'
|
4
|
+
require 'enumerate_it/base'
|
5
|
+
require 'enumerate_it/class_methods'
|
266
6
|
|
267
7
|
module EnumerateIt
|
268
8
|
def self.extended(receiver)
|
269
|
-
receiver.class_attribute :enumerations, :
|
9
|
+
receiver.class_attribute :enumerations, instance_writer: false, instance_reader: false
|
270
10
|
receiver.enumerations = {}
|
271
11
|
|
272
12
|
receiver.extend ClassMethods
|
273
13
|
end
|
274
14
|
end
|
275
|
-
|
276
|
-
|
data/lib/enumerate_it/base.rb
CHANGED
@@ -19,7 +19,7 @@ module EnumerateIt
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.list
|
22
|
-
|
22
|
+
sorted_map.map { |_k, v| v.first }
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.enumeration
|
@@ -85,6 +85,8 @@ module EnumerateIt
|
|
85
85
|
private
|
86
86
|
|
87
87
|
def self.sorted_map
|
88
|
+
return enumeration if sort_mode == :none
|
89
|
+
|
88
90
|
enumeration.sort_by { |k, v| sort_lambda.call(k, v) }
|
89
91
|
end
|
90
92
|
|
@@ -93,7 +95,6 @@ module EnumerateIt
|
|
93
95
|
:value => lambda { |k, v| v[0] },
|
94
96
|
:name => lambda { |k, v| k },
|
95
97
|
:translation => lambda { |k, v| translate(v[1]) },
|
96
|
-
:none => lambda { |k, v| nil }
|
97
98
|
}[sort_mode || :translation]
|
98
99
|
end
|
99
100
|
|
data/lib/enumerate_it/version.rb
CHANGED
@@ -16,9 +16,39 @@ describe EnumerateIt::Base do
|
|
16
16
|
TestEnumerationWithDash::PT_BR.should == 'pt-BR'
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
describe ".list" do
|
20
|
+
it "creates a method that returns the allowed values in the enumeration's class" do
|
21
|
+
TestEnumeration.list.should == ['1', '2', '3']
|
22
|
+
end
|
23
|
+
|
24
|
+
context "specifying a default sort mode" do
|
25
|
+
subject { create_enumeration_class_with_sort_mode(sort_mode).list }
|
26
|
+
|
27
|
+
context "by value" do
|
28
|
+
let(:sort_mode) { :value }
|
29
|
+
|
30
|
+
it { should == %w(0 1 2 3) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "by name" do
|
34
|
+
let(:sort_mode) { :name }
|
35
|
+
|
36
|
+
it { should == %w(2 1 3 0) }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "by translation" do
|
40
|
+
let(:sort_mode) { :translation }
|
41
|
+
|
42
|
+
it { should == %w(3 2 0 1) }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "by nothing" do
|
46
|
+
let(:sort_mode) { :none }
|
47
|
+
|
48
|
+
it { should == %w(1 2 3 0) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
22
52
|
|
23
53
|
it "creates a method that returns the enumeration specification" do
|
24
54
|
TestEnumeration.enumeration.should == {
|
@@ -207,7 +237,7 @@ describe EnumerateIt::Base do
|
|
207
237
|
end
|
208
238
|
end
|
209
239
|
|
210
|
-
ActiveRecordStub.stub
|
240
|
+
ActiveRecordStub.stub(:validates_inclusion_of).and_return(true)
|
211
241
|
ActiveRecordStub.extend EnumerateIt
|
212
242
|
end
|
213
243
|
|
@@ -220,7 +250,7 @@ describe EnumerateIt::Base do
|
|
220
250
|
|
221
251
|
context "using the :required option" do
|
222
252
|
before :each do
|
223
|
-
ActiveRecordStub.stub
|
253
|
+
ActiveRecordStub.stub(:validates_presence_of).and_return(true)
|
224
254
|
end
|
225
255
|
|
226
256
|
it "creates a validation for presence" do
|