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