enumerate_it 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZGI4ZDc1NjJkOTdiODA5Zjg4Y2ExMmMzNGY2OWUzODkxZWVlNmY4Ng==
5
+ data.tar.gz: !binary |-
6
+ M2YxZjM3NjhkYzg5NTVhM2ViODQ1YjU4NzNkNjYxMzYzN2U2YjZkNA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZmM2MDI1OWRmNzlmNjgwMWI1YzZlMzdhNjg3NzFlOWFmODgxNTQzYzMzOGQz
10
+ NWQ0YWUzYTQyYzc1MDk2OGE4NDYyMWU5OTA0OTliYzUzNTY0MjFjNmFlMGZk
11
+ ZjMzODE0Y2VjZjYyM2NhMTM5M2ZiNjdlOTVmODM1MTAwNzUzYTM=
12
+ data.tar.gz: !binary |-
13
+ OWNkZmY1ZTc5YTU4OTdkZmM2YzViMTgxYTI5NWJjNzlkZDQ2ZDMwYmEzZDYx
14
+ ZTk4YzRmNjg3MTI3MjE0ZjgwNGZjMjVlZTgxNjA0OGQ0NmNjZjM2OWE4OThh
15
+ Mzk3ZmFhMTc3Zjk0M2EzYjBkMDVlMGUzYTU5ZDQwNGFlMzE0YzA=
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- enumerate_it (1.2.0)
4
+ enumerate_it (1.2.1)
5
5
  activesupport (>= 3.0.0)
6
6
 
7
7
  GEM
data/README.markdown ADDED
@@ -0,0 +1,508 @@
1
+ # EnumerateIt - Ruby Enumerations
2
+
3
+ [![Build Status](https://travis-ci.org/cassiomarques/enumerate_it.png?branch=master)](https://travis-ci.org/cassiomarques/enumerate_it)
4
+ [![Gem Version](https://badge.fury.io/rb/enumerate_it.png)](http://badge.fury.io/rb/enumerate_it)
5
+
6
+ Author: Cássio Marques - cassiommc at gmail
7
+
8
+ ## Description
9
+
10
+ Ok, I know there are a lot of different solutions to this problem. But none of
11
+ them solved my problem, so here's EnumerateIt. I needed to build a Rails
12
+ application around a legacy database and this database was filled with those
13
+ small, unchangeable tables used to create foreign key constraints everywhere.
14
+
15
+ ### For example:
16
+
17
+ Table "public.relationshipstatus"
18
+
19
+ Column | Type | Modifiers
20
+ -------------+---------------+-----------
21
+ code | character(1) | not null
22
+ description | character(11) |
23
+
24
+ Indexes:
25
+ "relationshipstatus_pkey" PRIMARY KEY, btree (code)
26
+
27
+ SELECT * FROM relationshipstatus;
28
+
29
+ code | description
30
+ -------+--------------
31
+ 1 | Single
32
+ 2 | Married
33
+ 3 | Widow
34
+ 4 | Divorced
35
+
36
+ And then I had things like a people table with a 'relationship_status' column
37
+ with a foreign key pointing to the relationshipstatus table.
38
+
39
+ While this is a good thing from the database normalization perspective,
40
+ managing this values in my tests was very hard. Doing database joins just to
41
+ get the description of some value was absurd. And, more than this, referencing
42
+ them in my code using magic numbers was terrible and meaningless: What does it
43
+ mean when we say that someone or something is '2'?
44
+
45
+ Enter EnumerateIt.
46
+
47
+ ## About versions compatibility
48
+
49
+ Versions 1.x.x are NOT backwards compatible with 0.x.x versions. The biggest
50
+ difference is that on 1.0.0 you need to `extend` the EnumerateIt module inside
51
+ classes that are going to have enumerated attributes, while in past versions
52
+ you would use `include`.
53
+
54
+ ## Creating enumerations
55
+
56
+ Enumerations are created as models, but you can put then anywhere in your
57
+ application. In Rails applications, you can put them inside models/.
58
+
59
+ ``` ruby
60
+ class RelationshipStatus < EnumerateIt::Base
61
+ associate_values(
62
+ :single => [1, 'Single'],
63
+ :married => [2, 'Married'],
64
+ :widow => [3, 'Widow'],
65
+ :divorced => [4, 'Divorced']
66
+ )
67
+ end
68
+ ```
69
+
70
+ This will create some nice stuff:
71
+
72
+ * Each enumeration's value will turn into a constant:
73
+
74
+ ``` ruby
75
+ RelationshipStatus::SINGLE
76
+ #=> 1
77
+
78
+ RelationshipStatus::MARRIED
79
+ #=> 2
80
+ ```
81
+
82
+ * You can retrieve a list with all the enumeration codes:
83
+
84
+ ``` ruby
85
+ RelationshipStatus.list
86
+ #=> [1, 2, 3, 4]
87
+ ```
88
+
89
+ * You can get an array of options, ready to use with the 'select',
90
+ 'select_tag', etc family of Rails helpers.
91
+
92
+ ``` ruby
93
+ RelationshipStatus.to_a
94
+ #=> [["Divorced", 4], ["Married", 2], ["Single", 1], ["Widow", 3]]
95
+ ```
96
+
97
+ * You can retrieve a list with values for a group of enumeration constants.
98
+
99
+ ``` ruby
100
+ RelationshipStatus.values_for %w(MARRIED SINGLE)
101
+ #=> [2, 1]
102
+ ```
103
+
104
+ * You can retrieve the value for a specific enumeration constant:
105
+
106
+ ``` ruby
107
+ RelationshipStatus.value_for("MARRIED")
108
+ #=> 2
109
+ ```
110
+
111
+ * You can retrieve the symbol used to declare a specific enumeration value:
112
+
113
+ ``` ruby
114
+ RelationshipStatus.key_for(RelationshipStatus::MARRIED)
115
+ #=> :married
116
+ ```
117
+
118
+ * You can iterate over the list of the enumeration's values:
119
+
120
+ ``` ruby
121
+ RelationshipStatus.each_value { |value| ... }
122
+ ```
123
+
124
+ * You can iterate over the list of the enumeration's translations:
125
+
126
+ ``` ruby
127
+ RelationshipStatus.each_translation { |translation| ... }
128
+ ```
129
+
130
+ * You can ask for the enumeration's length:
131
+
132
+ ``` ruby
133
+ RelationshipStatus.length
134
+ #=> 4
135
+ ```
136
+
137
+ * You can manipulate the hash used to create the enumeration:
138
+
139
+ ``` ruby
140
+ RelationshipStatus.enumeration
141
+ #=> returns the exact hash used to define the enumeration
142
+ ```
143
+
144
+
145
+ You can also create enumerations in the following ways:
146
+
147
+ * Passing an array of symbols, so that the respective value for each symbol
148
+ will be the stringified version of the symbol itself:
149
+
150
+ ``` ruby
151
+ class RelationshipStatus < EnumerateIt::Base
152
+ associate_values :married, :single
153
+ end
154
+
155
+ RelationshipStatus::MARRIED
156
+ #=> "married"
157
+ ```
158
+
159
+ * Passing hashes where the value for each key/pair does not include a
160
+ translation. In this case, the I18n feature will be used (more on this
161
+ below):
162
+
163
+ ``` ruby
164
+ class RelationshipStatus < EnumerateIt::Base
165
+ associate_values :married => 1, :single => 2
166
+ end
167
+ ```
168
+
169
+
170
+ ### Defining a default sort mode
171
+
172
+ When calling methods like `to_a` and `to_json`, the returned values will be
173
+ sorted using the translation for each one of the enumeration values. If you
174
+ want to overwrite the default sort mode, you can use the `sort_by` class
175
+ method.
176
+
177
+ ``` ruby
178
+ class RelationshipStatus < EnumerateIt::Base
179
+ associate_values :married => 1, :single => 2
180
+
181
+ sort_by :value
182
+ end
183
+ ```
184
+
185
+ The `sort_by` methods accept one of the following values:
186
+
187
+ * `:translation`: The default behavior, will sort the returned values based
188
+ on translations.
189
+ * `:value`: Will sort the returned values based on values.
190
+ * `:name`: Will sort the returned values based on the name of each
191
+ enumeration option.
192
+ * `:none`: Will return values in order that was passed to associate_values
193
+ call.
194
+
195
+
196
+ ## Using enumerations
197
+
198
+ The cool part is that you can use these enumerations with any class, be it an
199
+ ActiveRecord instance or not.
200
+
201
+ ``` ruby
202
+ class Person
203
+ extend EnumerateIt
204
+ attr_accessor :relationship_status
205
+
206
+ has_enumeration_for :relationship_status, :with => RelationshipStatus
207
+ end
208
+ ```
209
+
210
+ The :with option is not required. If you ommit it, EnumerateIt will try to
211
+ load an enumeration class based on the camelized attribute name.
212
+
213
+ This will create:
214
+
215
+ * A humanized description for the values of the enumerated attribute:
216
+
217
+ ``` ruby
218
+ p = Person.new
219
+ p.relationship_status = RelationshipStatus::DIVORCED
220
+ p.relationship_status_humanize
221
+ #=> 'Divorced'
222
+ ```
223
+
224
+ * If you don't supply a humanized string to represent an option, EnumerateIt
225
+ will use a 'humanized' version of the hash's key to humanize the
226
+ attribute's value:
227
+
228
+ ``` ruby
229
+ class RelationshipStatus < EnumerateIt::Base
230
+ associate_values(
231
+ :married => 1,
232
+ :single => 2
233
+ )
234
+ end
235
+
236
+ p = Person.new
237
+ p.relationship_status = RelationshipStatus::MARRIED
238
+ p.relationship_status_humanize
239
+ #=> 'Married'
240
+ ```
241
+
242
+ * The associated enumerations can be retrieved with the 'enumerations' class
243
+ method.
244
+
245
+ ``` ruby
246
+ Person.enumerations[:relationship_status]
247
+ #=> RelationshipStatus
248
+ ```
249
+
250
+ * If you pass the :create_helpers option as 'true', it will create a helper
251
+ method for each enumeration option (this option defaults to false):
252
+
253
+ ``` ruby
254
+ class Person < ActiveRecord::Base
255
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
256
+ end
257
+
258
+ p = Person.new
259
+ p.relationship_status = RelationshipStatus::MARRIED
260
+
261
+ p.married?
262
+ #=> true
263
+
264
+ p.divorced?
265
+ #=> false
266
+ ```
267
+
268
+ * It's also possible to "namespace" the created helper methods, passing a
269
+ hash to the :create_helpers option. This can be useful when two or more of
270
+ the enumerations used share the same constants.
271
+
272
+ ``` ruby
273
+ class Person < ActiveRecord::Base
274
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :prefix => true }
275
+ end
276
+
277
+ p = Person.new
278
+ p.relationship_status = RelationshipStatus::MARRIED
279
+
280
+ p.relationship_status_married?
281
+ #=> true
282
+
283
+ p.relationship_status_divoced?
284
+ #=> false
285
+ ```
286
+
287
+ * You can define polymorphic behavior for the enum values, so you can define
288
+ a class for each of them:
289
+
290
+ ``` ruby
291
+ class RelationshipStatus < EnumerateIt::Base
292
+ associate_values :married, :single
293
+
294
+ class Married
295
+ def saturday_night
296
+ "At home with the kids"
297
+ end
298
+ end
299
+
300
+ class Single
301
+ def saturday_night
302
+ "Party Hard!"
303
+ end
304
+ end
305
+ end
306
+
307
+ class Person < ActiveRecord::Base
308
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => true }
309
+ end
310
+
311
+ p = Person.new
312
+ p.relationship_status = RelationshipStatus::MARRIED
313
+ p.relationship_status_object.saturday_night
314
+ #=> "At home with the kids"
315
+
316
+ p.relationship_status = RelationshipStatus::SINGLE
317
+ p.relationship_status_object.saturday_night
318
+ #=> "Party Hard!"
319
+ ```
320
+
321
+ You can also change the suffix '_object', using the :suffix option:
322
+
323
+ ``` ruby
324
+ class Person < ActiveRecord::Base
325
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => { :suffix => "_mode" } }
326
+ end
327
+
328
+ p.relationship_status_mode.saturday_night
329
+ ```
330
+
331
+ * The :create_helpers also creates some mutator helper methods, that can be
332
+ used to change the attribute's value.
333
+
334
+ ``` ruby
335
+ class Person < ActiveRecord::Base
336
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
337
+ end
338
+
339
+ p = Person.new
340
+ p.married!
341
+
342
+ p.married?
343
+ #=> true
344
+
345
+ p.divorced?
346
+ #=> false
347
+ ```
348
+
349
+ * If you pass the :create_scopes option as 'true', it will create a scope
350
+ method for each enumeration option (this option defaults to false):
351
+
352
+ ``` ruby
353
+ class Person < ActiveRecord::Base
354
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_scopes => true
355
+ end
356
+
357
+ Person.married.to_sql
358
+ #=> SELECT "people".* FROM "people" WHERE "people"."relationship_status" = 1
359
+ ```
360
+
361
+
362
+ NOTE: The :create_scopes option can only be used for Rails.version >= 3.0.0.
363
+
364
+ * If your class can manage validations and responds to
365
+ :validates_inclusion_of, it will create this validation:
366
+
367
+ ``` ruby
368
+ class Person < ActiveRecord::Base
369
+ has_enumeration_for :relationship_status, :with => RelationshipStatus
370
+ end
371
+
372
+ p = Person.new(:relationship_status => 6) # there is no '6' value in the enumeration
373
+ p.valid?
374
+ #=> false
375
+ p.errors[:relationship_status]
376
+ #=> "is not included in the list"
377
+ ```
378
+
379
+ * If your class can manage validations and responds to
380
+ :validates_presence_of, you can pass the :required options as true and
381
+ this validation will be created for you (this option defaults to false):
382
+
383
+ ``` ruby
384
+ class Person < ActiveRecord::Base
385
+ has_enumeration_for :relationship_status, :required => true
386
+ end
387
+
388
+ p = Person.new :relationship_status => nil
389
+ p.valid?
390
+ #=> false
391
+ p.errors[:relationship_status]
392
+ #=> "can't be blank"
393
+ ```
394
+
395
+
396
+ Remember that in Rails 3 you can add validations to any kind of class and not
397
+ only to those derived from ActiveRecord::Base.
398
+
399
+ ## I18n
400
+
401
+ I18n lookup is provided on both '_humanized' and 'Enumeration#to_a' methods,
402
+ given the hash key is a Symbol. The I18n strings are located on
403
+ enumerations.'enumeration_name'.'key' :
404
+
405
+ ``` yaml
406
+ # your locale file
407
+ pt:
408
+ enumerations:
409
+ relationship_status:
410
+ married: Casado
411
+ ```
412
+
413
+ ``` ruby
414
+ class RelationshipStatus < EnumerateIt::Base
415
+ associate_values(
416
+ :married => 1,
417
+ :single => 2,
418
+ :divorced => [3, "He's divorced"]
419
+ )
420
+ end
421
+
422
+ p = Person.new
423
+ p.relationship_status = RelationshipStatus::MARRIED
424
+ p.relationship_status_humanize
425
+ #=> 'Casado'
426
+
427
+ p.relationship_status = RelationshipStatus::SINGLE
428
+ p.relationship_status_humanize # nonexistent key
429
+ #=> 'Single'
430
+
431
+ p.relationship_status = RelationshipStatus::DIVORCED
432
+ p.relationship_status_humanize # uses the provided string
433
+ #=> 'He's divorced'
434
+ ```
435
+
436
+ You can also translate specific values:
437
+
438
+ ``` ruby
439
+ RelationshipStatus.t(1)
440
+ #=> 'Casado'
441
+ ```
442
+
443
+ ## Installation
444
+
445
+ ``` bash
446
+ gem install enumerate_it
447
+ ```
448
+
449
+ ## Using with Rails
450
+
451
+ * Add the gem to your Gemfile:
452
+
453
+ ``` ruby
454
+ gem "enumerate_it"
455
+ ```
456
+
457
+ * Run the install generator:
458
+
459
+ ``` bash
460
+ rails generate enumerate_it:install
461
+ ```
462
+
463
+
464
+ An interesting approach to use it in Rails apps is to create an
465
+ app/enumerations folder and add it to your autoload path in
466
+ config/application.rb:
467
+
468
+ ``` ruby
469
+ module YourApp
470
+ class Application < Rails::Application
471
+ config.autoload_paths << "#{Rails.root}/app/enumerations"
472
+ end
473
+ end
474
+ ```
475
+
476
+ There is also a Rails Generator that you can use to generate enumerations and
477
+ their locale files. Take a look at how to use it running
478
+
479
+ ``` bash
480
+ rails generate enumerate_it:enum --help
481
+ ```
482
+
483
+ ## Why did you reinvent the wheel?
484
+
485
+ There are other similar solutions to the problem out there, but I could not
486
+ find one that worked both with strings and integers as the enumerations'
487
+ codes. I had both situations in my legacy database.
488
+
489
+ ## Why defining enumerations outside the class that use it?
490
+
491
+ * I think it's cleaner.
492
+ * You can add behaviour to the enumeration class.
493
+ * You can reuse the enumeration inside other classes.
494
+
495
+ ## Note on Patches/Pull Requests
496
+
497
+ * Fork the project.
498
+ * Make your feature addition or bug fix.
499
+ * Add tests for it. This is important so I don't break it in a future
500
+ version unintentionally.
501
+ * Commit, do not mess with rakefile, version, or history. (if you want to
502
+ have your own version, that is fine but bump version in a commit by itself
503
+ I can ignore when I pull)
504
+ * Send me a pull request. Bonus points for topic branches.
505
+
506
+ ## Copyright
507
+
508
+ Copyright (c) 2010 Cássio Marques. See LICENSE for details.
@@ -1,3 +1,3 @@
1
1
  module EnumerateIt
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumerate_it
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
5
- prerelease:
4
+ version: 1.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Cássio Marques
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-16 00:00:00.000000000 Z
11
+ date: 2014-03-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ! '>='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ! '>='
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ! '>='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ! '>='
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: activerecord
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: pry
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ! '>='
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ! '>='
92
81
  - !ruby/object:Gem::Version
@@ -94,7 +83,6 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: pry-nav
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ! '>='
100
88
  - !ruby/object:Gem::Version
@@ -102,15 +90,11 @@ dependencies:
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ! '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
- description: Have a legacy database and need some enumerations in your models to match
111
- those stupid '4 rows/2 columns' tables with foreign keys and stop doing joins just
112
- to fetch a simple description? Or maybe use some integers instead of strings as
113
- the code for each value of your enumerations? Here's EnumerateIt.
97
+ description: Enumerations for Ruby with some magic powers!
114
98
  email:
115
99
  - cassiommc@gmail.com
116
100
  executables: []
@@ -123,7 +107,7 @@ files:
123
107
  - Gemfile
124
108
  - Gemfile.lock
125
109
  - LICENSE
126
- - README.rdoc
110
+ - README.markdown
127
111
  - Rakefile
128
112
  - enumerate_it.gemspec
129
113
  - lib/enumerate_it.rb
@@ -146,33 +130,26 @@ files:
146
130
  - spec/support/test_classes.rb
147
131
  homepage: http://github.com/cassiomarques/enumerate_it
148
132
  licenses: []
133
+ metadata: {}
149
134
  post_install_message:
150
135
  rdoc_options: []
151
136
  require_paths:
152
137
  - lib
153
138
  required_ruby_version: !ruby/object:Gem::Requirement
154
- none: false
155
139
  requirements:
156
140
  - - ! '>='
157
141
  - !ruby/object:Gem::Version
158
142
  version: '0'
159
- segments:
160
- - 0
161
- hash: 1153526174871300187
162
143
  required_rubygems_version: !ruby/object:Gem::Requirement
163
- none: false
164
144
  requirements:
165
145
  - - ! '>='
166
146
  - !ruby/object:Gem::Version
167
147
  version: '0'
168
- segments:
169
- - 0
170
- hash: 1153526174871300187
171
148
  requirements: []
172
149
  rubyforge_project:
173
- rubygems_version: 1.8.24
150
+ rubygems_version: 2.1.4
174
151
  signing_key:
175
- specification_version: 3
152
+ specification_version: 4
176
153
  summary: Ruby Enumerations
177
154
  test_files:
178
155
  - spec/enumerate_it/base_spec.rb
data/README.rdoc DELETED
@@ -1,366 +0,0 @@
1
- = EnumerateIt - Ruby Enumerations
2
-
3
- {<img src="https://secure.travis-ci.org/cassiomarques/enumerate_it.png?branch=master" alt="Build Status" />}[http://travis-ci.org/cassiomarques/enumerate_it]
4
-
5
- Author: Cássio Marques - cassiommc at gmail
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
-
32
- And then I had things like a people table with a 'relationship_status' column with a foreign key
33
- pointing to the relationshipstatus table.
34
-
35
- While this is a good thing from the database normalization perspective, managing this values in
36
- my tests was very hard. Doing database joins just to get the description of some value was absurd.
37
- And, more than this, referencing them in my code using magic numbers was terrible and meaningless:
38
- What does it mean when we say that someone or something is '2'?
39
-
40
- Enter EnumerateIt.
41
-
42
- == About versions compatibility
43
-
44
- Versions 1.x.x are NOT backwards compatible with 0.x.x versions. The biggest difference is that on 1.0.0 you need to `extend` the EnumerateIt
45
- module inside classes that are going to have enumerated attributes, while in past versions you would use `include`.
46
-
47
- == Creating enumerations
48
-
49
- Enumerations are created as models, but you can put then anywhere in your application. In Rails
50
- applications, you can put them inside models/.
51
-
52
- class RelationshipStatus < EnumerateIt::Base
53
- associate_values(
54
- :single => [1, 'Single'],
55
- :married => [2, 'Married'],
56
- :widow => [3, 'Widow'],
57
- :divorced => [4, 'Divorced']
58
- )
59
- end
60
-
61
- This will create some nice stuff:
62
-
63
- * Each enumeration's value will turn into a constant:
64
-
65
- RelationshipStatus::SINGLE # returns 1
66
- RelationshipStatus::MARRIED # returns 2 and so on...
67
-
68
- * You can retrieve a list with all the enumeration codes:
69
-
70
- RelationshipStatus.list # [1,2,3,4]
71
-
72
- * You can get an array of options, ready to use with the 'select', 'select_tag', etc family of Rails helpers.
73
-
74
- RelationshipStatus.to_a # [["Divorced", 4],["Married", 2],["Single", 1],["Widow", 3]]
75
-
76
- * You can retrieve a list with values for a group of enumeration constants.
77
-
78
- RelationshipStatus.values_for %w(MARRIED SINGLE) # [2, 1]
79
-
80
- * You can retrieve the value for a specific enumeration constant:
81
-
82
- RelationshipStatus.value_for("MARRIED") # 2
83
-
84
- * You can retrieve the symbol used to declare a specific enumeration value:
85
-
86
- RelationshipStatus.key_for(RelationshipStatus::MARRIED) # :married
87
-
88
- * You can iterate over the list of the enumeration's values:
89
-
90
- RelationshipStatus.each_value { |value| # ... }
91
-
92
- * You can iterate over the list of the enumeration's translations:
93
-
94
- RelationshipStatus.each_translation { |translation| # ... }
95
-
96
- * You can ask for the enumeration's length:
97
-
98
- RelationshipStatus.length # 4
99
-
100
- * You can manipulate the hash used to create the enumeration:
101
-
102
- RelationshipStatus.enumeration # returns the exact hash used to define the enumeration
103
-
104
- You can also create enumerations in the following ways:
105
-
106
- * Passing an array of symbols, so that the respective value for each symbol will be the stringified version of the symbol itself:
107
-
108
- class RelationshipStatus < EnumerateIt::Base
109
- associate_values :married, :single
110
- end
111
-
112
- RelationshipStatus::MARRIED # returns "married" and so on
113
-
114
- * 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):
115
-
116
- class RelationshipStatus < EnumerateIt::Base
117
- associate_values :married => 1, :single => 2
118
- end
119
-
120
- === Defining a default sort mode
121
-
122
- When calling methods like `to_a` and `to_json`, the returned values will be sorted using the translation for each one of the enumeration values. If you want
123
- to overwrite the default sort mode, you can use the `sort_mode` class method.
124
-
125
- class RelationshipStatus < EnumerateIt::Base
126
- associate_values :married => 1, :single => 2
127
-
128
- sort_by :value
129
- end
130
-
131
- The `sort_by` methods accept one of the following values:
132
-
133
- * `:translation`: The default behavior, will sort the returned values based on translations.
134
- * `:value`: Will sort the returned values based on values.
135
- * `:name`: Will sort the returned values based on the name of each enumeration option.
136
- * `:none`: Will return values in order that was passed to associate_values call.
137
-
138
- == Using enumerations
139
-
140
- The cool part is that you can use these enumerations with any class, be it an ActiveRecord instance
141
- or not.
142
-
143
- class Person
144
- extend EnumerateIt
145
- attr_accessor :relationship_status
146
-
147
- has_enumeration_for :relationship_status, :with => RelationshipStatus
148
- end
149
-
150
- The :with option is not required. If you ommit it, EnumerateIt will try to load an enumeration class based on the camelized attribute name.
151
-
152
- This will create:
153
-
154
- * A humanized description for the values of the enumerated attribute:
155
-
156
- p = Person.new
157
- p.relationship_status = RelationshipStatus::DIVORCED
158
- p.relationship_status_humanize # => 'Divorced'
159
-
160
- * If you don't supply a humanized string to represent an option, EnumerateIt will use a 'humanized' version of the hash's key to humanize the attribute's value:
161
-
162
- class RelationshipStatus < EnumerateIt::Base
163
- associate_values(
164
- :married => 1,
165
- :single => 2
166
- )
167
- end
168
-
169
- p = Person.new
170
- p.relationship_status = RelationshipStatus::MARRIED
171
- p.relationship_status_humanize # => 'Married'
172
-
173
- * The associated enumerations can be retrieved with the 'enumerations' class method.
174
-
175
- Person.enumerations[:relationship_status] # => RelationshipStatus
176
-
177
- * If you pass the :create_helpers option as 'true', it will create a helper method for each enumeration option (this option defaults to false):
178
-
179
- class Person < ActiveRecord::Base
180
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
181
- end
182
-
183
- p = Person.new
184
- p.relationship_status = RelationshipStatus::MARRIED
185
- p.married? #=> true
186
- p.divorced? #=> false
187
-
188
- * It's also possible to "namespace" the created helper methods, passing a hash to the :create_helpers option.
189
- This can be useful when two or more of the enumerations used share the same constants.
190
-
191
- class Person < ActiveRecord::Base
192
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :prefix => true }
193
- end
194
-
195
- p = Person.new
196
- p.relationship_status = RelationshipStatus::MARRIED
197
- p.relationship_status_married? #=> true
198
- p.relationship_status_divoced? #=> false
199
-
200
- * You can define polymorphic behavior for the enum values, so you can define a class for each of
201
- them:
202
-
203
- class RelationshipStatus < EnumerateIt::Base
204
- associate_values :married, :single
205
-
206
- class Married
207
- def saturday_night
208
- "At home with the kids"
209
- end
210
- end
211
-
212
- class Single
213
- def saturday_night
214
- "Party Hard!"
215
- end
216
- end
217
- end
218
-
219
- class Person < ActiveRecord::Base
220
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => true }
221
- end
222
-
223
- p = Person.new
224
- p.relationship_status = RelationshipStatus::MARRIED
225
- p.relationship_status_object.saturday_night # => "At home with the kids"
226
-
227
- p.relationship_status = RelationshipStatus::SINGLE
228
- p.relationship_status_object.saturday_night # => "Party Hard!"
229
-
230
- You can also change the suffix '_object', using the :suffix option:
231
-
232
- class Person < ActiveRecord::Base
233
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => { :polymorphic => { :suffix => "_mode" } }
234
- end
235
-
236
- p.relationship_status_mode.saturday_night
237
-
238
- * The :create_helpers also creates some mutator helper methods, that can be used to change the attribute's value.
239
-
240
- class Person < ActiveRecord::Base
241
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
242
- end
243
-
244
- p = Person.new
245
- p.married!
246
- p.married? #=> true
247
- p.divorced? #=> false
248
-
249
- * If you pass the :create_scopes option as 'true', it will create a scope method for each enumeration option (this option defaults to false):
250
-
251
- class Person < ActiveRecord::Base
252
- has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_scopes => true
253
- end
254
-
255
- Person.married.to_sql # => SELECT "people".* FROM "people" WHERE "people"."relationship_status" = 1
256
-
257
- NOTE: The :create_scopes option can only be used for Rails.version >= 3.0.0.
258
-
259
- * If your class can manage validations and responds to :validates_inclusion_of, it will create this validation:
260
-
261
- class Person < ActiveRecord::Base
262
- has_enumeration_for :relationship_status, :with => RelationshipStatus
263
- end
264
-
265
- p = Person.new :relationship_status => 6 # => there is no '6' value in the enumeration
266
- p.valid? # => false
267
- p.errors[:relationship_status] # => "is not included in the list"
268
-
269
- * If your class can manage validations and responds to :validates_presence_of, you can pass the :required options as true and this validation will be created for you (this option defaults to false):
270
-
271
- class Person < ActiveRecord::Base
272
- has_enumeration_for :relationship_status, :required => true
273
- end
274
-
275
- p = Person.new :relationship_status => nil
276
- p.valid? # => false
277
- p.errors[:relationship_status] # => "can't be blank"
278
-
279
-
280
- Remember that in Rails 3 you can add validations to any kind of class and not only to those derived from
281
- ActiveRecord::Base.
282
-
283
- == I18n
284
-
285
- I18n lookup is provided on both '_humanized' and 'Enumeration#to_a' methods, given the hash key is a Symbol. The I18n strings are
286
- located on enumerations.'enumeration_name'.'key' :
287
-
288
- class RelationshipStatus < EnumerateIt::Base
289
- associate_values(
290
- :married => 1,
291
- :single => 2,
292
- :divorced => [3, 'He's divorced']
293
- )
294
- end
295
-
296
- # your locale file
297
- pt:
298
- enumerations:
299
- relationship_status:
300
- married: Casado
301
-
302
- p = Person.new
303
- p.relationship_status = RelationshipStatus::MARRIED
304
- p.relationship_status_humanize # => 'Casado'
305
-
306
- p.relationship_status = RelationshipStatus::SINGLE
307
- p.relationship_status_humanize # => 'Single' => nonexistent key
308
-
309
- p.relationship_status = RelationshipStatus::DIVORCED
310
- p.relationship_status_humanize # => 'He's divorced' => uses the provided string
311
-
312
- You can also translate specific values:
313
-
314
- RelationshipStatus.t(1) # => 'Casado'
315
-
316
- == Installation
317
-
318
- gem install enumerate_it
319
-
320
- == Using with Rails
321
-
322
- * Add the gem to your Gemfile:
323
-
324
- gem "enumerate_it"
325
-
326
- * Run the install generator:
327
-
328
- rails g enumerate_it:install
329
-
330
- An interesting approach to use it in Rails apps is to create an app/enumerations folder and add it to your autoload path in config/application.rb:
331
-
332
- module YourApp
333
- class Application < Rails::Application
334
- config.autoload_paths << "#{Rails.root}/app/enumerations"
335
- end
336
- end
337
-
338
- There is also a Rails Generator that you can use to generate enumerations and their locale files. Take a look at how to use it running
339
-
340
- rails generate enumerate_it:enum --help
341
-
342
- == Why did you reinvent the wheel?
343
-
344
- There are other similar solutions to the problem out there, but I could not find one that
345
- worked both with strings and integers as the enumerations' codes. I had both situations in
346
- my legacy database.
347
-
348
- == Why defining enumerations outside the class that use it?
349
-
350
- * I think it's cleaner.
351
- * You can add behaviour to the enumeration class.
352
- * You can reuse the enumeration inside other classes.
353
-
354
- == Note on Patches/Pull Requests
355
-
356
- * Fork the project.
357
- * Make your feature addition or bug fix.
358
- * Add tests for it. This is important so I don't break it in a
359
- future version unintentionally.
360
- * Commit, do not mess with rakefile, version, or history.
361
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
362
- * Send me a pull request. Bonus points for topic branches.
363
-
364
- == Copyright
365
-
366
- Copyright (c) 2010 Cássio Marques. See LICENSE for details.