declare_schema 0.10.0 → 0.12.0.pre.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +16 -6
  5. data/lib/declare_schema.rb +12 -1
  6. data/lib/declare_schema/extensions/active_record/fields_declaration.rb +4 -2
  7. data/lib/declare_schema/model.rb +59 -15
  8. data/lib/declare_schema/model/column.rb +2 -2
  9. data/lib/declare_schema/model/field_spec.rb +4 -4
  10. data/lib/declare_schema/model/foreign_key_definition.rb +6 -11
  11. data/lib/declare_schema/model/habtm_model_shim.rb +2 -2
  12. data/lib/declare_schema/model/index_definition.rb +8 -25
  13. data/lib/declare_schema/schema_change/all.rb +22 -0
  14. data/lib/declare_schema/schema_change/base.rb +45 -0
  15. data/lib/declare_schema/schema_change/column_add.rb +27 -0
  16. data/lib/declare_schema/schema_change/column_change.rb +32 -0
  17. data/lib/declare_schema/schema_change/column_remove.rb +20 -0
  18. data/lib/declare_schema/schema_change/column_rename.rb +23 -0
  19. data/lib/declare_schema/schema_change/foreign_key_add.rb +25 -0
  20. data/lib/declare_schema/schema_change/foreign_key_remove.rb +20 -0
  21. data/lib/declare_schema/schema_change/index_add.rb +33 -0
  22. data/lib/declare_schema/schema_change/index_remove.rb +20 -0
  23. data/lib/declare_schema/schema_change/primary_key_change.rb +33 -0
  24. data/lib/declare_schema/schema_change/table_add.rb +37 -0
  25. data/lib/declare_schema/schema_change/table_change.rb +36 -0
  26. data/lib/declare_schema/schema_change/table_remove.rb +22 -0
  27. data/lib/declare_schema/schema_change/table_rename.rb +22 -0
  28. data/lib/declare_schema/version.rb +1 -1
  29. data/lib/generators/declare_schema/migration/USAGE +14 -24
  30. data/lib/generators/declare_schema/migration/migration_generator.rb +40 -38
  31. data/lib/generators/declare_schema/migration/migrator.rb +190 -187
  32. data/lib/generators/declare_schema/migration/templates/migration.rb.erb +3 -3
  33. data/spec/lib/declare_schema/api_spec.rb +3 -1
  34. data/spec/lib/declare_schema/field_spec_spec.rb +3 -3
  35. data/spec/lib/declare_schema/generator_spec.rb +2 -2
  36. data/spec/lib/declare_schema/interactive_primary_key_spec.rb +60 -25
  37. data/spec/lib/declare_schema/migration_generator_spec.rb +471 -377
  38. data/spec/lib/declare_schema/model/column_spec.rb +2 -6
  39. data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +28 -16
  40. data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +4 -6
  41. data/spec/lib/declare_schema/model/index_definition_spec.rb +4 -4
  42. data/spec/lib/declare_schema/schema_change/base_spec.rb +75 -0
  43. data/spec/lib/declare_schema/schema_change/column_add_spec.rb +30 -0
  44. data/spec/lib/declare_schema/schema_change/column_change_spec.rb +33 -0
  45. data/spec/lib/declare_schema/schema_change/column_remove_spec.rb +30 -0
  46. data/spec/lib/declare_schema/schema_change/column_rename_spec.rb +28 -0
  47. data/spec/lib/declare_schema/schema_change/foreign_key_add_spec.rb +29 -0
  48. data/spec/lib/declare_schema/schema_change/foreign_key_remove_spec.rb +29 -0
  49. data/spec/lib/declare_schema/schema_change/index_add_spec.rb +56 -0
  50. data/spec/lib/declare_schema/schema_change/index_remove_spec.rb +29 -0
  51. data/spec/lib/declare_schema/schema_change/primary_key_change_spec.rb +69 -0
  52. data/spec/lib/declare_schema/schema_change/table_add_spec.rb +50 -0
  53. data/spec/lib/declare_schema/schema_change/table_change_spec.rb +30 -0
  54. data/spec/lib/declare_schema/schema_change/table_remove_spec.rb +27 -0
  55. data/spec/lib/declare_schema/schema_change/table_rename_spec.rb +27 -0
  56. data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +59 -11
  57. data/spec/spec_helper.rb +1 -1
  58. data/spec/support/acceptance_spec_helpers.rb +2 -2
  59. metadata +34 -5
@@ -1,9 +1,9 @@
1
- class <%= @migration_class_name %> < (Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)
1
+ class <%= @migration_class_name %> < (ActiveSupport::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)
2
2
  def self.up
3
- <%= @up %>
3
+ <%= @up.presence or raise "no @up given!" %>
4
4
  end
5
5
 
6
6
  def self.down
7
- <%= @down %>
7
+ <%= @down.presence or raise "no @down given!" %>
8
8
  end
9
9
  end
@@ -39,12 +39,14 @@ RSpec.describe 'DeclareSchema API' do
39
39
 
40
40
  load_models
41
41
 
42
- if Rails::VERSION::MAJOR == 5
42
+ if ActiveSupport::VERSION::MAJOR == 5
43
43
  # TODO: get this to work on Travis for Rails 6
44
+ # TODO: uncomment since we're not on Travis any more? -Colin
44
45
  generate_migrations '-n', '-m'
45
46
  end
46
47
 
47
48
  require 'advert'
49
+ Advert.reset_primary_key
48
50
 
49
51
  ## The Basics
50
52
 
@@ -6,13 +6,13 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  RSpec.describe DeclareSchema::Model::FieldSpec do
9
- let(:model) { double('model', table_options: {}, _defined_primary_key: 'id') }
9
+ let(:model) { double('model', _table_options: {}, _declared_primary_key: 'id') }
10
10
  let(:col_spec) { double('col_spec', type: :string) }
11
11
 
12
12
  before do
13
13
  load File.expand_path('prepare_testapp.rb', __dir__)
14
14
 
15
- if Rails::VERSION::MAJOR < 5
15
+ if ActiveSupport::VERSION::MAJOR < 5
16
16
  allow(col_spec).to receive(:type_cast_from_database, &:itself)
17
17
  end
18
18
  end
@@ -184,7 +184,7 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
184
184
 
185
185
  describe '#schema_attributes' do
186
186
  let(:col_spec) do
187
- case Rails::VERSION::MAJOR
187
+ case ActiveSupport::VERSION::MAJOR
188
188
  when 4
189
189
  cast_type = ActiveRecord::Type::Integer.new(limit: 8)
190
190
  ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
@@ -27,7 +27,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
27
27
  end
28
28
  EOS
29
29
 
30
- case Rails::VERSION::MAJOR
30
+ case ActiveSupport::VERSION::MAJOR
31
31
  when 4, 5
32
32
  expect_test_definition_to_eq('alpha/beta', <<~EOS)
33
33
  require "test_helper"
@@ -50,7 +50,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
50
50
  EOS
51
51
  end
52
52
 
53
- case Rails::VERSION::MAJOR
53
+ case ActiveSupport::VERSION::MAJOR
54
54
  when 4
55
55
  expect_test_fixture_to_eq('alpha/beta', <<~EOS)
56
56
  # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails'
4
3
  begin
5
4
  require 'mysql2'
6
5
  rescue LoadError
@@ -20,7 +19,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
20
19
  end
21
20
 
22
21
  generate_migrations '-n', '-m'
23
- expect(Foo._defined_primary_key).to eq('foo_id')
22
+ expect(Foo._declared_primary_key).to eq('foo_id')
24
23
 
25
24
  ### migrate from
26
25
  # rename from custom primary_key
@@ -32,13 +31,38 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
32
31
 
33
32
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'id' }
34
33
  generate_migrations '-n', '-m'
35
- expect(Foo._defined_primary_key).to eq('id')
34
+ expect(Foo._declared_primary_key).to eq('id')
36
35
 
37
36
  nuke_model_class(Foo)
38
37
 
39
- ### migrate to
38
+ # The ActiveRecord sqlite3 driver has a bug where rename_column recreates the entire table, but forgets to set the primary key:
39
+ #
40
+ # [7] pry(#<RSpec::ExampleGroups::DeclareSchemaMigrationGeneratorInteractivePrimaryKey>)> u = 'rename_column :foos, :foo_id, :id'
41
+ # => "rename_column :foos, :foo_id, :id"
42
+ # [8] pry(#<RSpec::ExampleGroups::DeclareSchemaMigrationGeneratorInteractivePrimaryKey>)> ActiveRecord::Migration.class_eval(u)
43
+ # (0.0ms) begin transaction
44
+ # (pry):17
45
+ # (0.2ms) CREATE TEMPORARY TABLE "afoos" ("id" integer NOT NULL)
46
+ # (pry):17
47
+ # (0.1ms) INSERT INTO "afoos" ("id")
48
+ #
49
+ # (pry):17
50
+ # (0.4ms) DROP TABLE "foos"
51
+ # (pry):17
52
+ # (0.1ms) CREATE TABLE "foos" ("id" integer NOT NULL)
53
+ # (pry):17
54
+ # (0.1ms) INSERT INTO "foos" ("id")
55
+ #
56
+ # (pry):17
57
+ # (0.1ms) DROP TABLE "afoos"
58
+ # (pry):17
59
+ # (0.9ms) commit transaction
60
+ if defined?(SQLite3)
61
+ ActiveRecord::Base.connection.execute("drop table foos")
62
+ ActiveRecord::Base.connection.execute("CREATE TABLE foos (id integer PRIMARY KEY AUTOINCREMENT NOT NULL)")
63
+ end
40
64
 
41
- if Rails::VERSION::MAJOR >= 5 && !defined?(Mysql2) # TODO TECH-4814 Put this test back for Mysql2
65
+ if ActiveSupport::VERSION::MAJOR >= 5 && !defined?(Mysql2) # TODO TECH-4814 Put this test back for Mysql2
42
66
  # replace custom primary_key
43
67
  class Foo < ActiveRecord::Base
44
68
  fields do
@@ -48,13 +72,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
48
72
 
49
73
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'drop id' }
50
74
  generate_migrations '-n', '-m'
51
- expect(Foo._defined_primary_key).to eq('foo_id')
52
-
53
- ### ensure it doesn't cause further migrations
54
-
55
- # check no further migrations
56
- up = Generators::DeclareSchema::Migration::Migrator.run.first
57
- expect(up).to eq("")
75
+ expect(Foo._declared_primary_key).to eq('foo_id')
58
76
  end
59
77
  end
60
78
  end
@@ -62,8 +80,7 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
62
80
  context 'Using declare_schema' do
63
81
  it "allows alternate primary keys" do
64
82
  class Foo < ActiveRecord::Base
65
- declare_schema do
66
- end
83
+ declare_schema { }
67
84
  self.primary_key = "foo_id"
68
85
  end
69
86
 
@@ -73,21 +90,45 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
73
90
  ### migrate from
74
91
  # rename from custom primary_key
75
92
  class Foo < ActiveRecord::Base
76
- declare_schema do
77
- end
93
+ declare_schema { }
78
94
  self.primary_key = "id"
79
95
  end
80
96
 
81
97
  puts "\n\e[45m Please enter 'id' (no quotes) at the next prompt \e[0m"
82
98
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'id' }
83
99
  generate_migrations '-n', '-m'
84
- expect(Foo.primary_key).to eq('id')
100
+ expect(Foo._declared_primary_key).to eq('id')
85
101
 
86
102
  nuke_model_class(Foo)
87
103
 
88
- ### migrate to
104
+ # The ActiveRecord sqlite3 driver has a bug where rename_column recreates the entire table, but forgets to set the primary key:
105
+ #
106
+ # [7] pry(#<RSpec::ExampleGroups::DeclareSchemaMigrationGeneratorInteractivePrimaryKey>)> u = 'rename_column :foos, :foo_id, :id'
107
+ # => "rename_column :foos, :foo_id, :id"
108
+ # [8] pry(#<RSpec::ExampleGroups::DeclareSchemaMigrationGeneratorInteractivePrimaryKey>)> ActiveRecord::Migration.class_eval(u)
109
+ # (0.0ms) begin transaction
110
+ # (pry):17
111
+ # (0.2ms) CREATE TEMPORARY TABLE "afoos" ("id" integer NOT NULL)
112
+ # (pry):17
113
+ # (0.1ms) INSERT INTO "afoos" ("id")
114
+ #
115
+ # (pry):17
116
+ # (0.4ms) DROP TABLE "foos"
117
+ # (pry):17
118
+ # (0.1ms) CREATE TABLE "foos" ("id" integer NOT NULL)
119
+ # (pry):17
120
+ # (0.1ms) INSERT INTO "foos" ("id")
121
+ #
122
+ # (pry):17
123
+ # (0.1ms) DROP TABLE "afoos"
124
+ # (pry):17
125
+ # (0.9ms) commit transaction
126
+ if defined?(SQLite3)
127
+ ActiveRecord::Base.connection.execute("drop table foos")
128
+ ActiveRecord::Base.connection.execute("CREATE TABLE foos (id integer PRIMARY KEY AUTOINCREMENT NOT NULL)")
129
+ end
89
130
 
90
- if Rails::VERSION::MAJOR >= 5 && !defined?(Mysql2) # TODO TECH-4814 Put this test back for Mysql2
131
+ if ActiveSupport::VERSION::MAJOR >= 5 && !defined?(Mysql2) # TODO TECH-4814 Put this test back for Mysql2
91
132
  # replace custom primary_key
92
133
  class Foo < ActiveRecord::Base
93
134
  declare_schema do
@@ -99,12 +140,6 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
99
140
  allow_any_instance_of(DeclareSchema::Support::ThorShell).to receive(:ask).with(/one of the rename choices or press enter to keep/) { 'drop id' }
100
141
  generate_migrations '-n', '-m'
101
142
  expect(Foo.primary_key).to eq('foo_id')
102
-
103
- ### ensure it doesn't cause further migrations
104
-
105
- # check no further migrations
106
- up = Generators::DeclareSchema::Migration::Migrator.run.first
107
- expect(up).to eq("")
108
143
  end
109
144
  end
110
145
  end
@@ -1,25 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails'
4
3
  begin
5
4
  require 'mysql2'
6
5
  rescue LoadError
7
6
  end
8
7
 
8
+ begin
9
+ require 'sqlite3'
10
+ rescue LoadError
11
+ end
12
+
9
13
  RSpec.describe 'DeclareSchema Migration Generator' do
10
14
  before do
11
15
  load File.expand_path('prepare_testapp.rb', __dir__)
12
16
  end
13
-
14
- let(:charset_alter_table) do
15
- if defined?(Mysql2)
16
- <<~EOS
17
-
18
-
19
- execute "ALTER TABLE `adverts` CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
20
- EOS
21
- end
22
- end
23
17
  let(:text_limit) do
24
18
  if defined?(Mysql2)
25
19
  ", limit: 4294967295"
@@ -30,21 +24,26 @@ RSpec.describe 'DeclareSchema Migration Generator' do
30
24
  ', charset: "utf8mb4", collation: "utf8mb4_bin"'
31
25
  end
32
26
  end
27
+ let(:create_table_charset_and_collation) do
28
+ if defined?(Mysql2)
29
+ ", options: \"CHARACTER SET utf8mb4 COLLATE utf8mb4_bin\""
30
+ end
31
+ end
33
32
  let(:datetime_precision) do
34
- if defined?(Mysql2) && Rails::VERSION::MAJOR >= 5
33
+ if defined?(Mysql2) && ActiveSupport::VERSION::MAJOR >= 5
35
34
  ', precision: 0'
36
35
  end
37
36
  end
38
37
  let(:table_options) do
39
38
  if defined?(Mysql2)
40
- ", options: \"#{'ENGINE=InnoDB ' if Rails::VERSION::MAJOR == 5}DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\"" +
41
- if Rails::VERSION::MAJOR >= 6
39
+ ", options: \"#{'ENGINE=InnoDB ' if ActiveSupport::VERSION::MAJOR == 5}DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\"" +
40
+ if ActiveSupport::VERSION::MAJOR >= 6
42
41
  ', charset: "utf8mb4", collation: "utf8mb4_bin"'
43
42
  else
44
43
  ''
45
44
  end
46
45
  else
47
- ", id: :integer" unless Rails::VERSION::MAJOR < 5
46
+ ", id: :integer" unless ActiveSupport::VERSION::MAJOR < 5
48
47
  end
49
48
  end
50
49
  let(:lock_version_limit) do
@@ -81,9 +80,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
81
80
  up, _ = Generators::DeclareSchema::Migration::Migrator.run.tap do |migrations|
82
81
  expect(migrations).to(
83
82
  migrate_up(<<~EOS.strip)
84
- create_table :adverts, id: :bigint do |t|
83
+ create_table :adverts, id: :bigint#{create_table_charset_and_collation} do |t|
85
84
  t.string :name, limit: 250, null: true#{charset_and_collation}
86
- end#{charset_alter_table}
85
+ end
87
86
  EOS
88
87
  .and migrate_down("drop_table :adverts")
89
88
  )
@@ -92,7 +91,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
92
91
  ActiveRecord::Migration.class_eval(up)
93
92
  expect(Advert.columns.map(&:name)).to eq(["id", "name"])
94
93
 
95
- if Rails::VERSION::MAJOR < 5
94
+ if ActiveSupport::VERSION::MAJOR < 5
96
95
  # Rails 4 drivers don't always create PK properly. Fix that by dropping and recreating.
97
96
  ActiveRecord::Base.connection.execute("drop table adverts")
98
97
  if defined?(Mysql2)
@@ -119,8 +118,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
119
118
  add_column :adverts, :published_at, :datetime, null: true
120
119
  EOS
121
120
  .and migrate_down(<<~EOS.strip)
122
- remove_column :adverts, :body
123
121
  remove_column :adverts, :published_at
122
+ remove_column :adverts, :body
124
123
  EOS
125
124
  )
126
125
 
@@ -152,8 +151,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
152
151
  remove_column :adverts, :name
153
152
  EOS
154
153
  .and migrate_down(<<~EOS.strip)
155
- remove_column :adverts, :title
156
154
  add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
155
+ remove_column :adverts, :title
157
156
  EOS
158
157
  )
159
158
 
@@ -370,17 +369,13 @@ RSpec.describe 'DeclareSchema Migration Generator' do
370
369
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
371
370
  migrate_up(<<~EOS.strip)
372
371
  add_column :adverts, :category_id, :integer, limit: 8, null: false
373
-
374
- add_index :adverts, [:category_id], name: 'on_category_id'
375
-
376
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" if defined?(Mysql2)}
372
+ add_index :adverts, [:category_id], name: :on_category_id
373
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id" if defined?(Mysql2)}
377
374
  EOS
378
375
  .and migrate_down(<<~EOS.strip)
376
+ #{"remove_foreign_key :adverts, name: :index_adverts_on_category_id" if defined?(Mysql2)}
377
+ remove_index :adverts, name: :on_category_id
379
378
  remove_column :adverts, :category_id
380
-
381
- remove_index :adverts, name: :on_category_id rescue ActiveRecord::StatementInvalid
382
-
383
- #{"remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" if defined?(Mysql2)}
384
379
  EOS
385
380
  )
386
381
 
@@ -398,11 +393,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
398
393
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
399
394
  migrate_up(<<~EOS.strip)
400
395
  add_column :adverts, :c_id, :integer, limit: 8, null: false
401
-
402
- add_index :adverts, [:c_id], name: 'on_c_id'
403
-
404
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
405
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
396
+ add_index :adverts, [:c_id], name: :on_c_id
397
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
398
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
406
399
  EOS
407
400
  )
408
401
 
@@ -420,9 +413,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
420
413
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
421
414
  migrate_up(<<~EOS.strip)
422
415
  add_column :adverts, :category_id, :integer, limit: 8, null: false
423
-
424
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
425
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
416
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
417
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
426
418
  EOS
427
419
  )
428
420
 
@@ -440,21 +432,19 @@ RSpec.describe 'DeclareSchema Migration Generator' do
440
432
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
441
433
  migrate_up(<<~EOS.strip)
442
434
  add_column :adverts, :category_id, :integer, limit: 8, null: false
443
-
444
- add_index :adverts, [:category_id], name: 'my_index'
445
-
446
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
447
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
435
+ add_index :adverts, [:category_id], name: :my_index
436
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
437
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
448
438
  EOS
449
439
  )
450
440
 
451
441
  Advert.field_specs.delete(:category_id)
452
442
  Advert.index_definitions.delete_if { |spec| spec.fields == ["category_id"] }
453
443
 
454
- ### Timestamps and Optimimistic Locking
444
+ ### Timestamps and Optimistic Locking
455
445
 
456
446
  # `updated_at` and `created_at` can be declared with the shorthand `timestamps`.
457
- # Similarly, `lock_version` can be declared with the "shorthand" `optimimistic_lock`.
447
+ # Similarly, `lock_version` can be declared with the "shorthand" `optimistic_lock`.
458
448
 
459
449
  class Advert < ActiveRecord::Base
460
450
  fields do
@@ -468,17 +458,15 @@ RSpec.describe 'DeclareSchema Migration Generator' do
468
458
  add_column :adverts, :created_at, :datetime, null: true
469
459
  add_column :adverts, :updated_at, :datetime, null: true
470
460
  add_column :adverts, :lock_version, :integer#{lock_version_limit}, null: false, default: 1
471
-
472
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
473
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
461
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
462
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
474
463
  EOS
475
464
  .and migrate_down(<<~EOS.strip)
476
- remove_column :adverts, :created_at
477
- remove_column :adverts, :updated_at
465
+ #{"remove_foreign_key :adverts, name: :index_adverts_on_c_id\n" +
466
+ "remove_foreign_key :adverts, name: :index_adverts_on_category_id" if defined?(Mysql2)}
478
467
  remove_column :adverts, :lock_version
479
-
480
- #{"remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" +
481
- "remove_foreign_key(\"adverts\", name: \"on_c_id\")" if defined?(Mysql2)}
468
+ remove_column :adverts, :updated_at
469
+ remove_column :adverts, :created_at
482
470
  EOS
483
471
  )
484
472
 
@@ -499,11 +487,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
499
487
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
500
488
  migrate_up(<<~EOS.strip)
501
489
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
502
-
503
- add_index :adverts, [:title], name: 'on_title'
504
-
505
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
506
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
490
+ add_index :adverts, [:title], name: :on_title
491
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
492
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
507
493
  EOS
508
494
  )
509
495
 
@@ -520,11 +506,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
520
506
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
521
507
  migrate_up(<<~EOS.strip)
522
508
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
523
-
524
- add_index :adverts, [:title], unique: true, name: 'on_title'
525
-
526
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
527
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
509
+ add_index :adverts, [:title], name: :on_title, unique: true
510
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
511
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
528
512
  EOS
529
513
  )
530
514
 
@@ -541,11 +525,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
541
525
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
542
526
  migrate_up(<<~EOS.strip)
543
527
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
544
-
545
- add_index :adverts, [:title], name: 'my_index'
546
-
547
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
548
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
528
+ add_index :adverts, [:title], name: :my_index
529
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
530
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
549
531
  EOS
550
532
  )
551
533
 
@@ -560,11 +542,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
560
542
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
561
543
  migrate_up(<<~EOS.strip)
562
544
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
563
-
564
- add_index :adverts, [:title], name: 'on_title'
565
-
566
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
567
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
545
+ add_index :adverts, [:title], name: :on_title
546
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
547
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
568
548
  EOS
569
549
  )
570
550
 
@@ -579,11 +559,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
579
559
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
580
560
  migrate_up(<<~EOS.strip)
581
561
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
582
-
583
- add_index :adverts, [:title], unique: true, name: 'my_index'
584
-
585
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
586
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
562
+ add_index :adverts, [:title], name: :my_index, unique: true
563
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
564
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
587
565
  EOS
588
566
  )
589
567
 
@@ -598,11 +576,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
598
576
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
599
577
  migrate_up(<<~EOS.strip)
600
578
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
601
-
602
- add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
603
-
604
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
605
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
579
+ add_index :adverts, [:title, :category_id], name: :on_title_and_category_id
580
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
581
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
606
582
  EOS
607
583
  )
608
584
 
@@ -614,7 +590,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
614
590
 
615
591
  ### Rename a table
616
592
 
617
- # The migration generator respects the `set_table_name` declaration, although as before, we need to explicitly tell the generator that we want a rename rather than a create and a drop.
593
+ # The migration generator respects the `set_table_name` declaration, although as before,
594
+ # we need to explicitly tell the generator that we want a rename rather than a create and a drop.
618
595
 
619
596
  class Advert < ActiveRecord::Base
620
597
  self.table_name = "ads"
@@ -630,31 +607,21 @@ RSpec.describe 'DeclareSchema Migration Generator' do
630
607
  expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "ads")).to(
631
608
  migrate_up(<<~EOS.strip)
632
609
  rename_table :adverts, :ads
633
-
634
610
  add_column :ads, :title, :string, limit: 250, null: true#{charset_and_collation}
635
611
  add_column :ads, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
636
-
637
- #{if defined?(SQLite3)
638
- "add_index :ads, [:id], unique: true, name: 'PRIMARY'\n"
639
- elsif defined?(Mysql2)
640
- "execute \"ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
641
- "add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
642
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")"
612
+ #{if defined?(Mysql2)
613
+ "add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
614
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id"
643
615
  end}
644
616
  EOS
645
617
  .and migrate_down(<<~EOS.strip)
646
- remove_column :ads, :title
618
+ #{if defined?(Mysql2)
619
+ "remove_foreign_key :adverts, name: :index_adverts_on_c_id\n" +
620
+ "remove_foreign_key :adverts, name: :index_adverts_on_category_id"
621
+ end}
647
622
  remove_column :ads, :body
648
-
623
+ remove_column :ads, :title
649
624
  rename_table :ads, :adverts
650
-
651
- #{if defined?(SQLite3)
652
- "add_index :adverts, [:id], unique: true, name: 'PRIMARY'\n"
653
- elsif defined?(Mysql2)
654
- "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
655
- "remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" +
656
- "remove_foreign_key(\"adverts\", name: \"on_c_id\")"
657
- end}
658
625
  EOS
659
626
  )
660
627
 
@@ -684,29 +651,15 @@ RSpec.describe 'DeclareSchema Migration Generator' do
684
651
  expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "advertisements")).to(
685
652
  migrate_up(<<~EOS.strip)
686
653
  rename_table :adverts, :advertisements
687
-
688
654
  add_column :advertisements, :title, :string, limit: 250, null: true#{charset_and_collation}
689
655
  add_column :advertisements, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
690
656
  remove_column :advertisements, :name
691
-
692
- #{if defined?(SQLite3)
693
- "add_index :advertisements, [:id], unique: true, name: 'PRIMARY'"
694
- elsif defined?(Mysql2)
695
- "execute \"ALTER TABLE advertisements DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
696
- end}
697
657
  EOS
698
658
  .and migrate_down(<<~EOS.strip)
699
- remove_column :advertisements, :title
659
+ add_column :advertisements, :name, :string, limit: 250, null: true#{charset_and_collation}
700
660
  remove_column :advertisements, :body
701
- add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
702
-
661
+ remove_column :advertisements, :title
703
662
  rename_table :advertisements, :adverts
704
-
705
- #{if defined?(SQLite3)
706
- "add_index :adverts, [:id], unique: true, name: 'PRIMARY'"
707
- elsif defined?(Mysql2)
708
- "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
709
- end}
710
663
  EOS
711
664
  )
712
665
 
@@ -753,13 +706,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
753
706
  expect(migrations).to(
754
707
  migrate_up(<<~EOS.strip)
755
708
  add_column :adverts, :type, :string, limit: 250, null: true#{charset_and_collation}
756
-
757
- add_index :adverts, [:type], name: 'on_type'
709
+ add_index :adverts, [:type], name: :on_type
758
710
  EOS
759
711
  .and migrate_down(<<~EOS.strip)
760
712
  remove_column :adverts, :type
761
-
762
- remove_index :adverts, name: :on_type rescue ActiveRecord::StatementInvalid
713
+ remove_index :adverts, name: :on_type
763
714
  EOS
764
715
  )
765
716
  end
@@ -802,8 +753,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
802
753
  change_column :adverts, :name, :string, limit: 250, null: true, default: "No Name"#{charset_and_collation}
803
754
  EOS
804
755
  .and migrate_down(<<~EOS.strip)
756
+ change_column :adverts, :name, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
805
757
  rename_column :adverts, :name, :title
806
- change_column :adverts, :title, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
807
758
  EOS
808
759
  )
809
760
 
@@ -821,15 +772,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
821
772
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads)).to(
822
773
  migrate_up(<<~EOS.strip)
823
774
  rename_table :adverts, :ads
824
-
825
775
  add_column :ads, :created_at, :datetime, null: false
826
776
  change_column :ads, :title, :string, limit: 250, null: false, default: \"Untitled\"#{charset_and_collation}
827
-
828
- #{if defined?(SQLite3)
829
- "add_index :ads, [:id], unique: true, name: 'PRIMARY'"
830
- elsif defined?(Mysql2)
831
- 'execute "ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)"'
832
- end}
833
777
  EOS
834
778
  )
835
779
 
@@ -856,12 +800,6 @@ RSpec.describe 'DeclareSchema Migration Generator' do
856
800
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { id: :advert_id })).to(
857
801
  migrate_up(<<~EOS.strip)
858
802
  rename_column :adverts, :id, :advert_id
859
-
860
- #{if defined?(SQLite3)
861
- "add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY'"
862
- elsif defined?(Mysql2)
863
- 'execute "ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (advert_id)"'
864
- end}
865
803
  EOS
866
804
  )
867
805
 
@@ -902,6 +840,54 @@ RSpec.describe 'DeclareSchema Migration Generator' do
902
840
  expect(Ad.field_specs['company'].options[:validates].inspect).to eq("{:presence=>true, :uniqueness=>{:case_sensitive=>false}}")
903
841
  end
904
842
 
843
+ context 'models with the same parent foreign key relation' do
844
+ before do
845
+ class Category < ActiveRecord::Base
846
+ fields do
847
+ name :string, limit: 250, null: true
848
+ end
849
+ end
850
+ class Advertiser < ActiveRecord::Base
851
+ fields do
852
+ name :string, limit: 250, null: true
853
+ end
854
+ belongs_to :category, limit: 8
855
+ end
856
+ class Affiliate < ActiveRecord::Base
857
+ fields do
858
+ name :string, limit: 250, null: true
859
+ end
860
+ belongs_to :category, limit: 8
861
+ end
862
+ end
863
+
864
+ it 'will genereate unique constraint names' do
865
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
866
+ migrate_up(<<~EOS.strip)
867
+ create_table :categories, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
868
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
869
+ end
870
+ create_table :advertisers, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
871
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
872
+ t.integer :category_id, limit: 8, null: false
873
+ end
874
+ create_table :affiliates, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
875
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
876
+ t.integer :category_id, limit: 8, null: false
877
+ end
878
+ add_index :advertisers, [:category_id], name: :on_category_id
879
+ add_index :affiliates, [:category_id], name: :on_category_id
880
+ add_foreign_key :advertisers, :categories, column: :category_id, name: :index_advertisers_on_category_id
881
+ add_foreign_key :affiliates, :categories, column: :category_id, name: :index_affiliates_on_category_id
882
+ EOS
883
+ )
884
+ migrate
885
+
886
+ nuke_model_class(Advertiser)
887
+ nuke_model_class(Affiliate)
888
+ end
889
+ end if !defined?(SQLite3) && ActiveRecord::VERSION::MAJOR >= 5
890
+
905
891
  describe 'serialize' do
906
892
  before do
907
893
  class Ad < ActiveRecord::Base
@@ -1086,8 +1072,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1086
1072
  end
1087
1073
  end
1088
1074
 
1089
- context "for Rails #{Rails::VERSION::MAJOR}" do
1090
- if Rails::VERSION::MAJOR >= 5
1075
+ context "for Rails #{ActiveSupport::VERSION::MAJOR}" do
1076
+ if ActiveSupport::VERSION::MAJOR >= 5
1091
1077
  let(:optional_true) { { optional: true } }
1092
1078
  let(:optional_false) { { optional: false } }
1093
1079
  else
@@ -1193,13 +1179,13 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1193
1179
  migration_content = File.read(migrations.first)
1194
1180
  first_line = migration_content.split("\n").first
1195
1181
  base_class = first_line.split(' < ').last
1196
- expect(base_class).to eq("(Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
1182
+ expect(base_class).to eq("(ActiveSupport::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
1197
1183
  end
1198
1184
  end
1199
1185
 
1200
1186
  context 'Does not generate migrations' do
1201
1187
  it 'for aliased fields bigint -> integer limit 8' do
1202
- if Rails::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
1188
+ if ActiveSupport::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
1203
1189
  class Advert < active_record_base_class.constantize
1204
1190
  fields do
1205
1191
  price :bigint
@@ -1211,7 +1197,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1211
1197
  migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
1212
1198
  expect(migrations.size).to eq(1), migrations.inspect
1213
1199
 
1214
- if defined?(Mysql2) && Rails::VERSION::MAJOR < 5
1200
+ if defined?(Mysql2) && ActiveSupport::VERSION::MAJOR < 5
1215
1201
  ActiveRecord::Base.connection.execute("ALTER TABLE adverts ADD PRIMARY KEY (id)")
1216
1202
  end
1217
1203
 
@@ -1252,19 +1238,19 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1252
1238
 
1253
1239
  up, _ = Generators::DeclareSchema::Migration::Migrator.run.tap do |migrations|
1254
1240
  expect(migrations).to(
1255
- migrate_up(<<~EOS.strip)
1256
- create_table :adverts, id: :bigint do |t|
1241
+ migrate_up(<<~EOS.strip)
1242
+ create_table :adverts, id: :bigint#{create_table_charset_and_collation} do |t|
1257
1243
  t.string :name, limit: 250, null: true#{charset_and_collation}
1258
- end#{charset_alter_table}
1259
- EOS
1260
- .and migrate_down("drop_table :adverts")
1244
+ end
1245
+ EOS
1246
+ .and migrate_down("drop_table :adverts")
1261
1247
  )
1262
1248
  end
1263
1249
 
1264
1250
  ActiveRecord::Migration.class_eval(up)
1265
1251
  expect(Advert.columns.map(&:name)).to eq(["id", "name"])
1266
1252
 
1267
- if Rails::VERSION::MAJOR < 5
1253
+ if ActiveSupport::VERSION::MAJOR < 5
1268
1254
  # Rails 4 drivers don't always create PK properly. Fix that by dropping and recreating.
1269
1255
  ActiveRecord::Base.connection.execute("drop table adverts")
1270
1256
  if defined?(Mysql2)
@@ -1286,14 +1272,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1286
1272
  Advert.reset_column_information
1287
1273
 
1288
1274
  expect(migrate).to(
1289
- migrate_up(<<~EOS.strip)
1275
+ migrate_up(<<~EOS.strip)
1290
1276
  add_column :adverts, :body, :text#{text_limit}, null: true#{charset_and_collation}
1291
1277
  add_column :adverts, :published_at, :datetime, null: true
1292
- EOS
1293
- .and migrate_down(<<~EOS.strip)
1294
- remove_column :adverts, :body
1278
+ EOS
1279
+ .and migrate_down(<<~EOS.strip)
1295
1280
  remove_column :adverts, :published_at
1296
- EOS
1281
+ remove_column :adverts, :body
1282
+ EOS
1297
1283
  )
1298
1284
 
1299
1285
  Advert.field_specs.clear # not normally needed
@@ -1319,14 +1305,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1319
1305
  end
1320
1306
 
1321
1307
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1322
- migrate_up(<<~EOS.strip)
1308
+ migrate_up(<<~EOS.strip)
1323
1309
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1324
1310
  remove_column :adverts, :name
1325
- EOS
1326
- .and migrate_down(<<~EOS.strip)
1327
- remove_column :adverts, :title
1311
+ EOS
1312
+ .and migrate_down(<<~EOS.strip)
1328
1313
  add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
1329
- EOS
1314
+ remove_column :adverts, :title
1315
+ EOS
1330
1316
  )
1331
1317
 
1332
1318
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { name: :title })).to(
@@ -1540,20 +1526,16 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1540
1526
  end
1541
1527
 
1542
1528
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1543
- migrate_up(<<~EOS.strip)
1529
+ migrate_up(<<~EOS.strip)
1544
1530
  add_column :adverts, :category_id, :integer, limit: 8, null: false
1545
-
1546
- add_index :adverts, [:category_id], name: 'on_category_id'
1547
-
1548
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" if defined?(Mysql2)}
1549
- EOS
1550
- .and migrate_down(<<~EOS.strip)
1531
+ add_index :adverts, [:category_id], name: :on_category_id
1532
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" if defined?(Mysql2)}
1533
+ EOS
1534
+ .and migrate_down(<<~EOS.strip)
1535
+ #{"remove_foreign_key :adverts, name: :index_adverts_on_category_id" if defined?(Mysql2)}
1536
+ remove_index :adverts, name: :on_category_id
1551
1537
  remove_column :adverts, :category_id
1552
-
1553
- remove_index :adverts, name: :on_category_id rescue ActiveRecord::StatementInvalid
1554
-
1555
- #{"remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" if defined?(Mysql2)}
1556
- EOS
1538
+ EOS
1557
1539
  )
1558
1540
 
1559
1541
  Advert.field_specs.delete(:category_id)
@@ -1568,14 +1550,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1568
1550
  end
1569
1551
 
1570
1552
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1571
- migrate_up(<<~EOS.strip)
1553
+ migrate_up(<<~EOS.strip)
1572
1554
  add_column :adverts, :c_id, :integer, limit: 8, null: false
1573
-
1574
- add_index :adverts, [:c_id], name: 'on_c_id'
1575
-
1576
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1577
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1578
- EOS
1555
+ add_index :adverts, [:c_id], name: :on_c_id
1556
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1557
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1558
+ EOS
1579
1559
  )
1580
1560
 
1581
1561
  Advert.field_specs.delete(:c_id)
@@ -1590,12 +1570,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1590
1570
  end
1591
1571
 
1592
1572
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1593
- migrate_up(<<~EOS.strip)
1573
+ migrate_up(<<~EOS.strip)
1594
1574
  add_column :adverts, :category_id, :integer, limit: 8, null: false
1595
-
1596
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1597
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1598
- EOS
1575
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1576
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1577
+ EOS
1599
1578
  )
1600
1579
 
1601
1580
  Advert.field_specs.delete(:category_id)
@@ -1610,14 +1589,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1610
1589
  end
1611
1590
 
1612
1591
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1613
- migrate_up(<<~EOS.strip)
1592
+ migrate_up(<<~EOS.strip)
1614
1593
  add_column :adverts, :category_id, :integer, limit: 8, null: false
1615
-
1616
- add_index :adverts, [:category_id], name: 'my_index'
1617
-
1618
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1619
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1620
- EOS
1594
+ add_index :adverts, [:category_id], name: :my_index
1595
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1596
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1597
+ EOS
1621
1598
  )
1622
1599
 
1623
1600
  Advert.field_specs.delete(:category_id)
@@ -1636,22 +1613,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1636
1613
  end
1637
1614
 
1638
1615
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1639
- migrate_up(<<~EOS.strip)
1616
+ migrate_up(<<~EOS.strip)
1640
1617
  add_column :adverts, :created_at, :datetime, null: true
1641
1618
  add_column :adverts, :updated_at, :datetime, null: true
1642
1619
  add_column :adverts, :lock_version, :integer#{lock_version_limit}, null: false, default: 1
1643
-
1644
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1645
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1646
- EOS
1647
- .and migrate_down(<<~EOS.strip)
1648
- remove_column :adverts, :created_at
1649
- remove_column :adverts, :updated_at
1620
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1621
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1622
+ EOS
1623
+ .and migrate_down(<<~EOS.strip)
1624
+ #{"remove_foreign_key :adverts, name: :index_adverts_on_c_id\n" +
1625
+ "remove_foreign_key :adverts, name: :index_adverts_on_category_id" if defined?(Mysql2)}
1650
1626
  remove_column :adverts, :lock_version
1651
-
1652
- #{"remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" +
1653
- "remove_foreign_key(\"adverts\", name: \"on_c_id\")" if defined?(Mysql2)}
1654
- EOS
1627
+ remove_column :adverts, :updated_at
1628
+ remove_column :adverts, :created_at
1629
+ EOS
1655
1630
  )
1656
1631
 
1657
1632
  Advert.field_specs.delete(:updated_at)
@@ -1669,14 +1644,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1669
1644
  end
1670
1645
 
1671
1646
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1672
- migrate_up(<<~EOS.strip)
1647
+ migrate_up(<<~EOS.strip)
1673
1648
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1674
-
1675
- add_index :adverts, [:title], name: 'on_title'
1676
-
1677
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1678
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1679
- EOS
1649
+ add_index :adverts, [:title], name: :on_title
1650
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1651
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1652
+ EOS
1680
1653
  )
1681
1654
 
1682
1655
  Advert.index_definitions.delete_if { |spec| spec.fields==["title"] }
@@ -1690,14 +1663,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1690
1663
  end
1691
1664
 
1692
1665
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1693
- migrate_up(<<~EOS.strip)
1666
+ migrate_up(<<~EOS.strip)
1694
1667
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1695
-
1696
- add_index :adverts, [:title], unique: true, name: 'on_title'
1697
-
1698
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1699
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1700
- EOS
1668
+ add_index :adverts, [:title], name: :on_title, unique: true
1669
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1670
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1671
+ EOS
1701
1672
  )
1702
1673
 
1703
1674
  Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
@@ -1711,14 +1682,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1711
1682
  end
1712
1683
 
1713
1684
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1714
- migrate_up(<<~EOS.strip)
1685
+ migrate_up(<<~EOS.strip)
1715
1686
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1716
-
1717
- add_index :adverts, [:title], name: 'my_index'
1718
-
1719
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1720
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1721
- EOS
1687
+ add_index :adverts, [:title], name: :my_index
1688
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1689
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1690
+ EOS
1722
1691
  )
1723
1692
 
1724
1693
  Advert.index_definitions.delete_if { |spec| spec.fields==["title"] }
@@ -1730,14 +1699,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1730
1699
  end
1731
1700
 
1732
1701
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1733
- migrate_up(<<~EOS.strip)
1702
+ migrate_up(<<~EOS.strip)
1734
1703
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1735
-
1736
- add_index :adverts, [:title], name: 'on_title'
1737
-
1738
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1739
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1740
- EOS
1704
+ add_index :adverts, [:title], name: :on_title
1705
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1706
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1707
+ EOS
1741
1708
  )
1742
1709
 
1743
1710
  Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
@@ -1749,14 +1716,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1749
1716
  end
1750
1717
 
1751
1718
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1752
- migrate_up(<<~EOS.strip)
1719
+ migrate_up(<<~EOS.strip)
1753
1720
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1754
-
1755
- add_index :adverts, [:title], unique: true, name: 'my_index'
1756
-
1757
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1758
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1759
- EOS
1721
+ add_index :adverts, [:title], name: :my_index, unique: true
1722
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1723
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1724
+ EOS
1760
1725
  )
1761
1726
 
1762
1727
  Advert.index_definitions.delete_if { |spec| spec.fields == ["title"] }
@@ -1768,14 +1733,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1768
1733
  end
1769
1734
 
1770
1735
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1771
- migrate_up(<<~EOS.strip)
1736
+ migrate_up(<<~EOS.strip)
1772
1737
  add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
1773
-
1774
- add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
1775
-
1776
- #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1777
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")" if defined?(Mysql2)}
1778
- EOS
1738
+ add_index :adverts, [:title, :category_id], name: :on_title_and_category_id
1739
+ #{"add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1740
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id" if defined?(Mysql2)}
1741
+ EOS
1779
1742
  )
1780
1743
 
1781
1744
  Advert.index_definitions.delete_if { |spec| spec.fields==["title", "category_id"] }
@@ -1800,34 +1763,24 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1800
1763
  Advert.reset_column_information
1801
1764
 
1802
1765
  expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "ads")).to(
1803
- migrate_up(<<~EOS.strip)
1766
+ migrate_up(<<~EOS.strip)
1804
1767
  rename_table :adverts, :ads
1805
-
1806
1768
  add_column :ads, :title, :string, limit: 250, null: true#{charset_and_collation}
1807
1769
  add_column :ads, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
1808
-
1809
- #{if defined?(SQLite3)
1810
- "add_index :ads, [:id], unique: true, name: 'PRIMARY'\n"
1811
- elsif defined?(Mysql2)
1812
- "execute \"ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
1813
- "add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"on_category_id\")\n" +
1814
- "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"on_c_id\")"
1770
+ #{if defined?(Mysql2)
1771
+ "add_foreign_key :adverts, :categories, column: :category_id, name: :index_adverts_on_category_id\n" +
1772
+ "add_foreign_key :adverts, :categories, column: :c_id, name: :index_adverts_on_c_id"
1815
1773
  end}
1816
1774
  EOS
1817
- .and migrate_down(<<~EOS.strip)
1818
- remove_column :ads, :title
1819
- remove_column :ads, :body
1820
-
1821
- rename_table :ads, :adverts
1822
-
1823
- #{if defined?(SQLite3)
1824
- "add_index :adverts, [:id], unique: true, name: 'PRIMARY'\n"
1825
- elsif defined?(Mysql2)
1826
- "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
1827
- "remove_foreign_key(\"adverts\", name: \"on_category_id\")\n" +
1828
- "remove_foreign_key(\"adverts\", name: \"on_c_id\")"
1829
- end}
1830
- EOS
1775
+ .and migrate_down(<<~EOS.strip)
1776
+ #{if defined?(Mysql2)
1777
+ "remove_foreign_key :adverts, name: :index_adverts_on_c_id\n" +
1778
+ "remove_foreign_key :adverts, name: :index_adverts_on_category_id"
1779
+ end}
1780
+ remove_column :ads, :body
1781
+ remove_column :ads, :title
1782
+ rename_table :ads, :adverts
1783
+ EOS
1831
1784
  )
1832
1785
 
1833
1786
  # Set the table name back to what it should be and confirm we're in sync:
@@ -1854,32 +1807,18 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1854
1807
  end
1855
1808
 
1856
1809
  expect(Generators::DeclareSchema::Migration::Migrator.run("adverts" => "advertisements")).to(
1857
- migrate_up(<<~EOS.strip)
1810
+ migrate_up(<<~EOS.strip)
1858
1811
  rename_table :adverts, :advertisements
1859
-
1860
1812
  add_column :advertisements, :title, :string, limit: 250, null: true#{charset_and_collation}
1861
1813
  add_column :advertisements, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
1862
1814
  remove_column :advertisements, :name
1863
-
1864
- #{if defined?(SQLite3)
1865
- "add_index :advertisements, [:id], unique: true, name: 'PRIMARY'"
1866
- elsif defined?(Mysql2)
1867
- "execute \"ALTER TABLE advertisements DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
1868
- end}
1869
- EOS
1870
- .and migrate_down(<<~EOS.strip)
1871
- remove_column :advertisements, :title
1815
+ EOS
1816
+ .and migrate_down(<<~EOS.strip)
1817
+ add_column :advertisements, :name, :string, limit: 250, null: true#{charset_and_collation}
1872
1818
  remove_column :advertisements, :body
1873
- add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
1874
-
1819
+ remove_column :advertisements, :title
1875
1820
  rename_table :advertisements, :adverts
1876
-
1877
- #{if defined?(SQLite3)
1878
- "add_index :adverts, [:id], unique: true, name: 'PRIMARY'"
1879
- elsif defined?(Mysql2)
1880
- "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
1881
- end}
1882
- EOS
1821
+ EOS
1883
1822
  )
1884
1823
 
1885
1824
  ### Drop a table
@@ -1891,14 +1830,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1891
1830
  # Dropping tables is where the automatic down-migration really comes in handy:
1892
1831
 
1893
1832
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
1894
- migrate_up(<<~EOS.strip)
1833
+ migrate_up(<<~EOS.strip)
1895
1834
  drop_table :adverts
1896
- EOS
1897
- .and migrate_down(<<~EOS.strip)
1835
+ EOS
1836
+ .and migrate_down(<<~EOS.strip)
1898
1837
  create_table "adverts"#{table_options}, force: :cascade do |t|
1899
1838
  t.string "name", limit: 250#{charset_and_collation}
1900
1839
  end
1901
- EOS
1840
+ EOS
1902
1841
  )
1903
1842
 
1904
1843
  ## STI
@@ -1923,16 +1862,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1923
1862
 
1924
1863
  up, _ = Generators::DeclareSchema::Migration::Migrator.run do |migrations|
1925
1864
  expect(migrations).to(
1926
- migrate_up(<<~EOS.strip)
1865
+ migrate_up(<<~EOS.strip)
1927
1866
  add_column :adverts, :type, :string, limit: 250, null: true#{charset_and_collation}
1928
-
1929
- add_index :adverts, [:type], name: 'on_type'
1930
- EOS
1931
- .and migrate_down(<<~EOS.strip)
1867
+ add_index :adverts, [:type], name: :on_type
1868
+ EOS
1869
+ .and migrate_down(<<~EOS.strip)
1870
+ remove_index :adverts, name: :on_type
1932
1871
  remove_column :adverts, :type
1933
-
1934
- remove_index :adverts, name: :on_type rescue ActiveRecord::StatementInvalid
1935
- EOS
1872
+ EOS
1936
1873
  )
1937
1874
  end
1938
1875
 
@@ -1969,14 +1906,14 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1969
1906
  end
1970
1907
 
1971
1908
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { title: :name })).to(
1972
- migrate_up(<<~EOS.strip)
1909
+ migrate_up(<<~EOS.strip)
1973
1910
  rename_column :adverts, :title, :name
1974
1911
  change_column :adverts, :name, :string, limit: 250, null: true, default: "No Name"#{charset_and_collation}
1975
- EOS
1976
- .and migrate_down(<<~EOS.strip)
1912
+ EOS
1913
+ .and migrate_down(<<~EOS.strip)
1914
+ change_column :adverts, :name, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
1977
1915
  rename_column :adverts, :name, :title
1978
- change_column :adverts, :title, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
1979
- EOS
1916
+ EOS
1980
1917
  )
1981
1918
 
1982
1919
  ### Rename a table and add a column
@@ -1991,18 +1928,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1991
1928
  end
1992
1929
 
1993
1930
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: :ads)).to(
1994
- migrate_up(<<~EOS.strip)
1931
+ migrate_up(<<~EOS.strip)
1995
1932
  rename_table :adverts, :ads
1996
-
1997
1933
  add_column :ads, :created_at, :datetime, null: false
1998
1934
  change_column :ads, :title, :string, limit: 250, null: false, default: \"Untitled\"#{charset_and_collation}
1999
-
2000
- #{if defined?(SQLite3)
2001
- "add_index :ads, [:id], unique: true, name: 'PRIMARY'"
2002
- elsif defined?(Mysql2)
2003
- 'execute "ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)"'
2004
- end}
2005
- EOS
1935
+ EOS
2006
1936
  )
2007
1937
 
2008
1938
  class Advert < ActiveRecord::Base
@@ -2026,15 +1956,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2026
1956
  end
2027
1957
 
2028
1958
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { id: :advert_id })).to(
2029
- migrate_up(<<~EOS.strip)
1959
+ migrate_up(<<~EOS.strip)
2030
1960
  rename_column :adverts, :id, :advert_id
2031
-
2032
- #{if defined?(SQLite3)
2033
- "add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY'"
2034
- elsif defined?(Mysql2)
2035
- 'execute "ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (advert_id)"'
2036
- end}
2037
- EOS
1961
+ EOS
2038
1962
  )
2039
1963
 
2040
1964
  nuke_model_class(Advert)
@@ -2074,6 +1998,54 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2074
1998
  expect(Ad.field_specs['company'].options[:validates].inspect).to eq("{:presence=>true, :uniqueness=>{:case_sensitive=>false}}")
2075
1999
  end
2076
2000
 
2001
+ context 'models with the same parent foreign key relation' do
2002
+ before do
2003
+ class Category < ActiveRecord::Base
2004
+ fields do
2005
+ name :string, limit: 250, null: true
2006
+ end
2007
+ end
2008
+ class Advertiser < ActiveRecord::Base
2009
+ fields do
2010
+ name :string, limit: 250, null: true
2011
+ end
2012
+ belongs_to :category, limit: 8
2013
+ end
2014
+ class Affiliate < ActiveRecord::Base
2015
+ fields do
2016
+ name :string, limit: 250, null: true
2017
+ end
2018
+ belongs_to :category, limit: 8
2019
+ end
2020
+ end
2021
+
2022
+ it 'will genereate unique constraint names' do
2023
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
2024
+ migrate_up(<<~EOS.strip)
2025
+ create_table :categories, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
2026
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
2027
+ end
2028
+ create_table :advertisers, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
2029
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
2030
+ t.integer :category_id, limit: 8, null: false
2031
+ end
2032
+ create_table :affiliates, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin" do |t|
2033
+ t.string :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
2034
+ t.integer :category_id, limit: 8, null: false
2035
+ end
2036
+ add_index :advertisers, [:category_id], name: :on_category_id
2037
+ add_index :affiliates, [:category_id], name: :on_category_id
2038
+ add_foreign_key :advertisers, :categories, column: :category_id, name: :index_advertisers_on_category_id
2039
+ add_foreign_key :affiliates, :categories, column: :category_id, name: :index_affiliates_on_category_id
2040
+ EOS
2041
+ )
2042
+ migrate
2043
+
2044
+ nuke_model_class(Advertiser)
2045
+ nuke_model_class(Affiliate)
2046
+ end
2047
+ end if !defined?(SQLite3) && ActiveRecord::VERSION::MAJOR >= 5
2048
+
2077
2049
  describe 'serialize' do
2078
2050
  before do
2079
2051
  class Ad < ActiveRecord::Base
@@ -2258,8 +2230,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2258
2230
  end
2259
2231
  end
2260
2232
 
2261
- context "for Rails #{Rails::VERSION::MAJOR}" do
2262
- if Rails::VERSION::MAJOR >= 5
2233
+ context "for Rails #{ActiveSupport::VERSION::MAJOR}" do
2234
+ if ActiveSupport::VERSION::MAJOR >= 5
2263
2235
  let(:optional_true) { { optional: true } }
2264
2236
  let(:optional_false) { { optional: false } }
2265
2237
  else
@@ -2269,80 +2241,202 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2269
2241
  let(:optional_flag) { { false => optional_false, true => optional_true } }
2270
2242
 
2271
2243
  describe 'belongs_to' do
2272
- before do
2273
- unless defined?(AdCategory)
2274
- class AdCategory < ActiveRecord::Base
2275
- declare_schema { }
2244
+ context 'with AdCategory and Advert in DB' do
2245
+ before do
2246
+ unless defined?(AdCategory)
2247
+ class AdCategory < ActiveRecord::Base
2248
+ declare_schema { }
2249
+ end
2276
2250
  end
2277
- end
2278
2251
 
2279
- class Advert < ActiveRecord::Base
2280
- declare_schema do
2281
- string :name, limit: 250, null: true
2282
- integer :category_id, limit: 8
2283
- integer :nullable_category_id, limit: 8, null: true
2252
+ class Advert < ActiveRecord::Base
2253
+ declare_schema do
2254
+ string :name, limit: 250, null: true
2255
+ integer :category_id, limit: 8
2256
+ integer :nullable_category_id, limit: 8, null: true
2257
+ end
2284
2258
  end
2259
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2260
+ ActiveRecord::Migration.class_eval(up)
2285
2261
  end
2286
- up = Generators::DeclareSchema::Migration::Migrator.run.first
2287
- ActiveRecord::Migration.class_eval(up)
2288
- end
2289
2262
 
2290
- it 'passes through optional: when given' do
2291
- class AdvertBelongsTo < ActiveRecord::Base
2292
- self.table_name = 'adverts'
2293
- declare_schema { }
2294
- reset_column_information
2295
- belongs_to :ad_category, optional: true
2296
- end
2297
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2298
- end
2299
-
2300
- describe 'contradictory settings' do # contradictory settings are ok--for example, during migration
2301
- it 'passes through optional: true, null: false' do
2263
+ it 'passes through optional: when given' do
2302
2264
  class AdvertBelongsTo < ActiveRecord::Base
2303
2265
  self.table_name = 'adverts'
2304
2266
  declare_schema { }
2305
2267
  reset_column_information
2306
- belongs_to :ad_category, optional: true, null: false
2268
+ belongs_to :ad_category, optional: true
2307
2269
  end
2308
2270
  expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2309
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
2310
2271
  end
2311
2272
 
2312
- it 'passes through optional: false, null: true' do
2313
- class AdvertBelongsTo < ActiveRecord::Base
2314
- self.table_name = 'adverts'
2315
- declare_schema { }
2316
- reset_column_information
2317
- belongs_to :ad_category, optional: false, null: true
2273
+ describe 'contradictory settings' do # contradictory settings are ok--for example, during migration
2274
+ it 'passes through optional: true, null: false' do
2275
+ class AdvertBelongsTo < ActiveRecord::Base
2276
+ self.table_name = 'adverts'
2277
+ declare_schema { }
2278
+ reset_column_information
2279
+ belongs_to :ad_category, optional: true, null: false
2280
+ end
2281
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_true)
2282
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(false)
2318
2283
  end
2319
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_false)
2320
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
2284
+
2285
+ it 'passes through optional: false, null: true' do
2286
+ class AdvertBelongsTo < ActiveRecord::Base
2287
+ self.table_name = 'adverts'
2288
+ declare_schema { }
2289
+ reset_column_information
2290
+ belongs_to :ad_category, optional: false, null: true
2291
+ end
2292
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_false)
2293
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(true)
2294
+ end
2295
+ end
2296
+
2297
+ [false, true].each do |nullable|
2298
+ context "nullable=#{nullable}" do
2299
+ it 'infers optional: from null:' do
2300
+ eval <<~EOS
2301
+ class AdvertBelongsTo < ActiveRecord::Base
2302
+ declare_schema { }
2303
+ belongs_to :ad_category, null: #{nullable}
2304
+ end
2305
+ EOS
2306
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2307
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2308
+ end
2309
+
2310
+ it 'infers null: from optional:' do
2311
+ eval <<~EOS
2312
+ class AdvertBelongsTo < ActiveRecord::Base
2313
+ declare_schema { }
2314
+ belongs_to :ad_category, optional: #{nullable}
2315
+ end
2316
+ EOS
2317
+ expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2318
+ expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2319
+ end
2320
+ end
2321
+ end
2322
+
2323
+ it 'deprecates limit:' do
2324
+ expect(ActiveSupport::Deprecation).to receive(:warn).with("belongs_to limit: is deprecated since it is now inferred")
2325
+ eval <<~EOS
2326
+ class UsingLimit < ActiveRecord::Base
2327
+ declare_schema { }
2328
+ belongs_to :ad_category, limit: 4
2329
+ end
2330
+ EOS
2321
2331
  end
2322
2332
  end
2323
2333
 
2324
- [false, true].each do |nullable|
2325
- context "nullable=#{nullable}" do
2326
- it 'infers optional: from null:' do
2327
- eval <<~EOS
2328
- class AdvertBelongsTo < ActiveRecord::Base
2329
- declare_schema { }
2330
- belongs_to :ad_category, null: #{nullable}
2331
- end
2332
- EOS
2333
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2334
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2334
+ context 'when parent object PKs have different limits' do
2335
+ before do
2336
+ class IdDefault < ActiveRecord::Base
2337
+ declare_schema { }
2338
+ end
2339
+ class Id4 < ActiveRecord::Base
2340
+ declare_schema id: :integer do
2341
+ end
2335
2342
  end
2343
+ class Id8 < ActiveRecord::Base
2344
+ declare_schema id: :bigint do
2345
+ end
2346
+ end
2347
+ class Fk < ActiveRecord::Base
2348
+ declare_schema { }
2349
+ belongs_to :id_default, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2350
+ belongs_to :id4, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2351
+ belongs_to :id8, (ActiveSupport::VERSION::MAJOR < 5 ? { constraint: false } : {})
2352
+ end
2353
+ end
2336
2354
 
2337
- it 'infers null: from optional:' do
2338
- eval <<~EOS
2339
- class AdvertBelongsTo < ActiveRecord::Base
2340
- declare_schema { }
2341
- belongs_to :ad_category, optional: #{nullable}
2342
- end
2343
- EOS
2344
- expect(AdvertBelongsTo.reflections['ad_category'].options).to eq(optional_flag[nullable])
2345
- expect(AdvertBelongsTo.field_specs['ad_category_id'].options&.[](:null)).to eq(nullable)
2355
+ it 'creates the proper PKs' do
2356
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2357
+
2358
+ create_id4_defaults = up.split("\n").grep(/create_table :id_defaults/).first
2359
+ expect(create_id4_defaults).to be, up
2360
+ expect(create_id4_defaults).to match(/, id: :bigint/)
2361
+
2362
+ create_id4s = up.split("\n").grep(/create_table :id4s/).first
2363
+ expect(create_id4s).to be, up
2364
+ expect(create_id4s).to match(/, id: :integer/)
2365
+
2366
+ create_id8s = up.split("\n").grep(/create_table :id8s/).first
2367
+ expect(create_id8s).to be, up
2368
+ expect(create_id8s).to match(/, id: :bigint/)
2369
+ end
2370
+
2371
+ it 'infers the correct FK type from the create_table id: type' do
2372
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2373
+
2374
+ create_fks = up.split("\n").grep(/t\.integer /).map { |command| command.gsub(', null: false', '').gsub(/^ +/, '') }
2375
+ if defined?(SQLite3)
2376
+ create_fks.map! { |command| command.gsub(/limit: [a-z0-9]+/, 'limit: X') }
2377
+ expect(create_fks).to eq([
2378
+ 't.integer :id_default_id, limit: X',
2379
+ 't.integer :id4_id, limit: X',
2380
+ 't.integer :id8_id, limit: X'
2381
+ ]), up
2382
+ else
2383
+ expect(create_fks).to eq([
2384
+ 't.integer :id_default_id, limit: 8',
2385
+ 't.integer :id4_id, limit: 4',
2386
+ 't.integer :id8_id, limit: 8'
2387
+ ]), up
2388
+ end
2389
+ end
2390
+
2391
+ context "when parent objects were migrated before and later definitions don't have explicit id:" do
2392
+ before do
2393
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2394
+ ActiveRecord::Migration.class_eval up
2395
+ nuke_model_class(IdDefault)
2396
+ nuke_model_class(Id4)
2397
+ nuke_model_class(Id8)
2398
+ nuke_model_class(Fk)
2399
+ ActiveRecord::Base.connection.schema_cache.clear!
2400
+
2401
+
2402
+ class NewIdDefault < ActiveRecord::Base
2403
+ self.table_name = 'id_defaults'
2404
+ declare_schema { }
2405
+ end
2406
+ class NewId4 < ActiveRecord::Base
2407
+ self.table_name = 'id4s'
2408
+ declare_schema { }
2409
+ end
2410
+ class NewId8 < ActiveRecord::Base
2411
+ self.table_name = 'id8s'
2412
+ declare_schema { }
2413
+ end
2414
+ class NewFk < ActiveRecord::Base
2415
+ declare_schema { }
2416
+ belongs_to :new_id_default
2417
+ belongs_to :new_id4
2418
+ belongs_to :new_id8
2419
+ end
2420
+ end
2421
+
2422
+ it 'infers the correct FK :integer limit: ' do
2423
+ up = Generators::DeclareSchema::Migration::Migrator.run.first
2424
+
2425
+ create_fks = up.split("\n").grep(/t\.integer /).map { |command| command.gsub(', null: false', '').gsub(/^ +/, '') }
2426
+ if defined?(SQLite3)
2427
+ create_fks.map! { |command| command.gsub(/limit: [a-z0-9]+/, 'limit: X') }
2428
+ expect(create_fks).to eq([
2429
+ 't.integer :new_id_default_id, limit: X',
2430
+ 't.integer :new_id4_id, limit: X',
2431
+ 't.integer :new_id8_id, limit: X'
2432
+ ]), up
2433
+ else
2434
+ expect(create_fks).to eq([
2435
+ 't.integer :new_id_default_id, limit: 8',
2436
+ 't.integer :new_id4_id, limit: 4',
2437
+ 't.integer :new_id8_id, limit: 8'
2438
+ ]), up
2439
+ end
2346
2440
  end
2347
2441
  end
2348
2442
  end
@@ -2365,13 +2459,13 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2365
2459
  migration_content = File.read(migrations.first)
2366
2460
  first_line = migration_content.split("\n").first
2367
2461
  base_class = first_line.split(' < ').last
2368
- expect(base_class).to eq("(Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
2462
+ expect(base_class).to eq("(ActiveSupport::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
2369
2463
  end
2370
2464
  end
2371
2465
 
2372
2466
  context 'Does not generate migrations' do
2373
2467
  it 'for aliased fields bigint -> integer limit 8' do
2374
- if Rails::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
2468
+ if ActiveSupport::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
2375
2469
  class Advert < active_record_base_class.constantize
2376
2470
  declare_schema do
2377
2471
  bigint :price
@@ -2383,7 +2477,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
2383
2477
  migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
2384
2478
  expect(migrations.size).to eq(1), migrations.inspect
2385
2479
 
2386
- if defined?(Mysql2) && Rails::VERSION::MAJOR < 5
2480
+ if defined?(Mysql2) && ActiveSupport::VERSION::MAJOR < 5
2387
2481
  ActiveRecord::Base.connection.execute("ALTER TABLE adverts ADD PRIMARY KEY (id)")
2388
2482
  end
2389
2483