enum_table 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ module EnumTable
2
+ module SchemaDumper
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias_method_chain :tables, :enum_table
7
+ alias_method_chain :ignore_tables, :enum_table
8
+ end
9
+
10
+ def tables_with_enum_table(stream)
11
+ tables_without_enum_table(stream)
12
+ table_names = @connection.enum_tables
13
+ table_names.each do |table_name|
14
+ stream.puts " create_enum_table #{table_name.inspect}, force: true do |t|"
15
+ enum_table_column(stream, table_name, 'id', SchemaStatements::DEFAULT_ID_ATTRIBUTES)
16
+ enum_table_column(stream, table_name, 'value', SchemaStatements::DEFAULT_VALUE_ATTRIBUTES)
17
+ @connection.execute("SELECT id, value FROM #{table_name} ORDER BY id").each do |row|
18
+ stream.puts " t.add #{row[1].to_s.inspect}, #{row[0]}"
19
+ end
20
+ stream.puts " end"
21
+ stream.puts
22
+ end
23
+ end
24
+
25
+ def ignore_tables_with_enum_table
26
+ ignore_tables_without_enum_table + @connection.enum_tables << 'enum_tables'
27
+ end
28
+
29
+ private
30
+
31
+ def enum_table_column(stream, table_name, column_name, defaults)
32
+ column = @connection.columns(table_name).find { |c| c.name == column_name }
33
+ custom_attributes = {}
34
+ COLUMN_ATTRIBUTES.each do |attribute|
35
+ value = column.send(attribute)
36
+ value == defaults[attribute] or
37
+ custom_attributes[attribute] = value
38
+ end
39
+ if custom_attributes.present?
40
+ formatted = custom_attributes.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')
41
+ stream.puts " t.#{column_name} #{formatted}"
42
+ end
43
+ end
44
+
45
+ COLUMN_ATTRIBUTES = [:default, :type, :limit, :null, :precision, :scale]
46
+ end
47
+ end
48
+
49
+ # This is not loaded in enum_table.rb as it's only needed when dumping the
50
+ # schema. Instead, we make rake tasks load this file explicitly.
51
+ ActiveRecord::SchemaDumper.send :include, EnumTable::SchemaDumper
@@ -0,0 +1,86 @@
1
+ module EnumTable
2
+ module SchemaStatements
3
+ def create_enum_table(table_name, options={})
4
+ table = NewTable.new(self, table_name, options)
5
+ yield table if block_given?
6
+ table._create
7
+ end
8
+
9
+ def change_enum_table(table_name)
10
+ yield Table.new(self, table_name)
11
+ end
12
+
13
+ def drop_enum_table(table_name)
14
+ drop_table table_name
15
+ execute "DELETE FROM enum_tables WHERE table_name = '#{table_name}'"
16
+ end
17
+
18
+ def enum_tables
19
+ return [] if !table_exists?('enum_tables')
20
+ execute("SELECT table_name FROM enum_tables").map do |row|
21
+ row[0]
22
+ end.sort
23
+ end
24
+
25
+ DEFAULT_ID_ATTRIBUTES = {type: :integer, limit: 1, null: false}.freeze
26
+ DEFAULT_VALUE_ATTRIBUTES = {type: :string, limit: 255, null: false}.freeze
27
+
28
+ class NewTable
29
+ def initialize(connection, name, options)
30
+ @connection = connection
31
+ @name = name
32
+ @options = options
33
+ @id = DEFAULT_ID_ATTRIBUTES.dup
34
+ @value = DEFAULT_VALUE_ATTRIBUTES.dup
35
+ @adds = []
36
+ values = options.delete(:values) and
37
+ values.each { |args| add(*args) }
38
+ end
39
+
40
+ def _create
41
+ @connection.create_table @name, @options.merge(id: false) do |t|
42
+ t.column :id, @id.delete(:type), @id
43
+ t.column :value, @value.delete(:type), @value
44
+ end
45
+ unless @connection.table_exists?(:enum_tables)
46
+ @connection.create_table :enum_tables, id: false, force: true do |t|
47
+ t.string :table_name, null: false
48
+ end
49
+ end
50
+ @connection.execute "INSERT INTO enum_tables(table_name) VALUES('#{@name}')"
51
+ table = Table.new(@connection, @name, 0)
52
+ @adds.each { |args| table.add(*args) }
53
+ end
54
+
55
+ def id(options)
56
+ @id.update(options)
57
+ end
58
+
59
+ def value(options)
60
+ @value.update(options)
61
+ end
62
+
63
+ def add(*args)
64
+ @adds << args
65
+ end
66
+ end
67
+
68
+ class Table
69
+ def initialize(connection, name, max_id=nil)
70
+ @connection = connection
71
+ @name = name
72
+ @max_id = @connection.execute("SELECT max(id) FROM #{@name}").to_a[0][0] || 0
73
+ end
74
+
75
+ def add(value, id=nil)
76
+ id ||= @max_id + 1
77
+ @max_id = id if id > @max_id
78
+ @connection.execute "INSERT INTO #{@name}(id, value) VALUES(#{id}, '#{value}')"
79
+ end
80
+
81
+ def remove(value)
82
+ @connection.execute "DELETE FROM #{@name} WHERE value = '#{value}'"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,11 @@
1
+ module EnumTable
2
+ VERSION = [0, 0, 1]
3
+
4
+ class << VERSION
5
+ include Comparable
6
+
7
+ def to_s
8
+ join('.')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ sqlite3:
2
+ database: ':memory:'
3
+ mysql:
4
+ username: root
5
+ password:
6
+ database: db_nazi_test
7
+ mysql2:
8
+ username: root
9
+ password:
10
+ database: db_nazi_test
11
+ postgresql:
12
+ username: postgres
13
+ password:
14
+ database: db_nazi_test
15
+ min_messages: warning
16
+ jdbcmysql:
17
+ username: root
18
+ password:
19
+ database: db_nazi_test
@@ -0,0 +1,578 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe EnumTable do
4
+ use_database
5
+
6
+ before do
7
+ connection.create_table :users do |t|
8
+ t.integer :gender_id
9
+ t.integer :status_id
10
+ t.string :user_type
11
+ end
12
+ end
13
+
14
+ before { Object.const_set :User, Class.new(ActiveRecord::Base) }
15
+ after { Object.send :remove_const, :User }
16
+
17
+ describe '.enum' do
18
+ before do
19
+ connection.create_table(:user_genders) { |t| t.string :value }
20
+ connection.execute "INSERT INTO user_genders(id, value) VALUES (1, 'female'), (2, 'male')"
21
+ end
22
+
23
+ it "defines an enum by a conventionally named table by default" do
24
+ User.enum :gender
25
+ User.enums[:gender].value(1).must_equal(:female)
26
+ end
27
+
28
+ it "returns the reflection" do
29
+ reflection = User.enum :gender
30
+ reflection.must_be_kind_of EnumTable::Reflection
31
+ reflection.name.must_equal :gender
32
+ end
33
+
34
+ it "accepts the :table name as a string" do
35
+ connection.create_table(:custom_table) { |t| t.string :value }
36
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male'), (2, 'female')"
37
+ User.enum :gender, table: 'custom_table'
38
+ User.enums[:gender].value(1).must_equal(:male)
39
+ end
40
+
41
+ it "accepts the :table name as a symbol" do
42
+ connection.create_table(:custom_table) { |t| t.string :value }
43
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male'), (2, 'female')"
44
+ User.enum :gender, table: :custom_table
45
+ User.enums[:gender].value(1).must_equal(:male)
46
+ end
47
+
48
+ it "accepts the :table directly as a hash" do
49
+ User.enum :gender, table: {male: 1, female: 2}
50
+ User.enums[:gender].value(1).must_equal :male
51
+ end
52
+
53
+ it "accepts the :table as an array" do
54
+ User.enum :gender, table: [:male, :female]
55
+ User.enums[:gender].value(1).must_equal :male
56
+ end
57
+
58
+ it "raises an ArgumentError if :table is something else" do
59
+ ->{ User.enum :gender, table: Object.new }.must_raise ArgumentError, /invalid :table specifier/
60
+ end
61
+
62
+ it "passes other options to the Reflection" do
63
+ User.enum :gender, id_name: :gender_number
64
+ enum = User.enums[:gender]
65
+ enum.id_name.must_equal :gender_number
66
+ end
67
+
68
+ describe "on a subclass" do
69
+ before do
70
+ User.inheritance_column = :user_type
71
+ Object.const_set :Subuser, Class.new(User)
72
+ end
73
+
74
+ after do
75
+ Object.send :remove_const, :Subuser
76
+ end
77
+
78
+ it "makes any values in the superclass available in the subclass" do
79
+ User.enum :gender, table: {female: 1}
80
+ Subuser.enum :gender, table: {male: 2}
81
+ Subuser.reflect_on_enum(:gender).id(:female).must_equal 1
82
+ end
83
+
84
+ it "makes any values added in the subclass not available to the superclass" do
85
+ User.enum :gender, table: {female: 1}
86
+ Subuser.enum :gender, table: {male: 2}
87
+ User.reflect_on_enum(:gender).id(:male).must_be_nil
88
+ end
89
+
90
+ it "inherits options from the superclass that aren't given for the subclass" do
91
+ User.enum :gender, table: {female: 1, male: 2}, type: :string, id_name: :status_id
92
+ Subuser.enum :gender
93
+ reflection = Subuser.reflect_on_enum(:gender)
94
+ reflection.id(:female).must_equal 1
95
+ reflection.type.must_equal :string
96
+ reflection.id_name.must_equal :status_id
97
+ end
98
+
99
+ it "inherits options from the superclass if no enum call is made in the subclass" do
100
+ User.enum :gender, table: {female: 1, male: 2}
101
+ Subuser.reflect_on_enum(:gender).id(:female).must_equal 1
102
+ end
103
+
104
+ it "allows overriding the :type option in the subclass" do
105
+ User.enum :gender, type: :symbol
106
+ Subuser.enum :gender, type: :string
107
+ User.reflect_on_enum(:gender).type.must_equal :symbol
108
+ Subuser.reflect_on_enum(:gender).type.must_equal :string
109
+ end
110
+
111
+ it "allows overriding the :id_name option in the subclass" do
112
+ User.enum :gender, id_name: :status_id, type: :symbol
113
+ Subuser.enum :gender, id_name: :status_id, type: :string
114
+ User.reflect_on_enum(:gender).type.must_equal :symbol
115
+ Subuser.reflect_on_enum(:gender).type.must_equal :string
116
+ end
117
+ end
118
+ end
119
+
120
+ describe ".reflect_on_enum" do
121
+ before { User.enum :gender, table: {} }
122
+
123
+ it "returns the reflection for the named enum" do
124
+ reflection = User.reflect_on_enum(:gender)
125
+ reflection.name.must_equal :gender
126
+ end
127
+
128
+ it "returns nil if there is no such enum" do
129
+ User.reflect_on_enum(:invalid).must_be_nil
130
+ end
131
+ end
132
+
133
+ describe ".enum_id" do
134
+ before { User.enum :gender, table: {female: 1} }
135
+
136
+ it "raises an ArgumentError if the enum name is invalid" do
137
+ ->{ User.enum_id(:bad) }.must_raise ArgumentError
138
+ end
139
+
140
+ it "returns the id for the given enum value" do
141
+ User.enum_id(:gender, :female).must_equal 1
142
+ end
143
+ end
144
+
145
+ describe ".initialize_attributes" do
146
+ before { User.enum :gender, table: {female: 1, male: 2} }
147
+
148
+ it "converts enums to their underlying IDs" do
149
+ attributes = User.initialize_attributes('gender' => 'female')
150
+ attributes.must_equal('gender_id' => 1)
151
+ end
152
+
153
+ it "does not prevent optimistic locking from working, which also uses this internal method" do
154
+ attributes = User.initialize_attributes('lock_version' => nil)
155
+ attributes.must_equal('lock_version' => 0)
156
+ end
157
+
158
+ it "should favor the ID if both the id and value are present in the attributes hash (so enums override columns)" do
159
+ attributes = User.initialize_attributes('gender_id' => 1, 'gender' => :male)
160
+ attributes['gender_id'].must_equal 1
161
+ attributes.key?('gender').must_equal false
162
+ end
163
+ end
164
+
165
+ describe "#enum_id" do
166
+ before { User.enum :gender, table: {female: 1} }
167
+
168
+ it "raises an ArgumentError if the enum name is invalid" do
169
+ user = User.new
170
+ ->{ user.enum_id(:bad) }.must_raise ArgumentError
171
+ end
172
+
173
+ it "returns the id for the given enum value" do
174
+ user = User.new
175
+ user.enum_id(:gender, :female).must_equal 1
176
+ end
177
+ end
178
+
179
+ describe "#read_enum" do
180
+ before { User.enum :gender, table: {female: 1, male: 2} }
181
+
182
+ it "raises an ArgumentError if the enum name is invalid" do
183
+ user = User.new
184
+ ->{ user.read_enum(:bad) }.must_raise ArgumentError
185
+ end
186
+
187
+ it "returns the value mapped to the id" do
188
+ user = User.new(gender_id: 1)
189
+ user.read_enum(:gender).must_equal :female
190
+ end
191
+
192
+ it "returns nil if the id is not mapped" do
193
+ user = User.new(gender_id: 3)
194
+ user.read_enum(:gender).must_be_nil
195
+ end
196
+
197
+ describe "when loading an existing record" do
198
+ before do
199
+ connection.execute "INSERT INTO users(id, gender_id) VALUES(1, 1)"
200
+ end
201
+
202
+ it "returns the correct value" do
203
+ user = User.find(1)
204
+ user.read_enum(:gender).must_equal :female
205
+ end
206
+ end
207
+ end
208
+
209
+ describe "#write_enum" do
210
+ before { User.enum :gender, table: {female: 1, male: 2} }
211
+
212
+ it "raises an ArgumentError if the enum name is invalid" do
213
+ user = User.new
214
+ ->{ user.write_enum(:bad, :female) }.must_raise ArgumentError
215
+ end
216
+
217
+ it "sets the id to the id mapped to the given value" do
218
+ user = User.new
219
+ user.write_enum(:gender, :female)
220
+ user.gender_id.must_equal 1
221
+ end
222
+
223
+ it "sets the id to nil if the given value is not mapped to an id" do
224
+ user = User.new
225
+ user.write_enum(:gender, :other)
226
+ user.gender_id.must_be_nil
227
+ end
228
+ end
229
+
230
+ describe "#read_attribute" do
231
+ before { User.enum :gender, table: {female: 1, male: 2} }
232
+
233
+ it "reads enums" do
234
+ user = User.new(gender_id: 1)
235
+ user.read_attribute(:gender).must_equal :female
236
+ end
237
+
238
+ it "allows string names for enums" do
239
+ user = User.new(gender_id: 1)
240
+ user.read_attribute('gender').must_equal :female
241
+ end
242
+
243
+ it "still reads attributes" do
244
+ user = User.new(gender_id: 1)
245
+ user.read_attribute(:gender_id).must_equal 1
246
+ end
247
+ end
248
+
249
+ describe "#write_attribute" do
250
+ before { User.enum :gender, table: {female: 1, male: 2} }
251
+
252
+ it "writes enums" do
253
+ user = User.new
254
+ user.write_attribute(:gender, :female)
255
+ user.gender_id.must_equal 1
256
+ end
257
+
258
+ it "allows string names for enums" do
259
+ user = User.new
260
+ user.write_attribute('gender', :female)
261
+ user.gender_id.must_equal 1
262
+ end
263
+
264
+ it "still writes attributes" do
265
+ user = User.new
266
+ user.write_attribute(:gender_id, 1)
267
+ user.gender_id.must_equal 1
268
+ end
269
+ end
270
+
271
+ describe "#query_enum" do
272
+ before { User.enum :gender, table: {female: 1, male: 2} }
273
+
274
+ it "raises an ArgumentError if the enum name is invalid" do
275
+ user = User.new
276
+ ->{ user.query_enum(:bad) }.must_raise ArgumentError
277
+ end
278
+
279
+ it "returns true if the is mapped to a value" do
280
+ user = User.new(gender_id: 1)
281
+ user.query_enum(:gender).must_equal true
282
+ end
283
+
284
+ it "returns false if the given value is not mapped to an id" do
285
+ user = User.new(gender_id: 3)
286
+ user.query_enum(:gender).must_equal false
287
+ end
288
+ end
289
+
290
+ describe "#enum_changed?" do
291
+ before do
292
+ User.enum :gender, table: {female: 1, male: 2}
293
+ User.create(gender_id: 1)
294
+ end
295
+
296
+ it "raises an ArgumentError if the enum name is invalid" do
297
+ user = User.first
298
+ ->{ user.enum_changed?(:bad) }.must_raise ArgumentError
299
+ end
300
+
301
+ it "returns true if the enum value changed" do
302
+ user = User.first
303
+ user.gender = :male
304
+ user.enum_changed?(:gender).must_equal true
305
+ end
306
+
307
+ it "returns true if the id attribute changed" do
308
+ user = User.first
309
+ user.gender_id = 2
310
+ user.enum_changed?(:gender).must_equal true
311
+ end
312
+
313
+ it "returns false if the attribute value has not changed" do
314
+ user = User.first
315
+ user.enum_changed?(:gender).must_equal false
316
+ end
317
+ end
318
+
319
+ describe "#enum_was" do
320
+ before do
321
+ User.enum :gender, table: {female: 1, male: 2}
322
+ User.create(gender_id: 1)
323
+ end
324
+
325
+ it "raises an ArgumentError if the enum name is invalid" do
326
+ user = User.first
327
+ ->{ user.enum_was(:bad) }.must_raise ArgumentError
328
+ end
329
+
330
+ it "returns the old value if the enum value changed" do
331
+ user = User.first
332
+ user.gender = :male
333
+ user.enum_was(:gender).must_equal :female
334
+ end
335
+
336
+ it "returns the old value if the id attribute changed" do
337
+ user = User.first
338
+ user.gender_id = 2
339
+ user.enum_was(:gender).must_equal :female
340
+ end
341
+
342
+ it "returns the current value if the enum has not changed" do
343
+ user = User.first
344
+ user.enum_was(:gender).must_equal :female
345
+ end
346
+ end
347
+
348
+ describe "#enum_change" do
349
+ before do
350
+ User.enum :gender, table: {female: 1, male: 2}
351
+ User.create(gender_id: 1)
352
+ end
353
+
354
+ it "raises an ArgumentError if the enum name is invalid" do
355
+ user = User.first
356
+ ->{ user.enum_change(:bad) }.must_raise ArgumentError
357
+ end
358
+
359
+ it "returns the old and new values if the enum value changed" do
360
+ user = User.first
361
+ user.gender = :male
362
+ user.enum_change(:gender).must_equal [:female, :male]
363
+ end
364
+
365
+ it "returns the old and new values if the enum id changed" do
366
+ user = User.first
367
+ user.gender_id = 2
368
+ user.enum_change(:gender).must_equal [:female, :male]
369
+ end
370
+
371
+ it "returns nil if the enum has not changed" do
372
+ user = User.first
373
+ user.enum_change(:gender).must_be_nil
374
+ end
375
+ end
376
+
377
+ describe "#ENUM" do
378
+ before { User.enum :gender, table: {female: 1, male: 2} }
379
+
380
+ it "returns the enum value" do
381
+ user = User.new(gender_id: 1)
382
+ user.gender.must_equal :female
383
+ end
384
+ end
385
+
386
+ describe "#ENUM=" do
387
+ before { User.enum :gender, table: {female: 1, male: 2} }
388
+
389
+ it "sets the enum value" do
390
+ user = User.new
391
+ user.gender = :female
392
+ user.gender_id.must_equal 1
393
+ end
394
+ end
395
+
396
+ describe "#ENUM?" do
397
+ before { User.enum :gender, table: {female: 1, male: 2} }
398
+
399
+ it "returns true if the enum value is present" do
400
+ user = User.new(gender_id: nil)
401
+ user.gender?.must_equal false
402
+
403
+ user = User.new(gender_id: 1)
404
+ user.gender?.must_equal true
405
+ end
406
+ end
407
+
408
+ describe "#ENUM_changed?" do
409
+ before do
410
+ User.enum :gender, table: {female: 1, male: 2}
411
+ User.create(gender_id: 1)
412
+ end
413
+
414
+ it "returns the changed flag for the enum" do
415
+ user = User.first
416
+ user.gender_changed?.must_equal false
417
+
418
+ user.gender_id = 2
419
+ user.gender_changed?.must_equal true
420
+ end
421
+ end
422
+
423
+ describe "#ENUM_was" do
424
+ before do
425
+ User.enum :gender, table: {female: 1, male: 2}
426
+ User.create(gender_id: 1)
427
+ end
428
+
429
+ it "returns the changed flag for the enum" do
430
+ user = User.first
431
+ user.gender_was.must_equal :female
432
+ end
433
+ end
434
+
435
+ describe "#ENUM_change" do
436
+ before do
437
+ User.enum :gender, table: {female: 1, male: 2}
438
+ User.create(gender_id: 1)
439
+ end
440
+
441
+ it "returns the old and new values for the enum" do
442
+ user = User.first
443
+ user.gender_change.must_be_nil
444
+
445
+ user.gender_id = 2
446
+ user.gender_change.must_equal [:female, :male]
447
+ end
448
+ end
449
+
450
+ describe "roundtripping" do
451
+ it "roundtrips a value through write and read" do
452
+ User.enum :gender, table: {female: 1, male: 2}
453
+ user = User.new
454
+ user.gender = :female
455
+ user.gender.must_equal :female
456
+ end
457
+
458
+ it "roundtrips a value through persistence" do
459
+ User.enum :gender, table: {female: 1, male: 2}
460
+ User.create(gender: :female)
461
+ User.first.gender.must_equal :female
462
+ end
463
+
464
+ it "supports strings values" do
465
+ User.enum :gender, table: {female: 1, male: 2}, type: :string
466
+ User.create(gender: 'female')
467
+ User.first.gender.must_equal 'female'
468
+ end
469
+ end
470
+
471
+ describe ".where" do
472
+ it "supports filtering by enums with symbol keys" do
473
+ User.enum :gender, table: {female: 1, male: 2}
474
+ female = User.create(gender_id: 1)
475
+ male = User.create(gender_id: 2)
476
+ User.where(gender: :female).all.must_equal [female]
477
+ end
478
+
479
+ it "supports filtering by enums with string keys" do
480
+ User.enum :gender, table: {female: 1, male: 2}
481
+ female = User.create(gender_id: 1)
482
+ male = User.create(gender_id: 2)
483
+ User.where('gender' => :female).all.must_equal [female]
484
+ end
485
+
486
+ it "supports filtering by multiple values" do
487
+ User.enum :gender, table: {female: 1, male: 2, other: 3}
488
+ female = User.create(gender_id: 1)
489
+ male = User.create(gender_id: 2)
490
+ other = User.create(gender_id: 3)
491
+ User.where(gender: [:female, :male]).all.must_equal [female, male]
492
+ end
493
+
494
+ it "still supports filtering by other attributes" do
495
+ User.enum :gender, table: {female: 1, male: 2}
496
+ female1 = User.create(gender_id: 1, status_id: 1)
497
+ male1 = User.create(gender_id: 2, status_id: 1)
498
+ male2 = User.create(gender_id: 2, status_id: 2)
499
+ User.where(gender: :male, status_id: 1).all.must_equal [male1]
500
+ end
501
+ end
502
+
503
+ describe "dynamic finders" do
504
+ it "support retrieval by enums" do
505
+ User.enum :gender, table: {female: 1, male: 2}
506
+ female = User.create(gender_id: 1)
507
+ male = User.create(gender_id: 2)
508
+
509
+ User.find_by_gender(:female).must_equal female
510
+ User.find_all_by_gender(:female).must_equal [female]
511
+ end
512
+ end
513
+
514
+ describe "when the inheritance column is an enum" do
515
+ before do
516
+ connection.add_column :users, :type_id, :integer
517
+ User.enum :type, table: {Admin: 1, Member: 2}
518
+ Object.const_set :Admin, Class.new(User)
519
+ Object.const_set :Member, Class.new(User)
520
+ end
521
+
522
+ after do
523
+ Object.send :remove_const, :Admin
524
+ Object.send :remove_const, :Member
525
+
526
+ # Instantiating STI classes goes through ActiveSupport::Dependencies.
527
+ ActiveSupport::Dependencies.clear
528
+ end
529
+
530
+ it "sets the type ID when instantiating" do
531
+ admin = Admin.create
532
+ admin.type_id.must_equal 1
533
+ end
534
+
535
+ it "instantiates the correct class through the superclass" do
536
+ admin = Admin.create
537
+ user = User.find(admin.id)
538
+ user.class.must_equal Admin
539
+ user.id.must_equal admin.id
540
+ end
541
+
542
+ it "finds and instantiates the correct class through the subclass" do
543
+ admin = Admin.create
544
+ found = Admin.find(admin.id)
545
+ found.class.must_equal Admin
546
+ found.id.must_equal admin.id
547
+ end
548
+
549
+ it "filters correctly when finding through the subclass" do
550
+ admin = Admin.create
551
+ Admin.find(admin.id).must_equal admin
552
+ Member.find_by_id(admin.id).must_be_nil
553
+ end
554
+ end
555
+
556
+ describe "when an enum has the same name as a column" do
557
+ before do
558
+ connection.add_column :users, :gender, :string
559
+ User.enum :gender, table: {female: 1, male: 2}
560
+ end
561
+
562
+ # TODO: It's probably desirable to write the column if it's present, for
563
+ # transitioning to an enum.
564
+ it "only writes the enum id" do
565
+ User.create(gender_id: 1)
566
+ results = connection.execute("SELECT gender_id, gender FROM users").to_a
567
+ results.size.must_equal 1
568
+ results[0][0].must_equal 1
569
+ results[0][1].must_equal nil
570
+ end
571
+
572
+ it "favors the enum when loading" do
573
+ connection.execute "INSERT INTO users(gender_id, gender) VALUES(1, 'male')"
574
+ User.first.gender_id.must_equal 1
575
+ User.first.gender.must_equal :female
576
+ end
577
+ end
578
+ end