enumerize 2.0.1 → 2.5.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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +73 -0
  3. data/CHANGELOG.md +80 -3
  4. data/Gemfile +3 -3
  5. data/Gemfile.global +2 -9
  6. data/Gemfile.mongo_mapper +2 -2
  7. data/Gemfile.rails60 +6 -0
  8. data/Gemfile.rails61 +6 -0
  9. data/Gemfile.rails70 +9 -0
  10. data/Gemfile.railsmaster +5 -0
  11. data/README.md +209 -92
  12. data/Rakefile +2 -0
  13. data/lib/enumerize/activemodel.rb +47 -0
  14. data/lib/enumerize/activerecord.rb +79 -0
  15. data/lib/enumerize/attribute.rb +19 -11
  16. data/lib/enumerize/attribute_map.rb +2 -0
  17. data/lib/enumerize/base.rb +6 -6
  18. data/lib/enumerize/hooks/formtastic.rb +4 -1
  19. data/lib/enumerize/hooks/sequel_dataset.rb +2 -0
  20. data/lib/enumerize/hooks/simple_form.rb +4 -1
  21. data/lib/enumerize/hooks/uniqueness.rb +5 -1
  22. data/lib/enumerize/integrations/rails_admin.rb +3 -1
  23. data/lib/enumerize/integrations/rspec/matcher.rb +7 -2
  24. data/lib/enumerize/integrations/rspec.rb +2 -0
  25. data/lib/enumerize/module.rb +2 -0
  26. data/lib/enumerize/module_attributes.rb +2 -0
  27. data/lib/enumerize/mongoid.rb +16 -0
  28. data/lib/enumerize/predicatable.rb +3 -1
  29. data/lib/enumerize/predicates.rb +2 -0
  30. data/lib/enumerize/scope/activerecord.rb +16 -0
  31. data/lib/enumerize/scope/mongoid.rb +15 -0
  32. data/lib/enumerize/scope/sequel.rb +16 -0
  33. data/lib/enumerize/sequel.rb +9 -4
  34. data/lib/enumerize/set.rb +2 -0
  35. data/lib/enumerize/utils.rb +12 -0
  36. data/lib/enumerize/value.rb +14 -15
  37. data/lib/enumerize/version.rb +3 -1
  38. data/lib/enumerize.rb +9 -0
  39. data/lib/sequel/plugins/enumerize.rb +18 -0
  40. data/spec/enumerize/integrations/rspec/matcher_spec.rb +13 -10
  41. data/spec/spec_helper.rb +2 -0
  42. data/test/activemodel_test.rb +114 -0
  43. data/test/activerecord_test.rb +277 -79
  44. data/test/attribute_map_test.rb +9 -7
  45. data/test/attribute_test.rb +37 -30
  46. data/test/base_test.rb +66 -64
  47. data/test/formtastic_test.rb +25 -0
  48. data/test/module_attributes_test.rb +10 -8
  49. data/test/mongo_mapper_test.rb +19 -10
  50. data/test/mongoid_test.rb +51 -22
  51. data/test/multiple_test.rb +26 -18
  52. data/test/predicates_test.rb +30 -28
  53. data/test/rails_admin_test.rb +8 -6
  54. data/test/sequel_test.rb +111 -58
  55. data/test/set_test.rb +28 -26
  56. data/test/simple_form_test.rb +25 -0
  57. data/test/support/mock_controller.rb +6 -0
  58. data/test/support/shared_enums.rb +43 -0
  59. data/test/support/view_test_helper.rb +14 -1
  60. data/test/test_helper.rb +2 -0
  61. data/test/value_test.rb +51 -30
  62. metadata +14 -27
  63. data/.travis.yml +0 -18
  64. data/Gemfile.rails42 +0 -6
data/README.md CHANGED
@@ -1,7 +1,35 @@
1
- # Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.svg?branch=master)](http://travis-ci.org/brainspec/enumerize) [![Gemnasium](https://gemnasium.com/brainspec/enumerize.svg)](https://gemnasium.com/brainspec/enumerize)
1
+ # Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.svg?branch=master)](http://travis-ci.org/brainspec/enumerize)
2
2
 
3
3
  Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Supported Versions](#supported-versions)
9
+ - [Usage](#usage)
10
+ - [Database support](#database-support)
11
+ - [ActiveRecord](#activerecord)
12
+ - [Mongoid](#mongoid)
13
+ - [MongoMapper](#mongomapper)
14
+ - [I18n Support](#i18n-support)
15
+ - [I18n Helper Methods](#i18n-helper-methods)
16
+ - [Boolean Helper Methods](#boolean-helper-methods)
17
+ - [Basic](#basic)
18
+ - [Predicate Methods](#predicate-methods)
19
+ - [Optimzations and Tips](#optimzations-and-tips)
20
+ - [Extendable Module](#extendable-module)
21
+ - [Customizing Enumerize Value](#customizing-enumerize-value)
22
+ - [ActiveRecord scopes](#activerecord-scopes)
23
+ - [Array-like Attributes](#array-like-attributes)
24
+ - [Forms](#forms)
25
+ - [SimpleForm](#simpleform)
26
+ - [Formtastic](#formtastic)
27
+ - [Testing](#testing)
28
+ - [RSpec](#rspec)
29
+ - [Minitest with Shoulda](#minitest-with-shoulda)
30
+ - [Other Integrations](#other-integrations)
31
+ - [Contributing](#contributing)
32
+
5
33
  ## Installation
6
34
 
7
35
  Add this line to your application's Gemfile:
@@ -16,6 +44,11 @@ Or install it yourself as:
16
44
 
17
45
  $ gem install enumerize
18
46
 
47
+ ## Supported Versions
48
+
49
+ - Ruby 2.6+
50
+ - Rails 5.2+
51
+
19
52
  ## Usage
20
53
 
21
54
  Basic:
@@ -24,20 +57,23 @@ Basic:
24
57
  class User
25
58
  extend Enumerize
26
59
 
27
- enumerize :sex, in: [:male, :female]
60
+ enumerize :role, in: [:user, :admin]
28
61
  end
29
62
  ```
30
63
 
31
- Note that enumerized values are just identificators so if you want to use multi-word, etc. values you should use `I18n` feature.
64
+ Note that enumerized values are just identificators so if you want to use multi-word, etc. values then you should use `I18n` feature.
65
+
66
+ ---
32
67
 
68
+ ## Database support
33
69
 
34
- ActiveRecord:
70
+ ### ActiveRecord
35
71
 
36
72
  ```ruby
37
73
  class CreateUsers < ActiveRecord::Migration
38
74
  def change
39
75
  create_table :users do |t|
40
- t.string :sex
76
+ t.string :status
41
77
  t.string :role
42
78
 
43
79
  t.timestamps
@@ -48,13 +84,25 @@ end
48
84
  class User < ActiveRecord::Base
49
85
  extend Enumerize
50
86
 
51
- enumerize :sex, in: [:male, :female], default: lambda { |user| SexIdentifier.sex_for_name(user.name).to_sym }
87
+ enumerize :status, in: [:student, :employed, :retired], default: lambda { |user| StatusIdentifier.status_for_age(user.age).to_sym }
52
88
 
53
89
  enumerize :role, in: [:user, :admin], default: :user
54
90
  end
55
91
  ```
56
92
 
57
- Mongoid:
93
+ :warning: By default, `enumerize` adds `inclusion` validation to the model. You can skip validations by passing `skip_validations` option. :warning:
94
+
95
+ ```ruby
96
+ class User < ActiveRecord::Base
97
+ extend Enumerize
98
+
99
+ enumerize :status, in: [:student, :employed, :retired], skip_validations: lambda { |user| user.new_record? }
100
+
101
+ enumerize :role, in: [:user, :admin], skip_validations: true
102
+ end
103
+ ```
104
+
105
+ ### Mongoid
58
106
 
59
107
  ```ruby
60
108
  class User
@@ -66,7 +114,7 @@ class User
66
114
  end
67
115
  ```
68
116
 
69
- MongoMapper:
117
+ ### MongoMapper
70
118
 
71
119
  ```ruby
72
120
  class User
@@ -78,50 +126,54 @@ class User
78
126
  end
79
127
  ```
80
128
 
81
- I18n:
129
+ ---
130
+
131
+ ## I18n Support
82
132
 
83
133
  ```ruby
84
134
  en:
85
135
  enumerize:
86
136
  user:
87
- sex:
88
- male: "Male"
89
- female: "Female"
137
+ status:
138
+ student: "Student"
139
+ employed: "Employed"
140
+ retired: "Retiree"
90
141
  ```
91
142
 
92
- or if you use `sex` attribute across several models you can use `defaults` scope:
143
+ or if you use `status` attribute across several models you can use `defaults` scope:
93
144
 
94
145
  ```ruby
95
146
  en:
96
147
  enumerize:
97
148
  defaults:
98
- sex:
99
- male: "Male"
100
- female: "Female"
149
+ status:
150
+ student: "Student"
151
+ employed: "Employed"
152
+ retired: "Retiree"
101
153
  ```
102
154
 
103
155
  You can also pass `i18n_scope` option to specify scope (or array of scopes) storing the translations.
104
156
 
105
-
106
157
  ```ruby
107
158
  class Person
108
159
  extend Enumerize
109
160
  extend ActiveModel::Naming
110
161
 
111
- enumerize :sex, in: %w[male female], i18n_scope: "sex"
112
- enumerize :color, in: %w[black white], i18n_scope: ["various.colors", "colors"]
162
+ enumerize :status, in: %w[student employed retired], i18n_scope: "status"
163
+ enumerize :roles, in: %w[user admin], i18n_scope: ["user.roles", "roles"]
113
164
  end
114
165
 
115
166
  # localization file
116
167
  en:
117
- sex:
118
- male: "Male"
119
- female: "Female"
120
- various:
121
- colors:
122
- black: "Black"
123
- colors:
124
- white: "White"
168
+ status:
169
+ student: "Student"
170
+ employed: "Employed"
171
+ retired: "Retiree"
172
+ user:
173
+ roles:
174
+ user: "User"
175
+ roles:
176
+ admin: "Admin"
125
177
  ```
126
178
 
127
179
  Note that if you want to use I18n feature with plain Ruby object don't forget to extend it with `ActiveModel::Naming`:
@@ -133,88 +185,120 @@ class User
133
185
  end
134
186
  ```
135
187
 
136
- get attribute value:
188
+ ### I18n Helper Methods
189
+
190
+ #### \*\_text / .text
191
+
192
+ Attribute's I18n text value:
137
193
 
138
194
  ```ruby
139
- @user.sex_text # or @user.sex.text
195
+ @user.status_text # or @user.status.text
140
196
  ```
141
197
 
142
- get all values for enumerized attribute:
198
+ #### values
199
+
200
+ List of possible values for an enumerized attribute:
143
201
 
144
202
  ```ruby
145
- User.sex.values # or User.enumerized_attributes[:sex].values
203
+ User.status.values # or User.enumerized_attributes[:status].values
204
+ # => ['student', 'employed', 'retired']
146
205
  ```
147
206
 
148
- use it with forms (it supports `:only` and `:except` options):
207
+ #### I18n text values
208
+
209
+ List of possible I18n text values for an enumerized attribute:
210
+
211
+ ```ruby
212
+ User.status.values.collect(&:text)
213
+ # => ['Student', 'Employed', 'Retiree']
214
+ ```
215
+
216
+ #### Form example
217
+
218
+ Use it with forms (it supports `:only` and `:except` options):
149
219
 
150
220
  ```erb
151
221
  <%= form_for @user do |f| %>
152
- <%= f.select :sex, User.sex.options %>
222
+ <%= f.select :status, User.status.options %>
153
223
  <% end %>
154
224
  ```
155
225
 
156
- Boolean methods:
226
+ ---
227
+
228
+ ## Boolean Helper Methods
229
+
230
+ ### Basic
157
231
 
158
232
  ```ruby
159
- user.sex = :male
160
- user.sex.male? #=> true
161
- user.sex.female? #=> false
233
+ user.status = :student
234
+ user.status.student? #=> true
235
+ user.status.retired? #=> false
162
236
  ```
163
237
 
164
- Predicate methods:
238
+ ### Predicate Methods
165
239
 
166
240
  ```ruby
167
241
  class User
168
242
  extend Enumerize
169
243
 
170
- enumerize :sex, in: %w(male female), predicates: true
244
+ enumerize :status, in: %w(student employed retired), predicates: true
171
245
  end
172
246
 
173
247
  user = User.new
174
248
 
175
- user.male? # => false
176
- user.female? # => false
249
+ user.student? # => false
250
+ user.employed? # => false
177
251
 
178
- user.sex = 'male'
252
+ user.status = :student
179
253
 
180
- user.male? # => true
181
- user.female? # => false
254
+ user.student? # => true
255
+ user.employed? # => false
182
256
  ```
257
+
183
258
  :warning: If `enumerize` is used with Mongoid, it's not recommended to use `"writer"` as a field value since `writer?` is defined by Mongoid. [See more](https://github.com/brainspec/enumerize/issues/235). :warning:
184
259
 
185
- Using prefix:
260
+ #### Predicate Prefixes
186
261
 
187
262
  ```ruby
188
263
  class User
189
264
  extend Enumerize
190
265
 
191
- enumerize :sex, in: %w(male female), predicates: { prefix: true }
266
+ enumerize :status, in: %w(student employed retired), predicates: { prefix: true }
192
267
  end
193
268
 
194
269
  user = User.new
195
- user.sex = 'female'
196
- user.sex_female? # => true
270
+ user.status = 'student'
271
+ user.status_student? # => true
197
272
  ```
273
+
198
274
  Use `:only` and `:except` options to specify what values create predicate methods for.
199
275
 
276
+ ---
277
+
278
+ ## Optimzations and Tips
279
+
280
+ ### Extendable Module
281
+
200
282
  To make some attributes shared across different classes it's possible to define them in a separate module and then include it into classes:
201
283
 
202
284
  ```ruby
203
- module PersonEnumerations
285
+ module RoleEnumerations
204
286
  extend Enumerize
205
287
 
206
- enumerize :sex, in: %w[male female]
288
+ enumerize :roles, in: %w[user admin]
207
289
  end
208
290
 
209
- class Person
210
- include PersonEnumerations
291
+ class Buyer
292
+ include RoleEnumerations
211
293
  end
212
294
 
213
- class User
214
- include PersonEnumerations
295
+ class Seller
296
+ include RoleEnumerations
215
297
  end
216
298
  ```
217
299
 
300
+ ### Customizing Enumerize Value
301
+
218
302
  It's also possible to store enumerized attribute value using custom values (e.g. integers). You can pass a hash as `:in` option to achieve this:
219
303
 
220
304
  ```ruby
@@ -233,27 +317,49 @@ User.role.find_value(:user).value #=> 1
233
317
  User.role.find_value(:admin).value #=> 2
234
318
  ```
235
319
 
236
- ActiveRecord scopes:
320
+ ### ActiveRecord scopes:
321
+
322
+ #### Basic
237
323
 
238
324
  ```ruby
239
325
  class User < ActiveRecord::Base
240
326
  extend Enumerize
241
- enumerize :sex, :in => [:male, :female], scope: true
242
- enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
327
+ enumerize :role, :in => [:user, :admin], scope: true
328
+ enumerize :status, :in => { student: 1, employed: 2, retired: 3 }, scope: :having_status
243
329
  end
244
330
 
245
- User.with_sex(:female)
246
- # SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')
331
+ User.with_role(:admin)
332
+ # SELECT "users".* FROM "users" WHERE "users"."role" IN ('admin')
333
+
334
+ User.without_role(:admin)
335
+ # SELECT "users".* FROM "users" WHERE "users"."role" NOT IN ('admin')
336
+
337
+ User.having_status(:employed).with_role(:user, :admin)
338
+ # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."role" IN ('user', 'admin')
339
+ ```
340
+
341
+ #### Shallow Scopes
247
342
 
248
- User.without_sex(:male)
249
- # SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')
343
+ Adds named scopes to the class directly.
250
344
 
251
- User.having_status(:blocked).with_sex(:male, :female)
252
- # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')
345
+ ```ruby
346
+ class User < ActiveRecord::Base
347
+ extend Enumerize
348
+ enumerize :status, :in => [:student, :employed, :retired], scope: :shallow
349
+ enumerize :role, :in => { user: 1, admin: 2 }, scope: :shallow
350
+ end
351
+
352
+ User.student
353
+ # SELECT "users".* FROM "users" WHERE "users"."status" = 'student'
354
+
355
+ User.admin
356
+ # SELECT "users".* FROM "users" WHERE "users"."role" = 2
253
357
  ```
254
358
 
255
359
  :warning: It is not possible to define a scope when using the `:multiple` option. :warning:
256
360
 
361
+ ### Array-like Attributes
362
+
257
363
  Array-like attributes with plain ruby objects:
258
364
 
259
365
  ```ruby
@@ -288,22 +394,26 @@ get an array of all text values:
288
394
  Also, the reader method can be overridden, referencing the enumerized attribute value using `super`:
289
395
 
290
396
  ```ruby
291
- def sex
397
+ def status
292
398
  if current_user.admin?
293
- "Super#{super}"
399
+ "Super #{super}"
294
400
  else
295
401
  super
296
402
  end
297
403
  end
298
404
  ```
299
405
 
406
+ ---
407
+
408
+ ## Forms
409
+
300
410
  ### SimpleForm
301
411
 
302
412
  If you are using SimpleForm gem you don't need to specify input type (`:select` by default) and collection:
303
413
 
304
414
  ```erb
305
415
  <%= simple_form_for @user do |f| %>
306
- <%= f.input :sex %>
416
+ <%= f.input :status %>
307
417
  <% end %>
308
418
  ```
309
419
 
@@ -311,17 +421,19 @@ and if you want it as radio buttons:
311
421
 
312
422
  ```erb
313
423
  <%= simple_form_for @user do |f| %>
314
- <%= f.input :sex, :as => :radio_buttons %>
424
+ <%= f.input :status, :as => :radio_buttons %>
315
425
  <% end %>
316
426
  ```
317
427
 
428
+ Please note that Enumerize overwrites the I18n keys of SimpleForm collections. The enumerized keys are used instead of the SimpleForm ones for inputs concerning enumerized attributes. If you don't want this just pass `:collection` option to the `input` call.
429
+
318
430
  ### Formtastic
319
431
 
320
432
  If you are using Formtastic gem you also don't need to specify input type (`:select` by default) and collection:
321
433
 
322
434
  ```erb
323
435
  <%= semantic_form_for @user do |f| %>
324
- <%= f.input :sex %>
436
+ <%= f.input :status %>
325
437
  <% end %>
326
438
  ```
327
439
 
@@ -329,10 +441,14 @@ and if you want it as radio buttons:
329
441
 
330
442
  ```erb
331
443
  <%= semantic_form_for @user do |f| %>
332
- <%= f.input :sex, :as => :radio %>
444
+ <%= f.input :status, :as => :radio %>
333
445
  <% end %>
334
446
  ```
335
447
 
448
+ ---
449
+
450
+ ## Testing
451
+
336
452
  ### RSpec
337
453
 
338
454
  Also you can use builtin RSpec matcher:
@@ -341,14 +457,14 @@ Also you can use builtin RSpec matcher:
341
457
  class User
342
458
  extend Enumerize
343
459
 
344
- enumerize :sex, in: [:male, :female]
460
+ enumerize :status, in: [:student, :employed, :retired]
345
461
  end
346
462
 
347
463
  describe User do
348
- it { should enumerize(:sex) }
464
+ it { should enumerize(:status) }
349
465
 
350
466
  # or with RSpec 3 expect syntax
351
- it { is_expected.to enumerize(:sex) }
467
+ it { is_expected.to enumerize(:status) }
352
468
  end
353
469
  ```
354
470
 
@@ -362,11 +478,11 @@ Use `in` to test usage of the `:in` option.
362
478
  class User
363
479
  extend Enumerize
364
480
 
365
- enumerize :sex, in: [:male, :female]
481
+ enumerize :status, in: [:student, :employed, :retired]
366
482
  end
367
483
 
368
484
  describe User do
369
- it { should enumerize(:sex).in(:male, :female) }
485
+ it { should enumerize(:status).in(:student, :employed, :retired) }
370
486
  end
371
487
  ```
372
488
 
@@ -377,11 +493,11 @@ qualifier.
377
493
  class User
378
494
  extend Enumerize
379
495
 
380
- enumerize :sex, in: { male: 0, female: 1 }
496
+ enumerize :role, in: { user: 0, admin: 1 }
381
497
  end
382
498
 
383
499
  describe User do
384
- it { should enumerize(:sex).in(male: 0, female: 1) }
500
+ it { should enumerize(:role).in(user: 0, admin: 1) }
385
501
  end
386
502
  ```
387
503
 
@@ -393,11 +509,11 @@ Use `with_default` to test usage of the `:default` option.
393
509
  class User
394
510
  extend Enumerize
395
511
 
396
- enumerize :sex, in: [:male, :female], default: :female
512
+ enumerize :role, in: [:user, :admin], default: :user
397
513
  end
398
514
 
399
515
  describe User do
400
- it { should enumerize(:sex).in(:male, :female).with_default(:female) }
516
+ it { should enumerize(:user).in(:user, :admin).with_default(:user) }
401
517
  end
402
518
  ```
403
519
 
@@ -409,11 +525,11 @@ Use `with_i18n_scope` to test usage of the `:i18n_scope` option.
409
525
  class User
410
526
  extend Enumerize
411
527
 
412
- enumerize :sex, in: [:male, :female], i18n_scope: 'sex'
528
+ enumerize :status, in: [:student, :employed, :retired], i18n_scope: 'status'
413
529
  end
414
530
 
415
531
  describe User do
416
- it { should enumerize(:sex).in(:male, :female).with_i18n_scope('sex') }
532
+ it { should enumerize(:status).in(:student, :employed, :retired).with_i18n_scope('status') }
417
533
  end
418
534
  ```
419
535
 
@@ -425,11 +541,11 @@ Use `with_predicates` to test usage of the `:predicates` option.
425
541
  class User
426
542
  extend Enumerize
427
543
 
428
- enumerize :sex, in: [:male, :female], predicates: true
544
+ enumerize :status, in: [:student, :employed, :retired], predicates: true
429
545
  end
430
546
 
431
547
  describe User do
432
- it { should enumerize(:sex).in(:male, :female).with_predicates(true) }
548
+ it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(true) }
433
549
  end
434
550
  ```
435
551
 
@@ -439,11 +555,11 @@ You can text prefixed predicates with the `with_predicates` qualifiers.
439
555
  class User
440
556
  extend Enumerize
441
557
 
442
- enumerize :sex, in: [:male, :female], predicates: { prefix: true }
558
+ enumerize :status, in: [:student, :employed, :retired], predicates: { prefix: true }
443
559
  end
444
560
 
445
561
  describe User do
446
- it { should enumerize(:sex).in(:male, :female).with_predicates(prefix: true) }
562
+ it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(prefix: true) }
447
563
  end
448
564
  ```
449
565
 
@@ -455,25 +571,25 @@ Use `with_scope` to test usage of the `:scope` option.
455
571
  class User
456
572
  extend Enumerize
457
573
 
458
- enumerize :sex, in: [:male, :female], scope: true
574
+ enumerize :status, in: [:student, :employed, :retired], scope: true
459
575
  end
460
576
 
461
577
  describe User do
462
- it { should enumerize(:sex).in(:male, :female).with_scope(true) }
578
+ it { should enumerize(:status).in(:student, :employed, :retired).with_scope(true) }
463
579
  end
464
580
  ```
465
581
 
466
- You can text custom scope with the `with_scope` qualifiers.
582
+ You can test a custom scope with the `with_scope` qualifiers.
467
583
 
468
584
  ```ruby
469
585
  class User
470
586
  extend Enumerize
471
587
 
472
- enumerize :sex, in: [:male, :female], scope: :having_sex
588
+ enumerize :status, in: [:student, :employed], scope: :employable
473
589
  end
474
590
 
475
591
  describe User do
476
- it { should enumerize(:sex).in(:male, :female).with_scope(scope: :having_sex) }
592
+ it { should enumerize(:status).in(:student, :employed, :retired).with_scope(scope: :employable) }
477
593
  end
478
594
  ```
479
595
 
@@ -485,11 +601,11 @@ Use `with_multiple` to test usage of the `:multiple` option.
485
601
  class User
486
602
  extend Enumerize
487
603
 
488
- enumerize :sex, in: [:male, :female], multiple: true
604
+ enumerize :status, in: [:student, :employed, :retired], multiple: true
489
605
  end
490
606
 
491
607
  describe User do
492
- it { should enumerize(:sex).in(:male, :female).with_multiple(true) }
608
+ it { should enumerize(:status).in(:student, :employed, :retired).with_multiple(true) }
493
609
  end
494
610
  ```
495
611
 
@@ -512,8 +628,9 @@ end
512
628
 
513
629
  Enumerize integrates with the following automatically:
514
630
 
515
- * [RailsAdmin](https://github.com/sferik/rails_admin/)
631
+ - [RailsAdmin](https://github.com/sferik/rails_admin/)
516
632
 
633
+ ---
517
634
 
518
635
  ## Contributing
519
636
 
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
2
4
  require "bundler/gem_tasks"
3
5
 
4
6
  require 'rake/testtask'
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Enumerize
4
+ module ActiveModelAttributesSupport
5
+ def enumerize(name, options={})
6
+ super
7
+
8
+ _enumerize_module.dependent_eval do
9
+ if self.included_modules.include? ::ActiveModel::Attributes
10
+ include InstanceMethods
11
+
12
+ attribute name, Enumerize::ActiveModelAttributesSupport::Type.new(enumerized_attributes[name])
13
+ end
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ # https://github.com/brainspec/enumerize/issues/74
19
+ def write_attribute(attr_name, value, *options)
20
+ if self.class.enumerized_attributes[attr_name]
21
+ _enumerized_values_for_validation[attr_name.to_s] = value
22
+ end
23
+
24
+ super
25
+ end
26
+ end
27
+
28
+ class Type < ActiveModel::Type::Value
29
+ def type
30
+ :enumerize
31
+ end
32
+
33
+ def initialize(attr)
34
+ @attr = attr
35
+ end
36
+
37
+ def serialize(value)
38
+ v = @attr.find_value(value)
39
+ v && v.value
40
+ end
41
+
42
+ def deserialize(value)
43
+ @attr.find_value(value)
44
+ end
45
+ end
46
+ end
47
+ end