enumerize 2.0.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +75 -0
  3. data/CHANGELOG.md +117 -3
  4. data/Gemfile +3 -3
  5. data/Gemfile.global +5 -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 +210 -92
  12. data/Rakefile +9 -3
  13. data/enumerize.gemspec +1 -1
  14. data/lib/enumerize/activemodel.rb +47 -0
  15. data/lib/enumerize/activerecord.rb +92 -6
  16. data/lib/enumerize/attribute.rb +19 -11
  17. data/lib/enumerize/attribute_map.rb +2 -0
  18. data/lib/enumerize/base.rb +22 -18
  19. data/lib/enumerize/hooks/formtastic.rb +4 -1
  20. data/lib/enumerize/hooks/sequel_dataset.rb +2 -0
  21. data/lib/enumerize/hooks/simple_form.rb +4 -1
  22. data/lib/enumerize/hooks/uniqueness.rb +5 -1
  23. data/lib/enumerize/integrations/rails_admin.rb +3 -1
  24. data/lib/enumerize/integrations/rspec/matcher.rb +7 -2
  25. data/lib/enumerize/integrations/rspec.rb +3 -0
  26. data/lib/enumerize/module.rb +2 -0
  27. data/lib/enumerize/module_attributes.rb +2 -0
  28. data/lib/enumerize/mongoid.rb +23 -0
  29. data/lib/enumerize/predicatable.rb +3 -1
  30. data/lib/enumerize/predicates.rb +16 -0
  31. data/lib/enumerize/scope/activerecord.rb +16 -0
  32. data/lib/enumerize/scope/mongoid.rb +15 -0
  33. data/lib/enumerize/scope/sequel.rb +16 -0
  34. data/lib/enumerize/sequel.rb +9 -4
  35. data/lib/enumerize/set.rb +2 -0
  36. data/lib/enumerize/utils.rb +12 -0
  37. data/lib/enumerize/value.rb +14 -15
  38. data/lib/enumerize/version.rb +3 -1
  39. data/lib/enumerize.rb +9 -0
  40. data/lib/sequel/plugins/enumerize.rb +18 -0
  41. data/spec/enumerize/integrations/rspec/matcher_spec.rb +13 -10
  42. data/spec/spec_helper.rb +2 -0
  43. data/test/activemodel_test.rb +114 -0
  44. data/test/activerecord_test.rb +327 -78
  45. data/test/attribute_map_test.rb +9 -7
  46. data/test/attribute_test.rb +37 -34
  47. data/test/base_test.rb +117 -65
  48. data/test/formtastic_test.rb +25 -0
  49. data/test/module_attributes_test.rb +10 -8
  50. data/test/mongo_mapper_test.rb +20 -11
  51. data/test/mongoid_test.rb +52 -23
  52. data/test/multiple_test.rb +27 -19
  53. data/test/predicates_test.rb +51 -29
  54. data/test/rails_admin_test.rb +8 -6
  55. data/test/sequel_test.rb +228 -177
  56. data/test/set_test.rb +29 -27
  57. data/test/simple_form_test.rb +25 -0
  58. data/test/support/mock_controller.rb +6 -0
  59. data/test/support/shared_enums.rb +43 -0
  60. data/test/support/view_test_helper.rb +14 -1
  61. data/test/test_helper.rb +10 -0
  62. data/test/value_test.rb +59 -31
  63. metadata +16 -7
  64. data/.travis.yml +0 -18
  65. 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 [![Ruby](https://github.com/brainspec/enumerize/actions/workflows/ruby.yml/badge.svg)](https://github.com/brainspec/enumerize/actions/workflows/ruby.yml)
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.7+
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 identifiers 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,55 @@ 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"]
164
+ enumerize :color, in: %w[green blue], i18n_scope: proc { |value| "color" }
113
165
  end
114
166
 
115
167
  # localization file
116
168
  en:
117
- sex:
118
- male: "Male"
119
- female: "Female"
120
- various:
121
- colors:
122
- black: "Black"
123
- colors:
124
- white: "White"
169
+ status:
170
+ student: "Student"
171
+ employed: "Employed"
172
+ retired: "Retiree"
173
+ user:
174
+ roles:
175
+ user: "User"
176
+ roles:
177
+ admin: "Admin"
125
178
  ```
126
179
 
127
180
  Note that if you want to use I18n feature with plain Ruby object don't forget to extend it with `ActiveModel::Naming`:
@@ -133,88 +186,120 @@ class User
133
186
  end
134
187
  ```
135
188
 
136
- get attribute value:
189
+ ### I18n Helper Methods
190
+
191
+ #### \*\_text / .text
192
+
193
+ Attribute's I18n text value:
137
194
 
138
195
  ```ruby
139
- @user.sex_text # or @user.sex.text
196
+ @user.status_text # or @user.status.text
140
197
  ```
141
198
 
142
- get all values for enumerized attribute:
199
+ #### values
200
+
201
+ List of possible values for an enumerized attribute:
143
202
 
144
203
  ```ruby
145
- User.sex.values # or User.enumerized_attributes[:sex].values
204
+ User.status.values # or User.enumerized_attributes[:status].values
205
+ # => ['student', 'employed', 'retired']
146
206
  ```
147
207
 
148
- use it with forms (it supports `:only` and `:except` options):
208
+ #### I18n text values
209
+
210
+ List of possible I18n text values for an enumerized attribute:
211
+
212
+ ```ruby
213
+ User.status.values.collect(&:text)
214
+ # => ['Student', 'Employed', 'Retiree']
215
+ ```
216
+
217
+ #### Form example
218
+
219
+ Use it with forms (it supports `:only` and `:except` options):
149
220
 
150
221
  ```erb
151
222
  <%= form_for @user do |f| %>
152
- <%= f.select :sex, User.sex.options %>
223
+ <%= f.select :status, User.status.options %>
153
224
  <% end %>
154
225
  ```
155
226
 
156
- Boolean methods:
227
+ ---
228
+
229
+ ## Boolean Helper Methods
230
+
231
+ ### Basic
157
232
 
158
233
  ```ruby
159
- user.sex = :male
160
- user.sex.male? #=> true
161
- user.sex.female? #=> false
234
+ user.status = :student
235
+ user.status.student? #=> true
236
+ user.status.retired? #=> false
162
237
  ```
163
238
 
164
- Predicate methods:
239
+ ### Predicate Methods
165
240
 
166
241
  ```ruby
167
242
  class User
168
243
  extend Enumerize
169
244
 
170
- enumerize :sex, in: %w(male female), predicates: true
245
+ enumerize :status, in: %w(student employed retired), predicates: true
171
246
  end
172
247
 
173
248
  user = User.new
174
249
 
175
- user.male? # => false
176
- user.female? # => false
250
+ user.student? # => false
251
+ user.employed? # => false
177
252
 
178
- user.sex = 'male'
253
+ user.status = :student
179
254
 
180
- user.male? # => true
181
- user.female? # => false
255
+ user.student? # => true
256
+ user.employed? # => false
182
257
  ```
258
+
183
259
  :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
260
 
185
- Using prefix:
261
+ #### Predicate Prefixes
186
262
 
187
263
  ```ruby
188
264
  class User
189
265
  extend Enumerize
190
266
 
191
- enumerize :sex, in: %w(male female), predicates: { prefix: true }
267
+ enumerize :status, in: %w(student employed retired), predicates: { prefix: true }
192
268
  end
193
269
 
194
270
  user = User.new
195
- user.sex = 'female'
196
- user.sex_female? # => true
271
+ user.status = 'student'
272
+ user.status_student? # => true
197
273
  ```
274
+
198
275
  Use `:only` and `:except` options to specify what values create predicate methods for.
199
276
 
277
+ ---
278
+
279
+ ## Optimzations and Tips
280
+
281
+ ### Extendable Module
282
+
200
283
  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
284
 
202
285
  ```ruby
203
- module PersonEnumerations
286
+ module RoleEnumerations
204
287
  extend Enumerize
205
288
 
206
- enumerize :sex, in: %w[male female]
289
+ enumerize :roles, in: %w[user admin]
207
290
  end
208
291
 
209
- class Person
210
- include PersonEnumerations
292
+ class Buyer
293
+ include RoleEnumerations
211
294
  end
212
295
 
213
- class User
214
- include PersonEnumerations
296
+ class Seller
297
+ include RoleEnumerations
215
298
  end
216
299
  ```
217
300
 
301
+ ### Customizing Enumerize Value
302
+
218
303
  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
304
 
220
305
  ```ruby
@@ -233,27 +318,49 @@ User.role.find_value(:user).value #=> 1
233
318
  User.role.find_value(:admin).value #=> 2
234
319
  ```
235
320
 
236
- ActiveRecord scopes:
321
+ ### ActiveRecord scopes:
322
+
323
+ #### Basic
237
324
 
238
325
  ```ruby
239
326
  class User < ActiveRecord::Base
240
327
  extend Enumerize
241
- enumerize :sex, :in => [:male, :female], scope: true
242
- enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
328
+ enumerize :role, :in => [:user, :admin], scope: true
329
+ enumerize :status, :in => { student: 1, employed: 2, retired: 3 }, scope: :having_status
243
330
  end
244
331
 
245
- User.with_sex(:female)
246
- # SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')
332
+ User.with_role(:admin)
333
+ # SELECT "users".* FROM "users" WHERE "users"."role" IN ('admin')
334
+
335
+ User.without_role(:admin)
336
+ # SELECT "users".* FROM "users" WHERE "users"."role" NOT IN ('admin')
337
+
338
+ User.having_status(:employed).with_role(:user, :admin)
339
+ # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."role" IN ('user', 'admin')
340
+ ```
341
+
342
+ #### Shallow Scopes
247
343
 
248
- User.without_sex(:male)
249
- # SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')
344
+ Adds named scopes to the class directly.
250
345
 
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')
346
+ ```ruby
347
+ class User < ActiveRecord::Base
348
+ extend Enumerize
349
+ enumerize :status, :in => [:student, :employed, :retired], scope: :shallow
350
+ enumerize :role, :in => { user: 1, admin: 2 }, scope: :shallow
351
+ end
352
+
353
+ User.student
354
+ # SELECT "users".* FROM "users" WHERE "users"."status" = 'student'
355
+
356
+ User.admin
357
+ # SELECT "users".* FROM "users" WHERE "users"."role" = 2
253
358
  ```
254
359
 
255
360
  :warning: It is not possible to define a scope when using the `:multiple` option. :warning:
256
361
 
362
+ ### Array-like Attributes
363
+
257
364
  Array-like attributes with plain ruby objects:
258
365
 
259
366
  ```ruby
@@ -288,22 +395,26 @@ get an array of all text values:
288
395
  Also, the reader method can be overridden, referencing the enumerized attribute value using `super`:
289
396
 
290
397
  ```ruby
291
- def sex
398
+ def status
292
399
  if current_user.admin?
293
- "Super#{super}"
400
+ "Super #{super}"
294
401
  else
295
402
  super
296
403
  end
297
404
  end
298
405
  ```
299
406
 
407
+ ---
408
+
409
+ ## Forms
410
+
300
411
  ### SimpleForm
301
412
 
302
413
  If you are using SimpleForm gem you don't need to specify input type (`:select` by default) and collection:
303
414
 
304
415
  ```erb
305
416
  <%= simple_form_for @user do |f| %>
306
- <%= f.input :sex %>
417
+ <%= f.input :status %>
307
418
  <% end %>
308
419
  ```
309
420
 
@@ -311,17 +422,19 @@ and if you want it as radio buttons:
311
422
 
312
423
  ```erb
313
424
  <%= simple_form_for @user do |f| %>
314
- <%= f.input :sex, :as => :radio_buttons %>
425
+ <%= f.input :status, :as => :radio_buttons %>
315
426
  <% end %>
316
427
  ```
317
428
 
429
+ 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.
430
+
318
431
  ### Formtastic
319
432
 
320
433
  If you are using Formtastic gem you also don't need to specify input type (`:select` by default) and collection:
321
434
 
322
435
  ```erb
323
436
  <%= semantic_form_for @user do |f| %>
324
- <%= f.input :sex %>
437
+ <%= f.input :status %>
325
438
  <% end %>
326
439
  ```
327
440
 
@@ -329,10 +442,14 @@ and if you want it as radio buttons:
329
442
 
330
443
  ```erb
331
444
  <%= semantic_form_for @user do |f| %>
332
- <%= f.input :sex, :as => :radio %>
445
+ <%= f.input :status, :as => :radio %>
333
446
  <% end %>
334
447
  ```
335
448
 
449
+ ---
450
+
451
+ ## Testing
452
+
336
453
  ### RSpec
337
454
 
338
455
  Also you can use builtin RSpec matcher:
@@ -341,14 +458,14 @@ Also you can use builtin RSpec matcher:
341
458
  class User
342
459
  extend Enumerize
343
460
 
344
- enumerize :sex, in: [:male, :female]
461
+ enumerize :status, in: [:student, :employed, :retired]
345
462
  end
346
463
 
347
464
  describe User do
348
- it { should enumerize(:sex) }
465
+ it { should enumerize(:status) }
349
466
 
350
467
  # or with RSpec 3 expect syntax
351
- it { is_expected.to enumerize(:sex) }
468
+ it { is_expected.to enumerize(:status) }
352
469
  end
353
470
  ```
354
471
 
@@ -362,11 +479,11 @@ Use `in` to test usage of the `:in` option.
362
479
  class User
363
480
  extend Enumerize
364
481
 
365
- enumerize :sex, in: [:male, :female]
482
+ enumerize :status, in: [:student, :employed, :retired]
366
483
  end
367
484
 
368
485
  describe User do
369
- it { should enumerize(:sex).in(:male, :female) }
486
+ it { should enumerize(:status).in(:student, :employed, :retired) }
370
487
  end
371
488
  ```
372
489
 
@@ -377,11 +494,11 @@ qualifier.
377
494
  class User
378
495
  extend Enumerize
379
496
 
380
- enumerize :sex, in: { male: 0, female: 1 }
497
+ enumerize :role, in: { user: 0, admin: 1 }
381
498
  end
382
499
 
383
500
  describe User do
384
- it { should enumerize(:sex).in(male: 0, female: 1) }
501
+ it { should enumerize(:role).in(user: 0, admin: 1) }
385
502
  end
386
503
  ```
387
504
 
@@ -393,11 +510,11 @@ Use `with_default` to test usage of the `:default` option.
393
510
  class User
394
511
  extend Enumerize
395
512
 
396
- enumerize :sex, in: [:male, :female], default: :female
513
+ enumerize :role, in: [:user, :admin], default: :user
397
514
  end
398
515
 
399
516
  describe User do
400
- it { should enumerize(:sex).in(:male, :female).with_default(:female) }
517
+ it { should enumerize(:user).in(:user, :admin).with_default(:user) }
401
518
  end
402
519
  ```
403
520
 
@@ -409,11 +526,11 @@ Use `with_i18n_scope` to test usage of the `:i18n_scope` option.
409
526
  class User
410
527
  extend Enumerize
411
528
 
412
- enumerize :sex, in: [:male, :female], i18n_scope: 'sex'
529
+ enumerize :status, in: [:student, :employed, :retired], i18n_scope: 'status'
413
530
  end
414
531
 
415
532
  describe User do
416
- it { should enumerize(:sex).in(:male, :female).with_i18n_scope('sex') }
533
+ it { should enumerize(:status).in(:student, :employed, :retired).with_i18n_scope('status') }
417
534
  end
418
535
  ```
419
536
 
@@ -425,11 +542,11 @@ Use `with_predicates` to test usage of the `:predicates` option.
425
542
  class User
426
543
  extend Enumerize
427
544
 
428
- enumerize :sex, in: [:male, :female], predicates: true
545
+ enumerize :status, in: [:student, :employed, :retired], predicates: true
429
546
  end
430
547
 
431
548
  describe User do
432
- it { should enumerize(:sex).in(:male, :female).with_predicates(true) }
549
+ it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(true) }
433
550
  end
434
551
  ```
435
552
 
@@ -439,11 +556,11 @@ You can text prefixed predicates with the `with_predicates` qualifiers.
439
556
  class User
440
557
  extend Enumerize
441
558
 
442
- enumerize :sex, in: [:male, :female], predicates: { prefix: true }
559
+ enumerize :status, in: [:student, :employed, :retired], predicates: { prefix: true }
443
560
  end
444
561
 
445
562
  describe User do
446
- it { should enumerize(:sex).in(:male, :female).with_predicates(prefix: true) }
563
+ it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(prefix: true) }
447
564
  end
448
565
  ```
449
566
 
@@ -455,25 +572,25 @@ Use `with_scope` to test usage of the `:scope` option.
455
572
  class User
456
573
  extend Enumerize
457
574
 
458
- enumerize :sex, in: [:male, :female], scope: true
575
+ enumerize :status, in: [:student, :employed, :retired], scope: true
459
576
  end
460
577
 
461
578
  describe User do
462
- it { should enumerize(:sex).in(:male, :female).with_scope(true) }
579
+ it { should enumerize(:status).in(:student, :employed, :retired).with_scope(true) }
463
580
  end
464
581
  ```
465
582
 
466
- You can text custom scope with the `with_scope` qualifiers.
583
+ You can test a custom scope with the `with_scope` qualifiers.
467
584
 
468
585
  ```ruby
469
586
  class User
470
587
  extend Enumerize
471
588
 
472
- enumerize :sex, in: [:male, :female], scope: :having_sex
589
+ enumerize :status, in: [:student, :employed], scope: :employable
473
590
  end
474
591
 
475
592
  describe User do
476
- it { should enumerize(:sex).in(:male, :female).with_scope(scope: :having_sex) }
593
+ it { should enumerize(:status).in(:student, :employed, :retired).with_scope(scope: :employable) }
477
594
  end
478
595
  ```
479
596
 
@@ -485,11 +602,11 @@ Use `with_multiple` to test usage of the `:multiple` option.
485
602
  class User
486
603
  extend Enumerize
487
604
 
488
- enumerize :sex, in: [:male, :female], multiple: true
605
+ enumerize :status, in: [:student, :employed, :retired], multiple: true
489
606
  end
490
607
 
491
608
  describe User do
492
- it { should enumerize(:sex).in(:male, :female).with_multiple(true) }
609
+ it { should enumerize(:status).in(:student, :employed, :retired).with_multiple(true) }
493
610
  end
494
611
  ```
495
612
 
@@ -512,8 +629,9 @@ end
512
629
 
513
630
  Enumerize integrates with the following automatically:
514
631
 
515
- * [RailsAdmin](https://github.com/sferik/rails_admin/)
632
+ - [RailsAdmin](https://github.com/sferik/rails_admin/)
516
633
 
634
+ ---
517
635
 
518
636
  ## Contributing
519
637
 
data/Rakefile CHANGED
@@ -1,8 +1,9 @@
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'
5
- require 'rspec/core/rake_task'
6
7
 
7
8
  Rake::TestTask.new do |t|
8
9
  t.libs << 'test'
@@ -10,6 +11,11 @@ Rake::TestTask.new do |t|
10
11
  t.verbose = true
11
12
  end
12
13
 
13
- RSpec::Core::RakeTask.new
14
+ if ENV['TEST_FRAMEWORK'] == 'rspec'
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new
14
17
 
15
- task :default => [:test, :spec]
18
+ task :default => [:spec]
19
+ else
20
+ task :default => [:test]
21
+ end
data/enumerize.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = Enumerize::VERSION
18
18
 
19
- gem.required_ruby_version = '>= 1.9.3'
19
+ gem.required_ruby_version = '>= 2.7'
20
20
 
21
21
  gem.add_dependency('activesupport', '>= 3.2')
22
22
  end
@@ -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