enumerize 2.0.0 → 2.7.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 (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
@@ -1,11 +1,62 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'active_record'
3
5
  require 'logger'
4
6
 
7
+ db = (ENV['DB'] || 'sqlite3').to_sym
8
+
5
9
  silence_warnings do
6
10
  ActiveRecord::Migration.verbose = false
11
+ if ActiveRecord::Base.respond_to?(:use_yaml_unsafe_load)
12
+ ActiveRecord::Base.use_yaml_unsafe_load = true
13
+ end
7
14
  ActiveRecord::Base.logger = Logger.new(nil)
8
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
15
+ ActiveRecord::Base.configurations = {
16
+ 'sqlite3' => {
17
+ 'adapter' => 'sqlite3',
18
+ 'database' => ':memory:'
19
+ },
20
+ 'mysql2' => {
21
+ 'adapter' => 'mysql2',
22
+ 'host' => '127.0.0.1',
23
+ 'username' => 'root',
24
+ 'password' => ENV['MYSQL_ROOT_PASSWORD'],
25
+ 'database' => 'enumerize_test',
26
+ 'encoding' => 'utf8mb4',
27
+ 'charset' => 'utf8mb4'
28
+ },
29
+ 'postgresql' => {
30
+ 'adapter' => 'postgresql',
31
+ 'host' => 'localhost',
32
+ 'username' => ENV['POSTGRES_USER'],
33
+ 'password' => ENV['POSTGRES_PASSWORD']
34
+ },
35
+ 'postgresql_master' => {
36
+ 'adapter' => 'postgresql',
37
+ 'host' => 'localhost',
38
+ 'username' => ENV['POSTGRES_USER'],
39
+ 'password' => ENV['POSTGRES_PASSWORD'],
40
+ 'database' => 'template1',
41
+ 'schema_search_path' => 'public'
42
+ }
43
+ }
44
+
45
+ case db
46
+ when :postgresql
47
+ ActiveRecord::Base.establish_connection(:postgresql_master)
48
+ ActiveRecord::Base.connection.recreate_database('enumerize_test')
49
+ when :mysql2
50
+ if ActiveRecord::Base.configurations.respond_to?(:[])
51
+ ActiveRecord::Tasks::DatabaseTasks.create ActiveRecord::Base.configurations[db.to_s]
52
+ else
53
+ ActiveRecord::Tasks::DatabaseTasks.create ActiveRecord::Base.configurations.find_db_config(db.to_s)
54
+ end
55
+
56
+ ActiveRecord::Base.establish_connection(db)
57
+ else
58
+ ActiveRecord::Base.establish_connection(db)
59
+ end
9
60
  end
10
61
 
11
62
  ActiveRecord::Base.connection.instance_eval do
@@ -16,11 +67,16 @@ ActiveRecord::Base.connection.instance_eval do
16
67
  t.string :name
17
68
  t.string :interests
18
69
  t.integer :status
70
+ t.text :settings
71
+ t.integer :skill
19
72
  t.string :account_type, :default => :basic
73
+ t.string :foo
20
74
  end
21
75
 
22
76
  create_table :documents do |t|
77
+ t.integer :user_id
23
78
  t.string :visibility
79
+ t.integer :status
24
80
  t.timestamps null: true
25
81
  end
26
82
  end
@@ -33,6 +89,9 @@ class BaseEntity < ActiveRecord::Base
33
89
  end
34
90
 
35
91
  class Document < BaseEntity
92
+ belongs_to :user
93
+
94
+ enumerize :status, in: {draft: 1, release: 2}
36
95
  end
37
96
 
38
97
  module RoleEnum
@@ -45,18 +104,25 @@ class User < ActiveRecord::Base
45
104
  extend Enumerize
46
105
  include RoleEnum
47
106
 
48
- enumerize :sex, :in => [:male, :female]
107
+ store :settings, accessors: [:language]
108
+
109
+ enumerize :sex, :in => [:male, :female], scope: :shallow
110
+ enumerize :language, :in => [:en, :jp]
49
111
 
50
112
  serialize :interests, Array
51
113
  enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true
52
114
 
53
115
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: true
54
116
 
117
+ enumerize :skill, :in => { noob: 0, casual: 1, pro: 2 }, scope: :shallow
118
+
55
119
  enumerize :account_type, :in => [:basic, :premium]
56
120
 
57
121
  # There is no column for relationship enumeration for testing purposes: model
58
122
  # should not be broken even if the associated column does not exist yet.
59
123
  enumerize :relationship, :in => [:single, :married]
124
+
125
+ has_many :documents
60
126
  end
61
127
 
62
128
  class UniqStatusUser < User
@@ -68,11 +134,31 @@ class InterestsRequiredUser < User
68
134
  validates :interests, presence: true
69
135
  end
70
136
 
71
- describe Enumerize::ActiveRecordSupport do
137
+ class SkipValidationsUser < ActiveRecord::Base
138
+ self.table_name = "users"
139
+ include SkipValidationsEnum
140
+ end
141
+
142
+ class DoNotSkipValidationsUser < ActiveRecord::Base
143
+ self.table_name = "users"
144
+ include DoNotSkipValidationsEnum
145
+ end
146
+
147
+ class SkipValidationsLambdaUser < ActiveRecord::Base
148
+ self.table_name = "users"
149
+ include SkipValidationsLambdaEnum
150
+ end
151
+
152
+ class SkipValidationsLambdaWithParamUser < ActiveRecord::Base
153
+ self.table_name = "users"
154
+ include SkipValidationsLambdaWithParamEnum
155
+ end
156
+
157
+ class ActiveRecordTest < MiniTest::Spec
72
158
  it 'sets nil if invalid value is passed' do
73
159
  user = User.new
74
160
  user.sex = :invalid
75
- user.sex.must_equal nil
161
+ expect(user.sex).must_be_nil
76
162
  end
77
163
 
78
164
  it 'saves value' do
@@ -80,7 +166,7 @@ describe Enumerize::ActiveRecordSupport do
80
166
  user = User.new
81
167
  user.sex = :female
82
168
  user.save!
83
- user.sex.must_equal 'female'
169
+ expect(user.sex).must_equal 'female'
84
170
  end
85
171
 
86
172
  it 'loads value' do
@@ -88,26 +174,43 @@ describe Enumerize::ActiveRecordSupport do
88
174
  User.create!(:sex => :male)
89
175
  store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do
90
176
  user = User.first
91
- user.sex.must_equal 'male'
92
- user.sex_text.must_equal 'Male'
177
+ expect(user.sex).must_equal 'male'
178
+ expect(user.sex_text).must_equal 'Male'
93
179
  end
94
180
  end
95
181
 
182
+ it 'sets nil if invalid stored attribute value is passed' do
183
+ user = User.new
184
+ user.language = :invalid
185
+ expect(user.language).must_be_nil
186
+ end
187
+
188
+ it 'saves stored attribute value' do
189
+ User.delete_all
190
+ user = User.new
191
+ user.language = :en
192
+ user.save!
193
+ user.reload
194
+ expect(user.language).must_equal 'en'
195
+ end
196
+
96
197
  it 'has default value' do
97
- User.new.role.must_equal 'user'
98
- User.new.attributes['role'].must_equal 'user'
198
+ expect(User.new.role).must_equal 'user'
199
+ expect(User.new.attributes['role']).must_equal 'user'
99
200
  end
100
201
 
101
202
  it 'does not set default value for not selected attributes' do
102
203
  User.delete_all
103
204
  User.create!(:sex => :male)
104
205
 
105
- assert_equal ['id'], User.select(:id).first.attributes.keys
206
+ user = User.select(:id).first
207
+ expect(user.attributes['role']).must_be_nil
208
+ expect(user.attributes['lambda_role']).must_be_nil
106
209
  end
107
210
 
108
211
  it 'has default value with lambda' do
109
- User.new.lambda_role.must_equal 'admin'
110
- User.new.attributes['lambda_role'].must_equal 'admin'
212
+ expect(User.new.lambda_role).must_equal 'admin'
213
+ expect(User.new.attributes['lambda_role']).must_equal 'admin'
111
214
  end
112
215
 
113
216
  it 'uses after_initialize callback to set default value' do
@@ -115,11 +218,11 @@ describe Enumerize::ActiveRecordSupport do
115
218
  User.create!(sex: 'male', lambda_role: nil)
116
219
 
117
220
  user = User.where(:sex => 'male').first
118
- user.lambda_role.must_equal 'admin'
221
+ expect(user.lambda_role).must_equal 'admin'
119
222
  end
120
223
 
121
224
  it 'uses default value from db column' do
122
- User.new.account_type.must_equal 'basic'
225
+ expect(User.new.account_type).must_equal 'basic'
123
226
  end
124
227
 
125
228
  it 'has default value with default scope' do
@@ -127,31 +230,48 @@ describe Enumerize::ActiveRecordSupport do
127
230
  default_scope -> { having_role(:user) }
128
231
  end
129
232
 
130
- UserWithDefaultScope.new.role.must_equal 'user'
131
- UserWithDefaultScope.new.attributes['role'].must_equal 'user'
233
+ expect(UserWithDefaultScope.new.role).must_equal 'user'
234
+ expect(UserWithDefaultScope.new.attributes['role']).must_equal 'user'
132
235
  end
133
236
 
134
237
  it 'validates inclusion' do
135
238
  user = User.new
136
239
  user.role = 'wrong'
137
- user.wont_be :valid?
138
- user.errors[:role].must_include 'is not included in the list'
240
+ expect(user).wont_be :valid?
241
+ expect(user.errors[:role]).must_include 'is not included in the list'
242
+ end
243
+
244
+ it 'sets value to enumerized field from db when record is reloaded' do
245
+ user = User.create!(interests: [:music])
246
+ User.find(user.id).update(interests: %i[music dancing])
247
+ expect(user.interests).must_equal %w[music]
248
+ user.reload
249
+ expect(user.interests).must_equal %w[music dancing]
250
+ end
251
+
252
+ it 'has enumerized values in active record attributes after reload' do
253
+ User.delete_all
254
+ user = User.new
255
+ user.status = :blocked
256
+ user.save!
257
+ user.reload
258
+ expect(user.attributes["status"]).must_equal 'blocked'
139
259
  end
140
260
 
141
261
  it 'validates inclusion when using write_attribute with string attribute' do
142
262
  user = User.new
143
263
  user.send(:write_attribute, 'role', 'wrong')
144
- user.read_attribute_for_validation(:role).must_equal 'wrong'
145
- user.wont_be :valid?
146
- user.errors[:role].must_include 'is not included in the list'
264
+ expect(user.read_attribute_for_validation(:role)).must_equal 'wrong'
265
+ expect(user).wont_be :valid?
266
+ expect(user.errors[:role]).must_include 'is not included in the list'
147
267
  end
148
268
 
149
269
  it 'validates inclusion when using write_attribute with symbol attribute' do
150
270
  user = User.new
151
271
  user.send(:write_attribute, :role, 'wrong')
152
- user.read_attribute_for_validation(:role).must_equal 'wrong'
153
- user.wont_be :valid?
154
- user.errors[:role].must_include 'is not included in the list'
272
+ expect(user.read_attribute_for_validation(:role)).must_equal 'wrong'
273
+ expect(user).wont_be :valid?
274
+ expect(user.errors[:role]).must_include 'is not included in the list'
155
275
  end
156
276
 
157
277
  it 'validates inclusion on mass assignment' do
@@ -162,47 +282,72 @@ describe Enumerize::ActiveRecordSupport do
162
282
 
163
283
  it "uses persisted value for validation if it hasn't been set" do
164
284
  user = User.create! :sex => :male
165
- User.find(user.id).read_attribute_for_validation(:sex).must_equal 'male'
285
+ expect(User.find(user.id).read_attribute_for_validation(:sex)).must_equal 'male'
166
286
  end
167
287
 
168
288
  it 'is valid with empty string assigned' do
169
289
  user = User.new
170
290
  user.role = ''
171
- user.must_be :valid?
291
+ expect(user).must_be :valid?
172
292
  end
173
293
 
174
294
  it 'stores nil when empty string assigned' do
175
295
  user = User.new
176
296
  user.role = ''
177
- user.read_attribute(:role).must_equal nil
297
+ expect(user.read_attribute(:role)).must_be_nil
298
+ end
299
+
300
+ it 'validates inclusion when :skip_validations = false' do
301
+ user = DoNotSkipValidationsUser.new
302
+ user.foo = 'wrong'
303
+ expect(user).wont_be :valid?
304
+ expect(user.errors[:foo]).must_include 'is not included in the list'
305
+ end
306
+
307
+ it 'does not validate inclusion when :skip_validations = true' do
308
+ user = SkipValidationsUser.new
309
+ user.foo = 'wrong'
310
+ expect(user).must_be :valid?
311
+ end
312
+
313
+ it 'supports :skip_validations option as lambda' do
314
+ user = SkipValidationsLambdaUser.new
315
+ user.foo = 'wrong'
316
+ expect(user).must_be :valid?
317
+ end
318
+
319
+ it 'supports :skip_validations option as lambda with a parameter' do
320
+ user = SkipValidationsLambdaWithParamUser.new
321
+ user.foo = 'wrong'
322
+ expect(user).must_be :valid?
178
323
  end
179
324
 
180
325
  it 'supports multiple attributes' do
181
326
  user = User.new
182
- user.interests.must_be_empty
327
+ expect(user.interests).must_be_empty
183
328
  user.interests << :music
184
- user.interests.must_equal %w(music)
329
+ expect(user.interests).must_equal %w(music)
185
330
  user.save!
186
331
 
187
332
  user = User.find(user.id)
188
- user.interests.must_be_instance_of Enumerize::Set
189
- user.interests.must_equal %w(music)
333
+ expect(user.interests).must_be_instance_of Enumerize::Set
334
+ expect(user.interests).must_equal %w(music)
190
335
  user.interests << :sports
191
- user.interests.must_equal %w(music sports)
336
+ expect(user.interests).must_equal %w(music sports)
192
337
 
193
338
  user.interests = []
194
339
  interests = user.interests
195
340
  interests << :music
196
- interests.must_equal %w(music)
341
+ expect(interests).must_equal %w(music)
197
342
  interests << :dancing
198
- interests.must_equal %w(music dancing)
343
+ expect(interests).must_equal %w(music dancing)
199
344
  end
200
345
 
201
346
  it 'stores multiple value passed passed to new' do
202
347
  user = User.new(interests: [:music, :dancing])
203
348
  user.save!
204
- user.interests.must_equal %w(music dancing)
205
- User.find(user.id).interests.must_equal %w(music dancing)
349
+ expect(user.interests).must_equal %w(music dancing)
350
+ expect(User.find(user.id).interests).must_equal %w(music dancing)
206
351
  end
207
352
 
208
353
  it 'returns invalid multiple value for validation' do
@@ -210,57 +355,66 @@ describe Enumerize::ActiveRecordSupport do
210
355
  user.interests << :music
211
356
  user.interests << :invalid
212
357
  values = user.read_attribute_for_validation(:interests)
213
- values.must_equal %w(music invalid)
358
+ expect(values).must_equal %w(music invalid)
214
359
  end
215
360
 
216
361
  it 'validates multiple attributes' do
217
362
  user = User.new
218
363
  user.interests << :invalid
219
- user.wont_be :valid?
364
+ expect(user).wont_be :valid?
220
365
 
221
366
  user.interests = Object.new
222
- user.wont_be :valid?
367
+ expect(user).wont_be :valid?
223
368
 
224
369
  user.interests = ['music', '']
225
- user.must_be :valid?
370
+ expect(user).must_be :valid?
226
371
  end
227
372
 
228
373
  it 'stores custom values for multiple attributes' do
229
374
  User.delete_all
230
375
 
231
- klass = Class.new(User)
376
+ klass = Class.new(User) do
377
+ def self.name
378
+ 'UserSubclass'
379
+ end
380
+ end
232
381
  klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true
233
382
 
234
383
  user = klass.new
235
384
  user.interests << :music
236
- user.read_attribute(:interests).must_equal [0]
237
- user.interests.must_equal %w(music)
385
+ expect(user.read_attribute(:interests)).must_equal [0]
386
+ expect(user.interests).must_equal %w(music)
238
387
  user.save
239
388
 
240
389
  user = klass.find(user.id)
241
- user.interests.must_equal %w(music)
390
+ expect(user.interests).must_equal %w(music)
242
391
  end
243
392
 
244
393
  it 'adds scope' do
245
394
  User.delete_all
246
395
 
247
- user_1 = User.create!(status: :active, role: :admin)
248
- user_2 = User.create!(status: :blocked)
396
+ user_1 = User.create!(sex: :female, skill: :noob, status: :active, role: :admin)
397
+ user_2 = User.create!(sex: :female, skill: :casual, status: :blocked)
398
+ user_3 = User.create!(sex: :male, skill: :pro)
399
+
400
+ expect(User.with_status(:active)).must_equal [user_1]
401
+ expect(User.with_status(:blocked)).must_equal [user_2]
402
+ expect(User.with_status(:active, :blocked).to_set).must_equal [user_1, user_2].to_set
249
403
 
250
- User.with_status(:active).must_equal [user_1]
251
- User.with_status(:blocked).must_equal [user_2]
252
- User.with_status(:active, :blocked).to_set.must_equal [user_1, user_2].to_set
404
+ expect(User.without_status(:active)).must_equal [user_2]
405
+ expect(User.without_status(:active, :blocked)).must_equal []
253
406
 
254
- User.without_status(:active).must_equal [user_2]
255
- User.without_status(:active, :blocked).must_equal []
407
+ expect(User.male).must_equal [user_3]
408
+ expect(User.pro).must_equal [user_3]
256
409
 
257
- User.having_role(:admin).must_equal [user_1]
410
+ expect(User.not_male.to_set).must_equal [user_1, user_2].to_set
411
+ expect(User.not_pro.to_set).must_equal [user_1, user_2].to_set
258
412
  end
259
413
 
260
414
  it 'ignores not enumerized values that passed to the scope method' do
261
415
  User.delete_all
262
416
 
263
- User.with_status(:foo).must_equal []
417
+ expect(User.with_status(:foo)).must_equal []
264
418
  end
265
419
 
266
420
  it 'allows either key or value as valid' do
@@ -268,13 +422,13 @@ describe Enumerize::ActiveRecordSupport do
268
422
  user_2 = User.new(status: 1)
269
423
  user_3 = User.new(status: '1')
270
424
 
271
- user_1.status.must_equal 'active'
272
- user_2.status.must_equal 'active'
273
- user_3.status.must_equal 'active'
425
+ expect(user_1.status).must_equal 'active'
426
+ expect(user_2.status).must_equal 'active'
427
+ expect(user_3.status).must_equal 'active'
274
428
 
275
- user_1.must_be :valid?
276
- user_2.must_be :valid?
277
- user_3.must_be :valid?
429
+ expect(user_1).must_be :valid?
430
+ expect(user_2).must_be :valid?
431
+ expect(user_3).must_be :valid?
278
432
  end
279
433
 
280
434
  it 'supports defining enumerized attributes on abstract class' do
@@ -282,7 +436,7 @@ describe Enumerize::ActiveRecordSupport do
282
436
 
283
437
  document = Document.new
284
438
  document.visibility = :protected
285
- document.visibility.must_equal 'protected'
439
+ expect(document.visibility).must_equal 'protected'
286
440
  end
287
441
 
288
442
  it 'supports defining enumerized scopes on abstract class' do
@@ -291,7 +445,7 @@ describe Enumerize::ActiveRecordSupport do
291
445
  document_1 = Document.create!(visibility: :public)
292
446
  document_2 = Document.create!(visibility: :private)
293
447
 
294
- Document.with_visibility(:public).must_equal [document_1]
448
+ expect(Document.with_visibility(:public)).must_equal [document_1]
295
449
  end
296
450
 
297
451
  it 'validates uniqueness' do
@@ -303,7 +457,7 @@ describe Enumerize::ActiveRecordSupport do
303
457
  user.status = :active
304
458
  user.valid?
305
459
 
306
- user.errors[:status].wont_be :empty?
460
+ expect(user.errors[:status]).wont_be :empty?
307
461
  end
308
462
 
309
463
  it 'validates presence with multiple attributes' do
@@ -311,17 +465,17 @@ describe Enumerize::ActiveRecordSupport do
311
465
  user.interests = []
312
466
  user.valid?
313
467
 
314
- user.errors[:interests].wont_be :empty?
468
+ expect(user.errors[:interests]).wont_be :empty?
315
469
 
316
470
  user.interests = ['']
317
471
  user.valid?
318
472
 
319
- user.errors[:interests].wont_be :empty?
473
+ expect(user.errors[:interests]).wont_be :empty?
320
474
 
321
475
  user.interests = [:dancing, :programming]
322
476
  user.valid?
323
477
 
324
- user.errors[:interests].must_be_empty
478
+ expect(user.errors[:interests]).must_be_empty
325
479
  end
326
480
 
327
481
  it 'is valid after #becomes' do
@@ -333,7 +487,7 @@ describe Enumerize::ActiveRecordSupport do
333
487
  uniq_user = User.find(user.id).becomes(UniqStatusUser)
334
488
  uniq_user.valid?
335
489
 
336
- uniq_user.errors.must_be_empty
490
+ expect(uniq_user.errors).must_be_empty
337
491
  end
338
492
 
339
493
  it 'supports multiple attributes in #becomes' do
@@ -346,8 +500,8 @@ describe Enumerize::ActiveRecordSupport do
346
500
 
347
501
  user = uniq_user.becomes(User)
348
502
 
349
- user.sex.must_equal uniq_user.sex
350
- user.interests.must_equal uniq_user.interests
503
+ expect(user.sex).must_equal uniq_user.sex
504
+ expect(user.interests).must_equal uniq_user.interests
351
505
  end
352
506
 
353
507
  it "doesn't update record" do
@@ -369,7 +523,15 @@ describe Enumerize::ActiveRecordSupport do
369
523
  user = User.create(:status => :active)
370
524
  user.status = :blocked
371
525
 
372
- assert_equal [1, 2], YAML.load(user.changes.to_yaml)[:status]
526
+ assert_equal [1, 2], unsafe_yaml_load(user.changes.to_yaml)[:status]
527
+ end
528
+
529
+ it 'does not change by the practical same value' do
530
+ user = User.create!(status: 'active')
531
+ user.reload
532
+ user.status = 'active'
533
+
534
+ expect(user.changes).must_be_empty
373
535
  end
374
536
 
375
537
  it 'allows using update_all' do
@@ -379,26 +541,30 @@ describe Enumerize::ActiveRecordSupport do
379
541
 
380
542
  User.update_all(status: :blocked)
381
543
  user.reload
382
- user.status.must_equal 'blocked'
544
+ expect(user.status).must_equal 'blocked'
383
545
 
384
546
  User.update_all(status: :active, account_type: :basic)
385
547
  user.reload
386
- user.status.must_equal 'active'
387
- user.account_type.must_equal 'basic'
548
+ expect(user.status).must_equal 'active'
549
+ expect(user.account_type).must_equal 'basic'
388
550
  end
389
551
 
390
552
  it 'allows using update_all for multiple enumerize' do
391
553
  User.delete_all
392
554
 
393
- klass = Class.new(User)
555
+ klass = Class.new(User) do
556
+ def self.name
557
+ 'UserSubclass'
558
+ end
559
+ end
394
560
  klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true
395
561
 
396
562
  user = klass.create(status: :active)
397
563
  klass.update_all(status: :blocked, interests: [:music, :dancing])
398
564
 
399
565
  user = klass.find(user.id)
400
- user.status.must_equal 'blocked'
401
- user.interests.must_equal %w(music dancing)
566
+ expect(user.status).must_equal 'blocked'
567
+ expect(user.interests).must_equal %w(music dancing)
402
568
  end
403
569
 
404
570
  it 'allows using update_all with values' do
@@ -408,7 +574,29 @@ describe Enumerize::ActiveRecordSupport do
408
574
 
409
575
  User.update_all(status: 2)
410
576
  user.reload
411
- user.status.must_equal 'blocked'
577
+ expect(user.status).must_equal 'blocked'
578
+ end
579
+
580
+ it 'allows using update_all on relation objects' do
581
+ User.delete_all
582
+
583
+ user = User.create(status: :active, account_type: :premium)
584
+
585
+ User.all.update_all(status: :blocked)
586
+ user.reload
587
+ expect(user.status).must_equal 'blocked'
588
+ end
589
+
590
+ it 'allows using update_all on association relation objects' do
591
+ User.delete_all
592
+ Document.delete_all
593
+
594
+ user = User.create
595
+ document = Document.create(user: user, status: :draft)
596
+
597
+ user.documents.update_all(status: :release)
598
+ document.reload
599
+ expect(document.status).must_equal 'release'
412
600
  end
413
601
 
414
602
  it 'preserves string usage of update_all' do
@@ -418,7 +606,7 @@ describe Enumerize::ActiveRecordSupport do
418
606
 
419
607
  User.update_all("name = 'Frederick'")
420
608
  user.reload
421
- user.name.must_equal 'Frederick'
609
+ expect(user.name).must_equal 'Frederick'
422
610
  end
423
611
 
424
612
  it 'preserves interpolated array usage of update_all' do
@@ -428,6 +616,67 @@ describe Enumerize::ActiveRecordSupport do
428
616
 
429
617
  User.update_all(["name = :name", {name: 'Frederick'}])
430
618
  user.reload
431
- user.name.must_equal 'Frederick'
619
+ expect(user.name).must_equal 'Frederick'
620
+ end
621
+
622
+ it 'sets attribute to nil if given one is not valid' do
623
+ User.delete_all
624
+
625
+ user = User.create(status: :active)
626
+
627
+ User.update_all(status: :foo)
628
+ user.reload
629
+ expect(user.status).must_be_nil
630
+ end
631
+
632
+ it 'supports AR types serialization' do
633
+ type = User.type_for_attribute('status')
634
+ expect(type).must_be_instance_of Enumerize::ActiveRecordSupport::Type
635
+ serialized = type.serialize('blocked')
636
+ expect(serialized).must_equal 2
637
+ end
638
+
639
+ it 'has AR type itself JSON serializable' do
640
+ type = User.type_for_attribute('status')
641
+ expect(type.as_json['attr']).must_equal 'status'
642
+ end
643
+
644
+ it "doesn't break YAML serialization" do
645
+ user = unsafe_yaml_load(User.create(status: :blocked).to_yaml)
646
+ expect(user.status).must_equal 'blocked'
647
+ end
648
+
649
+ # https://github.com/brainspec/enumerize/issues/304
650
+ it "fallbacks to a raw passed value if AR type can't find value in the attribute" do
651
+ table = User.arel_table
652
+ sql = User.where(table[:account_type].matches '%foo%').to_sql
653
+
654
+ expect(sql).must_include 'LIKE \'%foo%\''
655
+ end
656
+
657
+ if Rails::VERSION::MAJOR >= 6
658
+ it 'supports AR#insert_all' do
659
+ User.delete_all
660
+
661
+ User.insert_all([{ sex: :male }])
662
+ User.insert_all([{ status: :active }])
663
+ User.insert_all([{ interests: [:music, :sports] }])
664
+
665
+ expect(User.exists?(sex: :male)).must_equal true
666
+ expect(User.exists?(status: :active)).must_equal true
667
+ expect(User.exists?(interests: [:music, :sports])).must_equal true
668
+ end
669
+
670
+ it 'supports AR#upsert_all' do
671
+ User.delete_all
672
+
673
+ User.upsert_all([{ sex: :male }])
674
+ User.upsert_all([{ status: :active }])
675
+ User.upsert_all([{ interests: [:music, :sports] }])
676
+
677
+ expect(User.exists?(sex: :male)).must_equal true
678
+ expect(User.exists?(status: :active)).must_equal true
679
+ expect(User.exists?(interests: [:music, :sports])).must_equal true
680
+ end
432
681
  end
433
682
  end