schema_plus 1.5.3 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -8
- data/CHANGELOG.md +10 -4
- data/README.md +24 -4
- data/Rakefile +1 -1
- data/gemfiles/rails-4.1/Gemfile.base +1 -1
- data/lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb +11 -5
- data/lib/schema_plus/active_record/connection_adapters/postgresql_adapter.rb +58 -2
- data/lib/schema_plus/active_record/schema_dumper.rb +10 -0
- data/lib/schema_plus/version.rb +1 -1
- data/runspecs +1 -1
- data/spec/column_default_spec.rb +20 -26
- data/spec/column_spec.rb +22 -24
- data/spec/connections/postgresql/connection.rb +1 -1
- data/spec/enum_spec.rb +132 -0
- data/spec/foreign_key_spec.rb +18 -15
- data/spec/index_definition_spec.rb +97 -102
- data/spec/index_spec.rb +5 -8
- data/spec/migration_spec.rb +288 -303
- data/spec/named_schemas_spec.rb +24 -26
- data/spec/schema_dumper_spec.rb +66 -53
- data/spec/spec_helper.rb +6 -0
- data/spec/views_spec.rb +41 -24
- metadata +24 -22
data/spec/migration_spec.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
3
|
|
4
4
|
describe ActiveRecord::Migration do
|
5
|
-
include SchemaPlusHelpers
|
6
5
|
|
7
6
|
before(:each) do
|
8
7
|
define_schema(:auto_create => true) do
|
@@ -44,7 +43,7 @@ describe ActiveRecord::Migration do
|
|
44
43
|
it "should properly handle default values for booleans" do
|
45
44
|
expect {
|
46
45
|
recreate_table(@model) do |t|
|
47
|
-
|
46
|
+
t.boolean :bool, :default => true
|
48
47
|
end
|
49
48
|
}.to_not raise_error
|
50
49
|
expect(@model.create.reload.bool).to be true
|
@@ -218,15 +217,13 @@ describe ActiveRecord::Migration do
|
|
218
217
|
end
|
219
218
|
end
|
220
219
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
t.string :bar, :index => { :with => :foo, :length => { :foo => 8, :bar => 12 }}
|
226
|
-
end
|
227
|
-
index = @model.indexes.first
|
228
|
-
expect(Hash[index.columns.zip(index.lengths.map(&:to_i))]).to eq({ "foo" => 8, "bar" => 12})
|
220
|
+
it "should pass index length option properly", :mysql => :only do
|
221
|
+
recreate_table(@model) do |t|
|
222
|
+
t.string :foo
|
223
|
+
t.string :bar, :index => { :with => :foo, :length => { :foo => 8, :bar => 12 }}
|
229
224
|
end
|
225
|
+
index = @model.indexes.first
|
226
|
+
expect(Hash[index.columns.zip(index.lengths.map(&:to_i))]).to eq({ "foo" => 8, "bar" => 12})
|
230
227
|
end
|
231
228
|
|
232
229
|
it "should create an index if specified explicitly" do
|
@@ -293,63 +290,69 @@ describe ActiveRecord::Migration do
|
|
293
290
|
|
294
291
|
actions = [:cascade, :restrict, :set_null, :set_default, :no_action]
|
295
292
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
}.to raise_error(NotImplementedError)
|
304
|
-
end
|
305
|
-
|
306
|
-
it "should raise a not-implemented error for on_delete => :set_default" do
|
307
|
-
expect {
|
308
|
-
recreate_table @model do |t|
|
309
|
-
t.integer :user_id, :foreign_key => { :on_delete => :set_default }
|
310
|
-
end
|
311
|
-
}.to raise_error(NotImplementedError)
|
293
|
+
actions.each do |action|
|
294
|
+
if action == :set_default
|
295
|
+
if_action_supported = { :mysql => :skip }
|
296
|
+
if_action_unsupported = { :mysql => :only }
|
297
|
+
else
|
298
|
+
if_action_supported = { :if => true }
|
299
|
+
if_action_unsupported = { :if => false }
|
312
300
|
end
|
313
|
-
end
|
314
301
|
|
315
|
-
|
316
|
-
it "should create and detect on_update #{action.inspect}" do
|
302
|
+
it "should create and detect on_update #{action.inspect}", if_action_supported do
|
317
303
|
recreate_table @model do |t|
|
318
304
|
t.integer :user_id, :foreign_key => { :on_update => action }
|
319
305
|
end
|
320
306
|
expect(@model).to reference.on(:user_id).on_update(action)
|
321
307
|
end
|
322
308
|
|
323
|
-
it "should create and detect on_update #{action.inspect} using shortcut" do
|
309
|
+
it "should create and detect on_update #{action.inspect} using shortcut", if_action_supported do
|
324
310
|
recreate_table @model do |t|
|
325
311
|
t.integer :user_id, :on_update => action
|
326
312
|
end
|
327
313
|
expect(@model).to reference.on(:user_id).on_update(action)
|
328
314
|
end
|
329
315
|
|
330
|
-
it "should
|
316
|
+
it "should raise a not-implemented error for on_update => #{action}", if_action_unsupported do
|
317
|
+
expect {
|
318
|
+
recreate_table @model do |t|
|
319
|
+
t.integer :user_id, :foreign_key => { :on_update => action }
|
320
|
+
end
|
321
|
+
}.to raise_error(NotImplementedError)
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should create and detect on_delete #{action.inspect}", if_action_supported do
|
331
325
|
recreate_table @model do |t|
|
332
326
|
t.integer :user_id, :foreign_key => { :on_delete => action }
|
333
327
|
end
|
334
328
|
expect(@model).to reference.on(:user_id).on_delete(action)
|
335
329
|
end
|
336
330
|
|
337
|
-
it "should create and detect on_delete #{action.inspect} using shortcut" do
|
331
|
+
it "should create and detect on_delete #{action.inspect} using shortcut", if_action_supported do
|
338
332
|
recreate_table @model do |t|
|
339
333
|
t.integer :user_id, :on_delete => action
|
340
334
|
end
|
341
335
|
expect(@model).to reference.on(:user_id).on_delete(action)
|
342
336
|
end
|
337
|
+
|
338
|
+
it "should raise a not-implemented error for on_delete => #{action}", if_action_unsupported do
|
339
|
+
expect {
|
340
|
+
recreate_table @model do |t|
|
341
|
+
t.integer :user_id, :foreign_key => { :on_delete => action }
|
342
|
+
end
|
343
|
+
}.to raise_error(NotImplementedError)
|
344
|
+
end
|
345
|
+
|
343
346
|
end
|
344
347
|
|
345
348
|
[false, true, :initially_deferred].each do |status|
|
346
|
-
it "should create and detect deferrable #{status.inspect}" do
|
349
|
+
it "should create and detect deferrable #{status.inspect}", :mysql => :skip do
|
347
350
|
recreate_table @model do |t|
|
348
351
|
t.integer :user_id, :on_delete => :cascade, :deferrable => status
|
349
352
|
end
|
350
353
|
expect(@model).to reference.on(:user_id).deferrable(status)
|
351
354
|
end
|
352
|
-
end
|
355
|
+
end
|
353
356
|
|
354
357
|
it "should use default on_delete action" do
|
355
358
|
with_fk_config(:on_delete => :cascade) do
|
@@ -407,30 +410,27 @@ describe ActiveRecord::Migration do
|
|
407
410
|
it "should raise an error for an invalid on_delete action" do
|
408
411
|
expect {
|
409
412
|
recreate_table @model do |t|
|
410
|
-
|
413
|
+
t.integer :user_id, :foreign_key => { :on_delete => :invalid }
|
411
414
|
end
|
412
415
|
}.to raise_error(ArgumentError)
|
413
416
|
end
|
414
417
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
t.integer :user_id
|
420
|
-
end
|
421
|
-
expect(@model).not_to have_index.on(:user_id)
|
418
|
+
it "should override foreign key auto_index negatively", :mysql => :skip do
|
419
|
+
with_fk_config(:auto_index => true) do
|
420
|
+
recreate_table @model, :foreign_keys => {:auto_index => false} do |t|
|
421
|
+
t.integer :user_id
|
422
422
|
end
|
423
|
+
expect(@model).not_to have_index.on(:user_id)
|
423
424
|
end
|
425
|
+
end
|
424
426
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
end
|
430
|
-
expect(@model).not_to have_index.on(:user_id)
|
427
|
+
it "should disable auto-index for a column", :mysql => :skip do
|
428
|
+
with_fk_config(:auto_index => true) do
|
429
|
+
recreate_table @model do |t|
|
430
|
+
t.integer :user_id, :index => false
|
431
431
|
end
|
432
|
+
expect(@model).not_to have_index.on(:user_id)
|
432
433
|
end
|
433
|
-
|
434
434
|
end
|
435
435
|
|
436
436
|
end
|
@@ -449,323 +449,313 @@ describe ActiveRecord::Migration do
|
|
449
449
|
expect(@model).to have_index.on(:state)
|
450
450
|
end
|
451
451
|
|
452
|
-
|
452
|
+
it "should create a foreign key constraint"+suffix, :sqlite3 => :skip do
|
453
|
+
change_table(@model, :bulk => bulk) do |t|
|
454
|
+
t.integer :user_id
|
455
|
+
end
|
456
|
+
expect(@model).to reference(:users, :id).on(:user_id)
|
457
|
+
end
|
453
458
|
|
454
|
-
|
455
|
-
|
456
|
-
|
459
|
+
context "migrate down" do
|
460
|
+
it "should remove a foreign key constraint"+suffix, :sqlite3 => :skip do
|
461
|
+
Comment.reset_column_information
|
462
|
+
expect(Comment).to reference(:users, :id).on(:user_id)
|
463
|
+
migration = Class.new ::ActiveRecord::Migration do
|
464
|
+
define_method(:change) {
|
465
|
+
change_table("comments", :bulk => bulk) do |t|
|
466
|
+
t.integer :user_id
|
467
|
+
end
|
468
|
+
}
|
457
469
|
end
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
context "migrate down" do
|
462
|
-
it "should remove a foreign key constraint"+suffix do
|
463
|
-
Comment.reset_column_information
|
464
|
-
expect(Comment).to reference(:users, :id).on(:user_id)
|
465
|
-
migration = Class.new ::ActiveRecord::Migration do
|
466
|
-
define_method(:change) {
|
467
|
-
change_table("comments", :bulk => bulk) do |t|
|
468
|
-
t.integer :user_id
|
469
|
-
end
|
470
|
-
}
|
471
|
-
end
|
472
|
-
ActiveRecord::Migration.suppress_messages do
|
473
|
-
migration.migrate(:down)
|
474
|
-
end
|
475
|
-
Comment.reset_column_information
|
476
|
-
expect(Comment).not_to reference(:users, :id).on(:user_id)
|
470
|
+
ActiveRecord::Migration.suppress_messages do
|
471
|
+
migration.migrate(:down)
|
477
472
|
end
|
478
|
-
|
473
|
+
Comment.reset_column_information
|
474
|
+
expect(Comment).not_to reference(:users, :id).on(:user_id)
|
475
|
+
end
|
476
|
+
end if ActiveRecord::VERSION::MAJOR >= 4
|
479
477
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
end
|
484
|
-
expect(@model).to reference(:users, :id).on(:user_id)
|
478
|
+
it "should create a foreign key constraint using :references"+suffix, :sqlite3 => :skip do
|
479
|
+
change_table(@model, :bulk => bulk) do |t|
|
480
|
+
t.references :user
|
485
481
|
end
|
482
|
+
expect(@model).to reference(:users, :id).on(:user_id)
|
483
|
+
end
|
486
484
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
end
|
491
|
-
expect(@model).to reference(:users, :id).on(:user_id)
|
485
|
+
it "should create a foreign key constraint using :belongs_to"+suffix, :sqlite3 => :skip do
|
486
|
+
change_table(@model, :bulk => bulk) do |t|
|
487
|
+
t.belongs_to :user
|
492
488
|
end
|
489
|
+
expect(@model).to reference(:users, :id).on(:user_id)
|
493
490
|
end
|
494
491
|
end
|
495
492
|
end
|
496
493
|
|
494
|
+
context "when column is added", :sqlite3 => :skip do
|
497
495
|
|
498
|
-
|
499
|
-
|
500
|
-
|
496
|
+
before(:each) do
|
497
|
+
@model = Comment
|
498
|
+
end
|
501
499
|
|
502
|
-
|
503
|
-
|
500
|
+
it "should create an index" do
|
501
|
+
add_column(:slug, :string, :index => true) do
|
502
|
+
expect(@model).to have_index.on(:slug)
|
504
503
|
end
|
504
|
+
end
|
505
505
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
end
|
506
|
+
it "should create foreign key" do
|
507
|
+
add_column(:post_id, :integer) do
|
508
|
+
expect(@model).to reference(:posts, :id).on(:post_id)
|
510
509
|
end
|
510
|
+
end
|
511
511
|
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
end
|
512
|
+
it "should create foreign key to explicitly given table" do
|
513
|
+
add_column(:author_id, :integer, :foreign_key => { :references => :users }) do
|
514
|
+
expect(@model).to reference(:users, :id).on(:author_id)
|
516
515
|
end
|
516
|
+
end
|
517
517
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
end
|
518
|
+
it "should create foreign key to explicitly given table using shortcut" do
|
519
|
+
add_column(:author_id, :integer, :references => :users) do
|
520
|
+
expect(@model).to reference(:users, :id).on(:author_id)
|
522
521
|
end
|
522
|
+
end
|
523
523
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
end
|
524
|
+
it "should create foreign key to explicitly given table and column name" do
|
525
|
+
add_column(:author_login, :string, :foreign_key => { :references => [:users, :login]}) do
|
526
|
+
expect(@model).to reference(:users, :login).on(:author_login)
|
528
527
|
end
|
528
|
+
end
|
529
529
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
end
|
530
|
+
it "should create foreign key to the same table on parent_id" do
|
531
|
+
add_column(:parent_id, :integer) do
|
532
|
+
expect(@model).to reference(@model.table_name, :id).on(:parent_id)
|
534
533
|
end
|
534
|
+
end
|
535
535
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
end
|
536
|
+
it "shouldn't create foreign key if column doesn't look like foreign key" do
|
537
|
+
add_column(:views_count, :integer) do
|
538
|
+
expect(@model).not_to reference.on(:views_count)
|
540
539
|
end
|
540
|
+
end
|
541
541
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
end
|
542
|
+
it "shouldn't create foreign key if specified explicitly" do
|
543
|
+
add_column(:post_id, :integer, :foreign_key => false) do
|
544
|
+
expect(@model).not_to reference.on(:post_id)
|
546
545
|
end
|
546
|
+
end
|
547
547
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
end
|
548
|
+
it "shouldn't create foreign key if specified explicitly by shorthand" do
|
549
|
+
add_column(:post_id, :integer, :references => nil) do
|
550
|
+
expect(@model).not_to reference.on(:post_id)
|
552
551
|
end
|
552
|
+
end
|
553
553
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
end
|
554
|
+
it "should create an index if specified" do
|
555
|
+
add_column(:post_id, :integer, :index => true) do
|
556
|
+
expect(@model).to have_index.on(:post_id)
|
558
557
|
end
|
558
|
+
end
|
559
559
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
end
|
560
|
+
it "should create a unique index if specified" do
|
561
|
+
add_column(:post_id, :integer, :index => { :unique => true }) do
|
562
|
+
expect(@model).to have_unique_index.on(:post_id)
|
564
563
|
end
|
564
|
+
end
|
565
565
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
end
|
566
|
+
it "should create a unique index if specified by shorthand" do
|
567
|
+
add_column(:post_id, :integer, :index => :unique) do
|
568
|
+
expect(@model).to have_unique_index.on(:post_id)
|
570
569
|
end
|
570
|
+
end
|
571
571
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
572
|
+
it "should allow custom name for index" do
|
573
|
+
index_name = 'comments_post_id_unique_index'
|
574
|
+
add_column(:post_id, :integer, :index => { :unique => true, :name => index_name }) do
|
575
|
+
expect(@model).to have_unique_index(:name => index_name).on(:post_id)
|
576
576
|
end
|
577
|
+
end
|
577
578
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
end
|
579
|
+
it "should auto-index if specified in global options" do
|
580
|
+
SchemaPlus.config.foreign_keys.auto_index = true
|
581
|
+
add_column(:post_id, :integer) do
|
582
|
+
expect(@model).to have_index.on(:post_id)
|
583
583
|
end
|
584
|
+
SchemaPlus.config.foreign_keys.auto_index = false
|
585
|
+
end
|
584
586
|
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
end
|
590
|
-
SchemaPlus.config.foreign_keys.auto_index = false
|
587
|
+
it "should auto-index foreign keys only" do
|
588
|
+
SchemaPlus.config.foreign_keys.auto_index = true
|
589
|
+
add_column(:state, :integer) do
|
590
|
+
expect(@model).not_to have_index.on(:state)
|
591
591
|
end
|
592
|
+
SchemaPlus.config.foreign_keys.auto_index = false
|
593
|
+
end
|
592
594
|
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
SchemaPlus.config.foreign_keys.auto_index = false
|
595
|
+
# MySQL creates an index on foreign key and we can't override that
|
596
|
+
it "should allow to overwrite auto_index options in column definition", :mysql => :skip do
|
597
|
+
SchemaPlus.config.foreign_keys.auto_index = true
|
598
|
+
add_column(:post_id, :integer, :index => false) do
|
599
|
+
expect(@model).not_to have_index.on(:post_id)
|
599
600
|
end
|
601
|
+
SchemaPlus.config.foreign_keys.auto_index = false
|
602
|
+
end
|
600
603
|
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
# and we can do nothing with that
|
606
|
-
unless SchemaPlusHelpers.mysql?
|
607
|
-
expect(@model).not_to have_index.on(:post_id)
|
608
|
-
end
|
609
|
-
end
|
610
|
-
SchemaPlus.config.foreign_keys.auto_index = false
|
604
|
+
it "should use default on_update action" do
|
605
|
+
SchemaPlus.config.foreign_keys.on_update = :cascade
|
606
|
+
add_column(:post_id, :integer) do
|
607
|
+
expect(@model).to reference.on(:post_id).on_update(:cascade)
|
611
608
|
end
|
609
|
+
SchemaPlus.config.foreign_keys.on_update = nil
|
610
|
+
end
|
612
611
|
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
end
|
618
|
-
SchemaPlus.config.foreign_keys.on_update = nil
|
612
|
+
it "should use default on_delete action" do
|
613
|
+
SchemaPlus.config.foreign_keys.on_delete = :cascade
|
614
|
+
add_column(:post_id, :integer) do
|
615
|
+
expect(@model).to reference.on(:post_id).on_delete(:cascade)
|
619
616
|
end
|
617
|
+
SchemaPlus.config.foreign_keys.on_delete = nil
|
618
|
+
end
|
620
619
|
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
SchemaPlus.config.foreign_keys.on_delete = nil
|
620
|
+
it "should allow to overwrite default actions" do
|
621
|
+
SchemaPlus.config.foreign_keys.on_delete = :cascade
|
622
|
+
SchemaPlus.config.foreign_keys.on_update = :restrict
|
623
|
+
add_column(:post_id, :integer, :foreign_key => { :on_update => :set_null, :on_delete => :set_null}) do
|
624
|
+
expect(@model).to reference.on(:post_id).on_delete(:set_null).on_update(:set_null)
|
627
625
|
end
|
626
|
+
SchemaPlus.config.foreign_keys.on_delete = nil
|
627
|
+
end
|
628
628
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
629
|
+
protected
|
630
|
+
def add_column(column_name, *args)
|
631
|
+
table = @model.table_name
|
632
|
+
ActiveRecord::Migration.suppress_messages do
|
633
|
+
ActiveRecord::Migration.add_column(table, column_name, *args)
|
634
|
+
@model.reset_column_information
|
635
|
+
yield if block_given?
|
636
|
+
ActiveRecord::Migration.remove_column(table, column_name)
|
636
637
|
end
|
638
|
+
end
|
637
639
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
ActiveRecord::Migration.add_column(table, column_name, *args)
|
643
|
-
@model.reset_column_information
|
644
|
-
yield if block_given?
|
645
|
-
ActiveRecord::Migration.remove_column(table, column_name)
|
646
|
-
end
|
647
|
-
end
|
640
|
+
end
|
641
|
+
|
642
|
+
|
643
|
+
context "when column is changed", :sqlite3 => :skip do
|
648
644
|
|
645
|
+
before(:each) do
|
646
|
+
@model = Comment
|
649
647
|
end
|
650
648
|
|
649
|
+
it "should create foreign key" do
|
650
|
+
change_column :user, :string, :foreign_key => { :references => [:users, :login] }
|
651
|
+
expect(@model).to reference(:users, :login).on(:user)
|
652
|
+
end
|
651
653
|
|
652
|
-
context "
|
654
|
+
context "and initially references to users table" do
|
653
655
|
|
654
656
|
before(:each) do
|
655
|
-
@model
|
657
|
+
recreate_table @model do |t|
|
658
|
+
t.integer :user_id
|
659
|
+
end
|
656
660
|
end
|
657
661
|
|
658
|
-
it "should
|
659
|
-
|
660
|
-
expect(@model).to reference(:users, :login).on(:user)
|
662
|
+
it "should have foreign key" do
|
663
|
+
expect(@model).to reference(:users)
|
661
664
|
end
|
662
665
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
t.integer :user_id
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
|
-
it "should have foreign key" do
|
672
|
-
expect(@model).to reference(:users)
|
673
|
-
end
|
666
|
+
it "should drop foreign key if it is no longer valid" do
|
667
|
+
change_column :user_id, :integer, :foreign_key => { :references => :members }
|
668
|
+
expect(@model).not_to reference(:users)
|
669
|
+
end
|
674
670
|
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
671
|
+
it "should drop foreign key if requested to do so" do
|
672
|
+
change_column :user_id, :integer, :foreign_key => { :references => nil }
|
673
|
+
expect(@model).not_to reference(:users)
|
674
|
+
end
|
679
675
|
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
676
|
+
it "should remove auto-created index if foreign key is removed" do
|
677
|
+
expect(@model).to have_index.on(:user_id) # sanity check that index was auto-created
|
678
|
+
change_column :user_id, :integer, :foreign_key => { :references => nil }
|
679
|
+
expect(@model).not_to have_index.on(:user_id)
|
680
|
+
end
|
684
681
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
end
|
682
|
+
it "should reference pointed table afterwards if new one is created" do
|
683
|
+
change_column :user_id, :integer, :foreign_key => { :references => :members }
|
684
|
+
expect(@model).to reference(:members)
|
685
|
+
end
|
690
686
|
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
687
|
+
it "should maintain foreign key if it's unaffected by change" do
|
688
|
+
change_column :user_id, :integer, :default => 0
|
689
|
+
expect(@model).to reference(:users)
|
690
|
+
end
|
695
691
|
|
696
|
-
|
692
|
+
it "should maintain foreign key if it's unaffected by change, even if auto_index is off" do
|
693
|
+
with_fk_config(:auto_create => false) do
|
697
694
|
change_column :user_id, :integer, :default => 0
|
698
695
|
expect(@model).to reference(:users)
|
699
696
|
end
|
700
|
-
|
701
|
-
it "should maintain foreign key if it's unaffected by change, even if auto_index is off" do
|
702
|
-
with_fk_config(:auto_create => false) do
|
703
|
-
change_column :user_id, :integer, :default => 0
|
704
|
-
expect(@model).to reference(:users)
|
705
|
-
end
|
706
|
-
end
|
707
|
-
|
708
697
|
end
|
709
698
|
|
710
|
-
|
711
|
-
before(:each) do
|
712
|
-
recreate_table @model do |t|
|
713
|
-
t.integer :user_id, :foreign_key => false, :index => true
|
714
|
-
end
|
715
|
-
end
|
716
|
-
|
717
|
-
it "should create the index" do
|
718
|
-
expect(@model).to have_index.on(:user_id)
|
719
|
-
end
|
699
|
+
end
|
720
700
|
|
721
|
-
|
722
|
-
|
701
|
+
context "if column defined without foreign key but with index" do
|
702
|
+
before(:each) do
|
703
|
+
recreate_table @model do |t|
|
704
|
+
t.integer :user_id, :foreign_key => false, :index => true
|
723
705
|
end
|
724
706
|
end
|
725
707
|
|
726
|
-
|
727
|
-
|
728
|
-
table = @model.table_name
|
729
|
-
ActiveRecord::Migration.suppress_messages do
|
730
|
-
ActiveRecord::Migration.change_column(table, column_name, *args)
|
731
|
-
@model.reset_column_information
|
732
|
-
end
|
708
|
+
it "should create the index" do
|
709
|
+
expect(@model).to have_index.on(:user_id)
|
733
710
|
end
|
734
711
|
|
712
|
+
it "adding foreign key should not fail due to attempt to auto-create existing index" do
|
713
|
+
expect { change_column :user_id, :integer, :foreign_key => true }.to_not raise_error
|
714
|
+
end
|
735
715
|
end
|
736
716
|
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
717
|
+
protected
|
718
|
+
def change_column(column_name, *args)
|
719
|
+
table = @model.table_name
|
720
|
+
ActiveRecord::Migration.suppress_messages do
|
721
|
+
ActiveRecord::Migration.change_column(table, column_name, *args)
|
722
|
+
@model.reset_column_information
|
743
723
|
end
|
724
|
+
end
|
744
725
|
|
745
|
-
|
746
|
-
expect(@model).to reference(:posts)
|
747
|
-
remove_column(:post_id)
|
748
|
-
expect(@model).not_to reference(:posts)
|
749
|
-
end
|
726
|
+
end
|
750
727
|
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
728
|
+
context "when column is removed", :sqlite3 => :skip do
|
729
|
+
before(:each) do
|
730
|
+
@model = Comment
|
731
|
+
recreate_table @model do |t|
|
732
|
+
t.integer :post_id
|
755
733
|
end
|
734
|
+
end
|
756
735
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
736
|
+
it "should remove a foreign key" do
|
737
|
+
expect(@model).to reference(:posts)
|
738
|
+
remove_column(:post_id)
|
739
|
+
expect(@model).not_to reference(:posts)
|
740
|
+
end
|
741
|
+
|
742
|
+
it "should remove an index" do
|
743
|
+
expect(@model).to have_index.on(:post_id)
|
744
|
+
remove_column(:post_id)
|
745
|
+
expect(@model).not_to have_index.on(:post_id)
|
765
746
|
end
|
766
747
|
|
748
|
+
protected
|
749
|
+
def remove_column(column_name)
|
750
|
+
table = @model.table_name
|
751
|
+
ActiveRecord::Migration.suppress_messages do
|
752
|
+
ActiveRecord::Migration.remove_column(table, column_name)
|
753
|
+
@model.reset_column_information
|
754
|
+
end
|
755
|
+
end
|
767
756
|
end
|
768
757
|
|
758
|
+
|
769
759
|
context "when table is renamed" do
|
770
760
|
|
771
761
|
before(:each) do
|
@@ -799,44 +789,39 @@ describe ActiveRecord::Migration do
|
|
799
789
|
expect(index.name).to match(/^fk__newname_/)
|
800
790
|
end
|
801
791
|
|
802
|
-
|
803
|
-
|
804
|
-
expect(ActiveRecord::Base.connection.foreign_keys(:newname).first.name).to match(/newname/)
|
805
|
-
end
|
792
|
+
it "should rename foreign key constraints", :sqlite3 => :skip do
|
793
|
+
expect(ActiveRecord::Base.connection.foreign_keys(:newname).first.name).to match(/newname/)
|
806
794
|
end
|
807
795
|
|
808
796
|
end
|
809
797
|
|
810
|
-
unless SchemaPlusHelpers.sqlite3?
|
811
798
|
|
812
|
-
|
799
|
+
context "when table with more than one fk constraint is renamed", :sqlite3 => :skip do
|
813
800
|
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
end
|
801
|
+
before(:each) do
|
802
|
+
@model = Comment
|
803
|
+
recreate_table @model do |t|
|
804
|
+
t.integer :user_id
|
805
|
+
t.integer :member_id
|
806
|
+
end
|
807
|
+
ActiveRecord::Migration.suppress_messages do
|
808
|
+
ActiveRecord::Migration.rename_table @model.table_name, :newname
|
823
809
|
end
|
810
|
+
end
|
824
811
|
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
end
|
812
|
+
around(:each) do |example|
|
813
|
+
begin
|
814
|
+
example.run
|
815
|
+
ensure
|
816
|
+
ActiveRecord::Migration.suppress_messages do
|
817
|
+
ActiveRecord::Migration.rename_table :newname, :comments
|
832
818
|
end
|
833
819
|
end
|
834
|
-
it "should rename foreign key constraints" do
|
835
|
-
names = ActiveRecord::Base.connection.foreign_keys(:newname).map(&:name)
|
836
|
-
expect(names.grep(/newname/)).to eq(names)
|
837
|
-
end
|
838
820
|
end
|
839
|
-
|
821
|
+
it "should rename foreign key constraints" do
|
822
|
+
names = ActiveRecord::Base.connection.foreign_keys(:newname).map(&:name)
|
823
|
+
expect(names.grep(/newname/)).to eq(names)
|
824
|
+
end
|
840
825
|
end
|
841
826
|
|
842
827
|
def recreate_table(model, opts={}, &block)
|