declare_schema 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/declare_schema_build.yml +21 -5
  3. data/Appraisals +21 -4
  4. data/CHANGELOG.md +40 -0
  5. data/Gemfile +1 -2
  6. data/Gemfile.lock +7 -9
  7. data/README.md +3 -3
  8. data/Rakefile +17 -4
  9. data/bin/declare_schema +1 -1
  10. data/declare_schema.gemspec +1 -1
  11. data/gemfiles/rails_4_mysql.gemfile +22 -0
  12. data/gemfiles/{rails_4.gemfile → rails_4_sqlite.gemfile} +1 -2
  13. data/gemfiles/rails_5_mysql.gemfile +22 -0
  14. data/gemfiles/{rails_5.gemfile → rails_5_sqlite.gemfile} +1 -2
  15. data/gemfiles/rails_6_mysql.gemfile +22 -0
  16. data/gemfiles/{rails_6.gemfile → rails_6_sqlite.gemfile} +2 -3
  17. data/lib/declare_schema/command.rb +10 -3
  18. data/lib/declare_schema/model/column.rb +168 -0
  19. data/lib/declare_schema/model/field_spec.rb +59 -143
  20. data/lib/declare_schema/model/foreign_key_definition.rb +36 -25
  21. data/lib/declare_schema/model/table_options_definition.rb +8 -6
  22. data/lib/declare_schema/version.rb +1 -1
  23. data/lib/generators/declare_schema/migration/migration_generator.rb +1 -1
  24. data/lib/generators/declare_schema/migration/migrator.rb +142 -116
  25. data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +1 -1
  26. data/spec/lib/declare_schema/field_spec_spec.rb +135 -38
  27. data/spec/lib/declare_schema/generator_spec.rb +4 -2
  28. data/spec/lib/declare_schema/interactive_primary_key_spec.rb +8 -2
  29. data/spec/lib/declare_schema/migration_generator_spec.rb +277 -171
  30. data/spec/lib/declare_schema/model/column_spec.rb +141 -0
  31. data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +93 -0
  32. data/spec/lib/declare_schema/model/index_definition_spec.rb +4 -5
  33. data/spec/lib/declare_schema/model/table_options_definition_spec.rb +19 -29
  34. data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +12 -26
  35. data/spec/support/acceptance_spec_helpers.rb +3 -3
  36. metadata +15 -9
@@ -25,7 +25,7 @@ RSpec.describe DeclareSchema::FieldDeclarationDsl do
25
25
  end
26
26
 
27
27
  it 'stores limits' do
28
- expect(TestModel.field_specs['name'].limit).to eq(127)
28
+ expect(TestModel.field_specs['name'].limit).to eq(127), TestModel.field_specs['name'].inspect
29
29
  end
30
30
 
31
31
  # TODO: fill out remaining tests
@@ -1,69 +1,166 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe 'DeclareSchema Model FieldSpec' do
3
+ begin
4
+ require 'mysql2'
5
+ rescue LoadError
6
+ end
7
+
8
+ RSpec.describe DeclareSchema::Model::FieldSpec do
9
+ let(:model) { double('model', table_options: {}) }
10
+ let(:col_spec) { double('col_spec', sql_type: 'varchar') }
11
+
4
12
  before do
5
13
  load File.expand_path('prepare_testapp.rb', __dir__)
14
+
15
+ if Rails::VERSION::MAJOR < 5
16
+ allow(col_spec).to receive(:type_cast_from_database, &:itself)
17
+ end
6
18
  end
7
19
 
8
- context 'There are no model columns to change' do
9
- it '#different_to should return false for int8 == int8' do
10
- subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
20
+ describe '#initialize' do
21
+ it 'normalizes option order' do
22
+ subject = described_class.new(model, :price, :integer, anonymize_using: 'x', null: false, position: 0, limit: 4)
23
+ expect(subject.options.keys).to eq([:limit, :null, :anonymize_using])
24
+ end
25
+ end
11
26
 
12
- case Rails::VERSION::MAJOR
13
- when 4
14
- cast_type = ActiveRecord::Type::Integer.new(limit: 8)
15
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
16
- else
17
- sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
18
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
27
+ describe '#schema_attributes' do
28
+ describe 'integer 4' do
29
+ it 'returns schema attributes' do
30
+ subject = described_class.new(model, :price, :integer, limit: 4, null: false, position: 0)
31
+ expect(subject.schema_attributes(col_spec)).to eq(type: :integer, limit: 4, null: false)
19
32
  end
20
-
21
- expect(subject.different_to?(subject.name, col)).to eq(false)
22
33
  end
23
34
 
24
- it '#different_to should return false for bigint == bigint' do
25
- subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
35
+ describe 'integer 8' do
36
+ it 'returns schema attributes' do
37
+ subject = described_class.new(model, :price, :integer, limit: 8, null: true, position: 2)
38
+ expect(subject.schema_attributes(col_spec)).to eq(type: :integer, limit: 8, null: true)
39
+ end
40
+ end
26
41
 
27
- case Rails::VERSION::MAJOR
28
- when 4
29
- cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
30
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
31
- else
32
- sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
33
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
42
+ describe 'bigint' do
43
+ it 'returns schema attributes' do
44
+ subject = described_class.new(model, :price, :bigint, null: false, position: 2)
45
+ expect(subject.schema_attributes(col_spec)).to eq(type: :integer, limit: 8, null: false)
34
46
  end
47
+ end
35
48
 
36
- expect(subject.different_to?(subject.name, col)).to eq(false)
49
+ describe 'string' do
50
+ it 'returns schema attributes (including charset/collation iff mysql)' do
51
+ subject = described_class.new(model, :title, :string, limit: 100, null: true, charset: 'utf8mb4', position: 0)
52
+ if defined?(Mysql2)
53
+ expect(subject.schema_attributes(col_spec)).to eq(type: :string, limit: 100, null: true, charset: 'utf8mb4', collation: 'utf8mb4_bin')
54
+ else
55
+ expect(subject.schema_attributes(col_spec)).to eq(type: :string, limit: 100, null: true)
56
+ end
57
+ end
37
58
  end
38
59
 
39
- it '#different_to should return false for int8 == bigint' do
40
- subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
60
+ describe 'text' do
61
+ it 'returns schema attributes (including charset/collation iff mysql)' do
62
+ subject = described_class.new(model, :title, :text, limit: 200, null: true, charset: 'utf8mb4', position: 2)
63
+ if defined?(Mysql2)
64
+ expect(subject.schema_attributes(col_spec)).to eq(type: :text, limit: 255, null: true, charset: 'utf8mb4', collation: 'utf8mb4_bin')
65
+ else
66
+ expect(subject.schema_attributes(col_spec)).to eq(type: :text, null: true)
67
+ end
68
+ end
41
69
 
42
- case Rails::VERSION::MAJOR
43
- when 4
44
- cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
45
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
46
- else
47
- sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
48
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
70
+ it 'allows a default to be set unless mysql' do
71
+ if defined?(Mysql2)
72
+ expect do
73
+ described_class.new(model, :title, :text, limit: 200, null: true, default: 'none', charset: 'utf8mb4', position: 2)
74
+ end.to raise_exception(DeclareSchema::MysqlTextMayNotHaveDefault)
75
+ else
76
+ subject = described_class.new(model, :title, :text, limit: 200, null: true, default: 'none', charset: 'utf8mb4', position: 2)
77
+ expect(subject.schema_attributes(col_spec)).to eq(type: :text, null: true, default: 'none')
78
+ end
79
+ end
80
+
81
+ describe 'decimal' do
82
+ it 'allows precision: and scale:' do
83
+ subject = described_class.new(model, :quantity, :decimal, precision: 8, scale: 10, null: true, position: 3)
84
+ expect(subject.schema_attributes(col_spec)).to eq(type: :decimal, precision: 8, scale: 10, null: true)
85
+ end
86
+
87
+ it 'requires precision:' do
88
+ expect_any_instance_of(described_class).to receive(:warn).with(/precision: required for :decimal type/)
89
+ described_class.new(model, :quantity, :decimal, scale: 10, null: true, position: 3)
90
+ end
91
+
92
+ it 'requires scale:' do
93
+ expect_any_instance_of(described_class).to receive(:warn).with(/scale: required for :decimal type/)
94
+ described_class.new(model, :quantity, :decimal, precision: 8, null: true, position: 3)
95
+ end
96
+ end
97
+
98
+ [:integer, :bigint, :string, :text, :binary, :datetime, :date, :time].each do |t|
99
+ describe t.to_s do
100
+ let(:extra) { t == :string ? { limit: 100 } : {} }
101
+
102
+ it 'does not allow precision:' do
103
+ expect_any_instance_of(described_class).to receive(:warn).with(/precision: only allowed for :decimal type/)
104
+ described_class.new(model, :quantity, t, { precision: 8, null: true, position: 3 }.merge(extra))
105
+ end unless t == :datetime
106
+
107
+ it 'does not allow scale:' do
108
+ expect_any_instance_of(described_class).to receive(:warn).with(/scale: only allowed for :decimal type/)
109
+ described_class.new(model, :quantity, t, { scale: 10, null: true, position: 3 }.merge(extra))
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ describe 'datetime' do
116
+ it 'keeps type as "datetime"' do
117
+ subject = described_class.new(model, :created_at, :datetime, null: false, position: 1)
118
+ expect(subject.schema_attributes(col_spec)).to eq(type: :datetime, null: false)
49
119
  end
120
+ end
50
121
 
51
- expect(subject.different_to?(subject.name, col)).to eq(false)
122
+ describe 'timestamp' do
123
+ it 'normalizes type to "datetime"' do
124
+ subject = described_class.new(model, :created_at, :timestamp, null: true, position: 2)
125
+ expect(subject.schema_attributes(col_spec)).to eq(type: :datetime, null: true)
126
+ end
52
127
  end
53
128
 
54
- it '#different_to should return false for bigint == int8' do
55
- subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
129
+ describe 'default:' do
130
+ let(:col_spec) { double('col_spec', sql_type: :integer) }
56
131
 
132
+ it 'typecasts default value' do
133
+ allow(col_spec).to receive(:type_cast_from_database) { |default| Integer(default) }
134
+ subject = described_class.new(model, :price, :integer, limit: 4, default: '42', null: true, position: 2)
135
+ expect(subject.schema_attributes(col_spec)).to eq(type: :integer, limit: 4, default: 42, null: true)
136
+ end
137
+ end
138
+ end
139
+
140
+ describe '#schema_attributes' do
141
+ let(:col_spec) do
57
142
  case Rails::VERSION::MAJOR
58
143
  when 4
59
144
  cast_type = ActiveRecord::Type::Integer.new(limit: 8)
60
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
145
+ ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
61
146
  else
62
147
  sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
63
- col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
148
+ ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
64
149
  end
150
+ end
151
+
152
+ it 'returns the attributes except name, position' do
153
+ subject = described_class.new(model, :price, :bigint, null: true, default: 0, position: 2)
154
+ expect(subject.schema_attributes(col_spec)).to eq(type: :integer, limit: 8, null: true, default: 0)
155
+ end
156
+
157
+ it 'aliases :bigint and :integer limit: 8' do
158
+ int8 = described_class.new(model, :price, :integer, limit: 8, null: false, position: 0)
159
+ bigint = described_class.new(model, :price, :bigint, null: false, position: 0)
65
160
 
66
- expect(subject.different_to?(subject.name, col)).to eq(false)
161
+ expected_attributes = { type: :integer, limit: 8, null: false }
162
+ expect(int8.schema_attributes(col_spec)).to eq(expected_attributes)
163
+ expect(bigint.schema_attributes(col_spec)).to eq(expected_attributes)
67
164
  end
68
165
  end
69
166
  end
@@ -30,7 +30,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
30
30
  case Rails::VERSION::MAJOR
31
31
  when 4, 5
32
32
  expect_test_definition_to_eq('alpha/beta', <<~EOS)
33
- require 'test_helper'
33
+ require "test_helper"
34
34
 
35
35
  class Alpha::BetaTest < ActiveSupport::TestCase
36
36
  # test "the truth" do
@@ -101,7 +101,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
101
101
 
102
102
  expect(File.exist?('db/schema.rb')).to be_truthy
103
103
 
104
- expect(File.exist?("db/development.sqlite3") || File.exist?("db/test.sqlite3")).to be_truthy
104
+ if defined?(SQLite3)
105
+ expect(File.exist?("db/development.sqlite3") || File.exist?("db/test.sqlite3")).to be_truthy
106
+ end
105
107
 
106
108
  module Alpha; end
107
109
  require 'alpha/beta'
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails'
4
+ begin
5
+ require 'mysql2'
6
+ rescue LoadError
7
+ end
8
+
3
9
  RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
4
10
  before do
5
11
  load File.expand_path('prepare_testapp.rb', __dir__)
@@ -31,8 +37,8 @@ RSpec.describe 'DeclareSchema Migration Generator interactive primary key' do
31
37
 
32
38
  ### migrate to
33
39
 
34
- if Rails::VERSION::MAJOR >= 5
35
- # rename to custom primary_key
40
+ if Rails::VERSION::MAJOR >= 5 && !defined?(Mysql2) # TODO TECH-4814 Put this test back for Mysql2
41
+ # replace custom primary_key
36
42
  class Foo < ActiveRecord::Base
37
43
  fields do
38
44
  end
@@ -1,12 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rails'
4
+ begin
5
+ require 'mysql2'
6
+ rescue LoadError
7
+ end
4
8
 
5
9
  RSpec.describe 'DeclareSchema Migration Generator' do
6
10
  before do
7
11
  load File.expand_path('prepare_testapp.rb', __dir__)
8
12
  end
9
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
+ let(:text_limit) do
24
+ if defined?(Mysql2)
25
+ ", limit: 4294967295"
26
+ end
27
+ end
28
+ let(:charset_and_collation) do
29
+ if defined?(Mysql2)
30
+ ', charset: "utf8mb4", collation: "utf8mb4_bin"'
31
+ end
32
+ end
33
+ let(:datetime_precision) do
34
+ if defined?(Mysql2) && Rails::VERSION::MAJOR >= 5
35
+ ', precision: 0'
36
+ end
37
+ end
38
+ let(:table_options) do
39
+ if defined?(Mysql2)
40
+ ", options: \"#{'ENGINE=InnoDB ' if Rails::VERSION::MAJOR == 5}DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\"" +
41
+ if Rails::VERSION::MAJOR >= 6
42
+ ', charset: "utf8mb4", collation: "utf8mb4_bin"'
43
+ else
44
+ ''
45
+ end
46
+ else
47
+ ", id: :integer" unless Rails::VERSION::MAJOR < 5
48
+ end
49
+ end
50
+ let(:lock_version_limit) do
51
+ if defined?(Mysql2)
52
+ ", limit: 4"
53
+ else
54
+ ''
55
+ end
56
+ end
57
+
10
58
  # DeclareSchema - Migration Generator
11
59
  it 'generates migrations' do
12
60
  ## The migration generator -- introduction
@@ -25,7 +73,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
25
73
 
26
74
  class Advert < ActiveRecord::Base
27
75
  fields do
28
- name :string, limit: 255, null: true
76
+ name :string, limit: 250, null: true
29
77
  end
30
78
  end
31
79
 
@@ -33,8 +81,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
33
81
  expect(migrations).to(
34
82
  migrate_up(<<~EOS.strip)
35
83
  create_table :adverts, id: :bigint do |t|
36
- t.string :name, limit: 255
37
- end
84
+ t.string :name, limit: 250, null: true#{charset_and_collation}
85
+ end#{charset_alter_table}
38
86
  EOS
39
87
  .and migrate_down("drop_table :adverts")
40
88
  )
@@ -44,14 +92,18 @@ RSpec.describe 'DeclareSchema Migration Generator' do
44
92
  expect(Advert.columns.map(&:name)).to eq(["id", "name"])
45
93
 
46
94
  if Rails::VERSION::MAJOR < 5
47
- # Rails 4 sqlite driver doesn't create PK properly. Fix that by dropping and recreating.
95
+ # Rails 4 drivers don't always create PK properly. Fix that by dropping and recreating.
48
96
  ActiveRecord::Base.connection.execute("drop table adverts")
49
- ActiveRecord::Base.connection.execute('CREATE TABLE "adverts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255))')
97
+ if defined?(Mysql2)
98
+ ActiveRecord::Base.connection.execute("CREATE TABLE adverts (id integer PRIMARY KEY AUTO_INCREMENT NOT NULL, name varchar(250)) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin")
99
+ else
100
+ ActiveRecord::Base.connection.execute("CREATE TABLE adverts (id integer PRIMARY KEY AUTOINCREMENT NOT NULL, name varchar(250))")
101
+ end
50
102
  end
51
103
 
52
104
  class Advert < ActiveRecord::Base
53
105
  fields do
54
- name :string, limit: 255, null: true
106
+ name :string, limit: 250, null: true
55
107
  body :text, null: true
56
108
  published_at :datetime, null: true
57
109
  end
@@ -62,8 +114,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do
62
114
 
63
115
  expect(migrate).to(
64
116
  migrate_up(<<~EOS.strip)
65
- add_column :adverts, :body, :text
66
- add_column :adverts, :published_at, :datetime
117
+ add_column :adverts, :body, :text#{text_limit}, null: true#{charset_and_collation}
118
+ add_column :adverts, :published_at, :datetime, null: true
67
119
  EOS
68
120
  .and migrate_down(<<~EOS.strip)
69
121
  remove_column :adverts, :body
@@ -74,33 +126,33 @@ RSpec.describe 'DeclareSchema Migration Generator' do
74
126
  Advert.field_specs.clear # not normally needed
75
127
  class Advert < ActiveRecord::Base
76
128
  fields do
77
- name :string, limit: 255, null: true
129
+ name :string, limit: 250, null: true
78
130
  body :text, null: true
79
131
  end
80
132
  end
81
133
 
82
134
  expect(migrate).to(
83
135
  migrate_up("remove_column :adverts, :published_at").and(
84
- migrate_down("add_column :adverts, :published_at, :datetime")
136
+ migrate_down("add_column :adverts, :published_at, :datetime#{datetime_precision}, null: true")
85
137
  )
86
138
  )
87
139
 
88
140
  nuke_model_class(Advert)
89
141
  class Advert < ActiveRecord::Base
90
142
  fields do
91
- title :string, limit: 255, null: true
143
+ title :string, limit: 250, null: true
92
144
  body :text, null: true
93
145
  end
94
146
  end
95
147
 
96
148
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
97
149
  migrate_up(<<~EOS.strip)
98
- add_column :adverts, :title, :string, limit: 255
150
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
99
151
  remove_column :adverts, :name
100
152
  EOS
101
153
  .and migrate_down(<<~EOS.strip)
102
154
  remove_column :adverts, :title
103
- add_column :adverts, :name, :string, limit: 255
155
+ add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
104
156
  EOS
105
157
  )
106
158
 
@@ -120,24 +172,24 @@ RSpec.describe 'DeclareSchema Migration Generator' do
120
172
  end
121
173
 
122
174
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
123
- migrate_up("change_column :adverts, :title, :text").and(
124
- migrate_down("change_column :adverts, :title, :string, limit: 255")
175
+ migrate_up("change_column :adverts, :title, :text#{text_limit}, null: true#{charset_and_collation}").and(
176
+ migrate_down("change_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}")
125
177
  )
126
178
  )
127
179
 
128
180
  class Advert < ActiveRecord::Base
129
181
  fields do
130
- title :string, default: "Untitled", limit: 255, null: true
182
+ title :string, default: "Untitled", limit: 250, null: true
131
183
  body :text, null: true
132
184
  end
133
185
  end
134
186
 
135
187
  expect(migrate).to(
136
188
  migrate_up(<<~EOS.strip)
137
- change_column :adverts, :title, :string, limit: 255, default: "Untitled"
189
+ change_column :adverts, :title, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
138
190
  EOS
139
191
  .and migrate_down(<<~EOS.strip)
140
- change_column :adverts, :title, :string, limit: 255
192
+ change_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
141
193
  EOS
142
194
  )
143
195
 
@@ -150,7 +202,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
150
202
  end
151
203
 
152
204
  up, _ = Generators::DeclareSchema::Migration::Migrator.run.tap do |migrations|
153
- expect(migrations).to migrate_up("add_column :adverts, :price, :integer, limit: 2")
205
+ expect(migrations).to migrate_up("add_column :adverts, :price, :integer, limit: 2, null: true")
154
206
  end
155
207
 
156
208
  # Now run the migration, then change the limit:
@@ -164,30 +216,29 @@ RSpec.describe 'DeclareSchema Migration Generator' do
164
216
 
165
217
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
166
218
  migrate_up(<<~EOS.strip)
167
- change_column :adverts, :price, :integer, limit: 3
219
+ change_column :adverts, :price, :integer, limit: 3, null: true
168
220
  EOS
169
221
  .and migrate_down(<<~EOS.strip)
170
- change_column :adverts, :price, :integer, limit: 2
222
+ change_column :adverts, :price, :integer, limit: 2, null: true
171
223
  EOS
172
224
  )
173
225
 
174
- # Note that limit on a decimal column is ignored (use :scale and :precision)
175
-
176
226
  ActiveRecord::Migration.class_eval("remove_column :adverts, :price")
177
227
  class Advert < ActiveRecord::Base
178
228
  fields do
179
- price :decimal, null: true, limit: 4
229
+ price :decimal, precision: 4, scale: 1, null: true
180
230
  end
181
231
  end
182
232
 
183
- expect(Generators::DeclareSchema::Migration::Migrator.run).to migrate_up("add_column :adverts, :price, :decimal")
184
-
185
233
  # Limits are generally not needed for `text` fields, because by default, `text` fields will use the maximum size
186
234
  # allowed for that database type (0xffffffff for LONGTEXT in MySQL unlimited in Postgres, 1 billion in Sqlite).
187
235
  # If a `limit` is given, it will only be used in MySQL, to choose the smallest TEXT field that will accommodate
188
236
  # that limit (0xff for TINYTEXT, 0xffff for TEXT, 0xffffff for MEDIUMTEXT, 0xffffffff for LONGTEXT).
189
237
 
190
- expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_falsey
238
+ if defined?(SQLite3)
239
+ expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_falsey
240
+ end
241
+
191
242
  class Advert < ActiveRecord::Base
192
243
  fields do
193
244
  notes :text
@@ -197,114 +248,108 @@ RSpec.describe 'DeclareSchema Migration Generator' do
197
248
 
198
249
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
199
250
  migrate_up(<<~EOS.strip)
200
- add_column :adverts, :price, :decimal
201
- add_column :adverts, :notes, :text, null: false
202
- add_column :adverts, :description, :text, null: false
251
+ add_column :adverts, :price, :decimal, precision: 4, scale: 1, null: true
252
+ add_column :adverts, :notes, :text#{text_limit}, null: false#{charset_and_collation}
253
+ add_column :adverts, :description, :text#{', limit: 65535' if defined?(Mysql2)}, null: false#{charset_and_collation}
203
254
  EOS
204
255
  )
205
256
 
206
- # (There is no limit on `add_column ... :description` above since these tests are run against SQLite.)
207
-
208
257
  Advert.field_specs.delete :price
209
258
  Advert.field_specs.delete :notes
210
259
  Advert.field_specs.delete :description
211
260
 
212
261
  # In MySQL, limits are applied, rounded up:
213
262
 
214
- ::DeclareSchema::Model::FieldSpec::instance_variable_set(:@mysql_text_limits, true)
215
- expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_truthy
216
- class Advert < ActiveRecord::Base
217
- fields do
218
- notes :text
219
- description :text, limit: 200
220
- end
221
- end
222
-
223
- expect(Generators::DeclareSchema::Migration::Migrator.run).to(
224
- migrate_up(<<~EOS.strip)
225
- add_column :adverts, :notes, :text, null: false, limit: 4294967295
226
- add_column :adverts, :description, :text, null: false, limit: 255
227
- EOS
228
- )
263
+ if defined?(Mysql2)
264
+ expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_truthy
229
265
 
230
- Advert.field_specs.delete :notes
231
-
232
- # Limits that are too high for MySQL will raise an exception.
233
-
234
- ::DeclareSchema::Model::FieldSpec::instance_variable_set(:@mysql_text_limits, true)
235
- expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_truthy
236
- expect do
237
266
  class Advert < ActiveRecord::Base
238
267
  fields do
239
268
  notes :text
240
- description :text, limit: 0x1_0000_0000
269
+ description :text, limit: 250
241
270
  end
242
271
  end
243
- end.to raise_exception(ArgumentError, "limit of 4294967296 is too large for MySQL")
244
272
 
245
- Advert.field_specs.delete :notes
273
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
274
+ migrate_up(<<~EOS.strip)
275
+ add_column :adverts, :notes, :text, limit: 4294967295, null: false#{charset_and_collation}
276
+ add_column :adverts, :description, :text, limit: 255, null: false#{charset_and_collation}
277
+ EOS
278
+ )
246
279
 
247
- # And in MySQL, unstated text limits are treated as the maximum (LONGTEXT) limit.
280
+ Advert.field_specs.delete :notes
248
281
 
249
- # To start, we'll set the database schema for `description` to match the above limit of 255.
282
+ # Limits that are too high for MySQL will raise an exception.
250
283
 
251
- expect(::DeclareSchema::Model::FieldSpec.mysql_text_limits?).to be_truthy
252
- Advert.connection.execute "ALTER TABLE adverts ADD COLUMN description TINYTEXT"
253
- Advert.connection.schema_cache.clear!
254
- Advert.reset_column_information
255
- expect(Advert.connection.tables - Generators::DeclareSchema::Migration::Migrator.always_ignore_tables).
256
- to eq(["adverts"])
257
- expect(Advert.columns.map(&:name)).to eq(["id", "body", "title", "description"])
284
+ expect do
285
+ class Advert < ActiveRecord::Base
286
+ fields do
287
+ notes :text
288
+ description :text, limit: 0x1_0000_0000
289
+ end
290
+ end
291
+ end.to raise_exception(ArgumentError, "limit of 4294967296 is too large for MySQL")
258
292
 
259
- # Now migrate to an unstated text limit:
293
+ Advert.field_specs.delete :notes
260
294
 
261
- class Advert < ActiveRecord::Base
262
- fields do
263
- description :text
264
- end
265
- end
295
+ # And in MySQL, unstated text limits are treated as the maximum (LONGTEXT) limit.
266
296
 
267
- expect(Generators::DeclareSchema::Migration::Migrator.run).to(
268
- migrate_up(<<~EOS.strip)
269
- change_column :adverts, :description, :text, limit: 4294967295, null: false
270
- EOS
271
- .and migrate_down(<<~EOS.strip)
272
- change_column :adverts, :description, :text
273
- EOS
274
- )
297
+ # To start, we'll set the database schema for `description` to match the above limit of 250.
275
298
 
276
- # TODO TECH-4814: The above test should have this output:
277
- # TODO => "change_column :adverts, :description, :text, limit: 255
299
+ Advert.connection.execute "ALTER TABLE adverts ADD COLUMN description TINYTEXT"
300
+ Advert.connection.schema_cache.clear!
301
+ Advert.reset_column_information
302
+ expect(Advert.connection.tables - Generators::DeclareSchema::Migration::Migrator.always_ignore_tables).
303
+ to eq(["adverts"])
304
+ expect(Advert.columns.map(&:name)).to eq(["id", "body", "title", "description"])
278
305
 
279
- # And migrate to a stated text limit that is the same as the unstated one:
306
+ # Now migrate to an unstated text limit:
280
307
 
281
- class Advert < ActiveRecord::Base
282
- fields do
283
- description :text, limit: 0xffffffff
308
+ class Advert < ActiveRecord::Base
309
+ fields do
310
+ description :text
311
+ end
284
312
  end
285
- end
286
313
 
287
- expect(Generators::DeclareSchema::Migration::Migrator.run).to(
288
- migrate_up(<<~EOS.strip)
289
- change_column :adverts, :description, :text, limit: 4294967295, null: false
290
- EOS
291
- .and migrate_down(<<~EOS.strip)
292
- change_column :adverts, :description, :text
293
- EOS
294
- )
295
- ::DeclareSchema::Model::FieldSpec::instance_variable_set(:@mysql_text_limits, false)
314
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
315
+ migrate_up(<<~EOS.strip)
316
+ change_column :adverts, :description, :text, limit: 4294967295, null: false#{charset_and_collation}
317
+ EOS
318
+ .and migrate_down(<<~EOS.strip)
319
+ change_column :adverts, :description, :text#{', limit: 255' if defined?(Mysql2)}, null: true#{charset_and_collation}
320
+ EOS
321
+ )
322
+
323
+ # And migrate to a stated text limit that is the same as the unstated one:
324
+
325
+ class Advert < ActiveRecord::Base
326
+ fields do
327
+ description :text, limit: 0xffffffff
328
+ end
329
+ end
330
+
331
+ expect(Generators::DeclareSchema::Migration::Migrator.run).to(
332
+ migrate_up(<<~EOS.strip)
333
+ change_column :adverts, :description, :text, limit: 4294967295, null: false#{charset_and_collation}
334
+ EOS
335
+ .and migrate_down(<<~EOS.strip)
336
+ change_column :adverts, :description, :text#{', limit: 255' if defined?(Mysql2)}, null: true#{charset_and_collation}
337
+ EOS
338
+ )
339
+ end
296
340
 
297
341
  Advert.field_specs.clear
298
342
  Advert.connection.schema_cache.clear!
299
343
  Advert.reset_column_information
300
344
  class Advert < ActiveRecord::Base
301
345
  fields do
302
- name :string, limit: 255, null: true
346
+ name :string, limit: 250, null: true
303
347
  end
304
348
  end
305
349
 
306
350
  up = Generators::DeclareSchema::Migration::Migrator.run.first
307
351
  ActiveRecord::Migration.class_eval up
352
+
308
353
  Advert.connection.schema_cache.clear!
309
354
  Advert.reset_column_information
310
355
 
@@ -316,7 +361,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
316
361
  class Category < ActiveRecord::Base; end
317
362
  class Advert < ActiveRecord::Base
318
363
  fields do
319
- name :string, limit: 255, null: true
364
+ name :string, limit: 250, null: true
320
365
  end
321
366
  belongs_to :category
322
367
  end
@@ -326,11 +371,15 @@ RSpec.describe 'DeclareSchema Migration Generator' do
326
371
  add_column :adverts, :category_id, :integer, limit: 8, null: false
327
372
 
328
373
  add_index :adverts, [:category_id], name: 'on_category_id'
374
+
375
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" if defined?(Mysql2)}
329
376
  EOS
330
377
  .and migrate_down(<<~EOS.strip)
331
378
  remove_column :adverts, :category_id
332
379
 
333
380
  remove_index :adverts, name: :on_category_id rescue ActiveRecord::StatementInvalid
381
+
382
+ #{"remove_foreign_key(\"adverts\", name: \"index_adverts_on_category_id\")\n" if defined?(Mysql2)}
334
383
  EOS
335
384
  )
336
385
 
@@ -350,6 +399,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
350
399
  add_column :adverts, :c_id, :integer, limit: 8, null: false
351
400
 
352
401
  add_index :adverts, [:c_id], name: 'on_c_id'
402
+
403
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
404
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
353
405
  EOS
354
406
  )
355
407
 
@@ -367,6 +419,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
367
419
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
368
420
  migrate_up(<<~EOS.strip)
369
421
  add_column :adverts, :category_id, :integer, limit: 8, null: false
422
+
423
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
424
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
370
425
  EOS
371
426
  )
372
427
 
@@ -386,6 +441,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
386
441
  add_column :adverts, :category_id, :integer, limit: 8, null: false
387
442
 
388
443
  add_index :adverts, [:category_id], name: 'my_index'
444
+
445
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
446
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
389
447
  EOS
390
448
  )
391
449
 
@@ -406,14 +464,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
406
464
 
407
465
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
408
466
  migrate_up(<<~EOS.strip)
409
- add_column :adverts, :created_at, :datetime
410
- add_column :adverts, :updated_at, :datetime
411
- add_column :adverts, :lock_version, :integer, null: false, default: 1
467
+ add_column :adverts, :created_at, :datetime, null: true
468
+ add_column :adverts, :updated_at, :datetime, null: true
469
+ add_column :adverts, :lock_version, :integer#{lock_version_limit}, null: false, default: 1
470
+
471
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
472
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
412
473
  EOS
413
474
  .and migrate_down(<<~EOS.strip)
414
475
  remove_column :adverts, :created_at
415
476
  remove_column :adverts, :updated_at
416
477
  remove_column :adverts, :lock_version
478
+
479
+ #{"remove_foreign_key(\"adverts\", name: \"index_adverts_on_category_id\")\n" +
480
+ "remove_foreign_key(\"adverts\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
417
481
  EOS
418
482
  )
419
483
 
@@ -427,15 +491,18 @@ RSpec.describe 'DeclareSchema Migration Generator' do
427
491
 
428
492
  class Advert < ActiveRecord::Base
429
493
  fields do
430
- title :string, index: true, limit: 255, null: true
494
+ title :string, index: true, limit: 250, null: true
431
495
  end
432
496
  end
433
497
 
434
498
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
435
499
  migrate_up(<<~EOS.strip)
436
- add_column :adverts, :title, :string, limit: 255
500
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
437
501
 
438
502
  add_index :adverts, [:title], name: 'on_title'
503
+
504
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
505
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
439
506
  EOS
440
507
  )
441
508
 
@@ -445,15 +512,18 @@ RSpec.describe 'DeclareSchema Migration Generator' do
445
512
 
446
513
  class Advert < ActiveRecord::Base
447
514
  fields do
448
- title :string, index: true, unique: true, null: true, limit: 255
515
+ title :string, index: true, unique: true, null: true, limit: 250
449
516
  end
450
517
  end
451
518
 
452
519
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
453
520
  migrate_up(<<~EOS.strip)
454
- add_column :adverts, :title, :string, limit: 255
521
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
455
522
 
456
523
  add_index :adverts, [:title], unique: true, name: 'on_title'
524
+
525
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
526
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
457
527
  EOS
458
528
  )
459
529
 
@@ -463,15 +533,18 @@ RSpec.describe 'DeclareSchema Migration Generator' do
463
533
 
464
534
  class Advert < ActiveRecord::Base
465
535
  fields do
466
- title :string, index: 'my_index', limit: 255, null: true
536
+ title :string, index: 'my_index', limit: 250, null: true
467
537
  end
468
538
  end
469
539
 
470
540
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
471
541
  migrate_up(<<~EOS.strip)
472
- add_column :adverts, :title, :string, limit: 255
542
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
473
543
 
474
544
  add_index :adverts, [:title], name: 'my_index'
545
+
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)}
475
548
  EOS
476
549
  )
477
550
 
@@ -485,9 +558,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
485
558
 
486
559
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
487
560
  migrate_up(<<~EOS.strip)
488
- add_column :adverts, :title, :string, limit: 255
561
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
489
562
 
490
563
  add_index :adverts, [:title], name: 'on_title'
564
+
565
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
566
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
491
567
  EOS
492
568
  )
493
569
 
@@ -501,9 +577,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
501
577
 
502
578
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
503
579
  migrate_up(<<~EOS.strip)
504
- add_column :adverts, :title, :string, limit: 255
580
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
505
581
 
506
582
  add_index :adverts, [:title], unique: true, name: 'my_index'
583
+
584
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
585
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
507
586
  EOS
508
587
  )
509
588
 
@@ -517,9 +596,12 @@ RSpec.describe 'DeclareSchema Migration Generator' do
517
596
 
518
597
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
519
598
  migrate_up(<<~EOS.strip)
520
- add_column :adverts, :title, :string, limit: 255
599
+ add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
521
600
 
522
601
  add_index :adverts, [:title, :category_id], name: 'on_title_and_category_id'
602
+
603
+ #{"add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
604
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")" if defined?(Mysql2)}
523
605
  EOS
524
606
  )
525
607
 
@@ -536,7 +618,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
536
618
  class Advert < ActiveRecord::Base
537
619
  self.table_name = "ads"
538
620
  fields do
539
- title :string, limit: 255, null: true
621
+ title :string, limit: 250, null: true
540
622
  body :text, null: true
541
623
  end
542
624
  end
@@ -548,10 +630,16 @@ RSpec.describe 'DeclareSchema Migration Generator' do
548
630
  migrate_up(<<~EOS.strip)
549
631
  rename_table :adverts, :ads
550
632
 
551
- add_column :ads, :title, :string, limit: 255
552
- add_column :ads, :body, :text
633
+ add_column :ads, :title, :string, limit: 250, null: true#{charset_and_collation}
634
+ add_column :ads, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
553
635
 
554
- add_index :ads, [:id], unique: true, name: 'PRIMARY'
636
+ #{if defined?(SQLite3)
637
+ "add_index :ads, [:id], unique: true, name: 'PRIMARY'\n"
638
+ elsif defined?(Mysql2)
639
+ "execute \"ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
640
+ "add_foreign_key(\"adverts\", \"categories\", column: \"category_id\", name: \"index_adverts_on_category_id\")\n" +
641
+ "add_foreign_key(\"adverts\", \"categories\", column: \"c_id\", name: \"index_adverts_on_c_id\")"
642
+ end}
555
643
  EOS
556
644
  .and migrate_down(<<~EOS.strip)
557
645
  remove_column :ads, :title
@@ -559,14 +647,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
559
647
 
560
648
  rename_table :ads, :adverts
561
649
 
562
- add_index :adverts, [:id], unique: true, name: 'PRIMARY'
650
+ #{if defined?(SQLite3)
651
+ "add_index :adverts, [:id], unique: true, name: 'PRIMARY'\n"
652
+ elsif defined?(Mysql2)
653
+ "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\"\n\n" +
654
+ "remove_foreign_key(\"adverts\", name: \"index_adverts_on_category_id\")\n" +
655
+ "remove_foreign_key(\"adverts\", name: \"index_adverts_on_c_id\")"
656
+ end}
563
657
  EOS
564
658
  )
565
659
 
566
660
  # Set the table name back to what it should be and confirm we're in sync:
567
661
 
568
- Advert.field_specs.delete(:title)
569
- Advert.field_specs.delete(:body)
662
+ nuke_model_class(Advert)
663
+
570
664
  class Advert < ActiveRecord::Base
571
665
  self.table_name = "adverts"
572
666
  end
@@ -581,7 +675,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
581
675
 
582
676
  class Advertisement < ActiveRecord::Base
583
677
  fields do
584
- title :string, limit: 255, null: true
678
+ title :string, limit: 250, null: true
585
679
  body :text, null: true
586
680
  end
587
681
  end
@@ -590,20 +684,28 @@ RSpec.describe 'DeclareSchema Migration Generator' do
590
684
  migrate_up(<<~EOS.strip)
591
685
  rename_table :adverts, :advertisements
592
686
 
593
- add_column :advertisements, :title, :string, limit: 255
594
- add_column :advertisements, :body, :text
687
+ add_column :advertisements, :title, :string, limit: 250, null: true#{charset_and_collation}
688
+ add_column :advertisements, :body, :text#{', limit: 4294967295' if defined?(Mysql2)}, null: true#{charset_and_collation}
595
689
  remove_column :advertisements, :name
596
690
 
597
- add_index :advertisements, [:id], unique: true, name: 'PRIMARY'
691
+ #{if defined?(SQLite3)
692
+ "add_index :advertisements, [:id], unique: true, name: 'PRIMARY'"
693
+ elsif defined?(Mysql2)
694
+ "execute \"ALTER TABLE advertisements DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
695
+ end}
598
696
  EOS
599
697
  .and migrate_down(<<~EOS.strip)
600
698
  remove_column :advertisements, :title
601
699
  remove_column :advertisements, :body
602
- add_column :adverts, :name, :string, limit: 255
700
+ add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
603
701
 
604
702
  rename_table :advertisements, :adverts
605
703
 
606
- add_index :adverts, [:id], unique: true, name: 'PRIMARY'
704
+ #{if defined?(SQLite3)
705
+ "add_index :adverts, [:id], unique: true, name: 'PRIMARY'"
706
+ elsif defined?(Mysql2)
707
+ "execute \"ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (id)\""
708
+ end}
607
709
  EOS
608
710
  )
609
711
 
@@ -615,23 +717,15 @@ RSpec.describe 'DeclareSchema Migration Generator' do
615
717
 
616
718
  # Dropping tables is where the automatic down-migration really comes in handy:
617
719
 
618
- rails4_table_create = <<~EOS.strip
619
- create_table "adverts", force: :cascade do |t|
620
- t.string "name", limit: 255
621
- end
622
- EOS
623
-
624
- rails5_table_create = <<~EOS.strip
625
- create_table "adverts", id: :integer, force: :cascade do |t|
626
- t.string "name", limit: 255
627
- end
628
- EOS
629
-
630
720
  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
631
721
  migrate_up(<<~EOS.strip)
632
722
  drop_table :adverts
633
723
  EOS
634
- .and migrate_down(Rails::VERSION::MAJOR >= 5 ? rails5_table_create : rails4_table_create)
724
+ .and migrate_down(<<~EOS.strip)
725
+ create_table "adverts"#{table_options}, force: :cascade do |t|
726
+ t.string "name", limit: 250#{charset_and_collation}
727
+ end
728
+ EOS
635
729
  )
636
730
 
637
731
  ## STI
@@ -643,7 +737,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
643
737
  class Advert < ActiveRecord::Base
644
738
  fields do
645
739
  body :text, null: true
646
- title :string, default: "Untitled", limit: 255, null: true
740
+ title :string, default: "Untitled", limit: 250, null: true
647
741
  end
648
742
  end
649
743
  up = Generators::DeclareSchema::Migration::Migrator.run.first
@@ -657,7 +751,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
657
751
  up, _ = Generators::DeclareSchema::Migration::Migrator.run do |migrations|
658
752
  expect(migrations).to(
659
753
  migrate_up(<<~EOS.strip)
660
- add_column :adverts, :type, :string, limit: 255
754
+ add_column :adverts, :type, :string, limit: 250, null: true#{charset_and_collation}
661
755
 
662
756
  add_index :adverts, [:type], name: 'on_type'
663
757
  EOS
@@ -696,7 +790,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
696
790
 
697
791
  class Advert < ActiveRecord::Base
698
792
  fields do
699
- name :string, default: "No Name", limit: 255, null: true
793
+ name :string, default: "No Name", limit: 250, null: true
700
794
  body :text, null: true
701
795
  end
702
796
  end
@@ -704,11 +798,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
704
798
  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: { title: :name })).to(
705
799
  migrate_up(<<~EOS.strip)
706
800
  rename_column :adverts, :title, :name
707
- change_column :adverts, :name, :string, limit: 255, default: "No Name"
801
+ change_column :adverts, :name, :string, limit: 250, null: true, default: "No Name"#{charset_and_collation}
708
802
  EOS
709
803
  .and migrate_down(<<~EOS.strip)
710
804
  rename_column :adverts, :name, :title
711
- change_column :adverts, :title, :string, limit: 255, default: "Untitled"
805
+ change_column :adverts, :title, :string, limit: 250, null: true, default: "Untitled"#{charset_and_collation}
712
806
  EOS
713
807
  )
714
808
 
@@ -717,7 +811,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
717
811
  nuke_model_class(Advert)
718
812
  class Ad < ActiveRecord::Base
719
813
  fields do
720
- title :string, default: "Untitled", limit: 255
814
+ title :string, default: "Untitled", limit: 250
721
815
  body :text, null: true
722
816
  created_at :datetime
723
817
  end
@@ -728,16 +822,20 @@ RSpec.describe 'DeclareSchema Migration Generator' do
728
822
  rename_table :adverts, :ads
729
823
 
730
824
  add_column :ads, :created_at, :datetime, null: false
731
- change_column :ads, :title, :string, limit: 255, null: false, default: \"Untitled\"
825
+ change_column :ads, :title, :string, limit: 250, null: false, default: \"Untitled\"#{charset_and_collation}
732
826
 
733
- add_index :ads, [:id], unique: true, name: 'PRIMARY'
827
+ #{if defined?(SQLite3)
828
+ "add_index :ads, [:id], unique: true, name: 'PRIMARY'"
829
+ elsif defined?(Mysql2)
830
+ 'execute "ALTER TABLE ads DROP PRIMARY KEY, ADD PRIMARY KEY (id)"'
831
+ end}
734
832
  EOS
735
833
  )
736
834
 
737
835
  class Advert < ActiveRecord::Base
738
836
  fields do
739
837
  body :text, null: true
740
- title :string, default: "Untitled", limit: 255, null: true
838
+ title :string, default: "Untitled", limit: 250, null: true
741
839
  end
742
840
  end
743
841
 
@@ -758,7 +856,11 @@ RSpec.describe 'DeclareSchema Migration Generator' do
758
856
  migrate_up(<<~EOS.strip)
759
857
  rename_column :adverts, :id, :advert_id
760
858
 
761
- add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY'
859
+ #{if defined?(SQLite3)
860
+ "add_index :adverts, [:advert_id], unique: true, name: 'PRIMARY'"
861
+ elsif defined?(Mysql2)
862
+ 'execute "ALTER TABLE adverts DROP PRIMARY KEY, ADD PRIMARY KEY (advert_id)"'
863
+ end}
762
864
  EOS
763
865
  )
764
866
 
@@ -771,7 +873,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
771
873
 
772
874
  class User < ActiveRecord::Base
773
875
  fields do
774
- company :string, limit: 255, ruby_default: -> { "BigCorp" }
876
+ company :string, limit: 250, ruby_default: -> { "BigCorp" }
775
877
  end
776
878
  end
777
879
  expect(User.field_specs.keys).to eq(['company'])
@@ -790,7 +892,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
790
892
  expect(Ad).to receive(:validates).with(:company, presence: true, uniqueness: { case_sensitive: false })
791
893
  class Ad < ActiveRecord::Base
792
894
  fields do
793
- company :string, limit: 255, index: true, unique: true, validates: { presence: true, uniqueness: { case_sensitive: false } }
895
+ company :string, limit: 250, index: true, unique: true, validates: { presence: true, uniqueness: { case_sensitive: false } }
794
896
  end
795
897
  self.primary_key = "advert_id"
796
898
  end
@@ -828,10 +930,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
828
930
  it 'converts defaults with .to_yaml' do
829
931
  class Ad < ActiveRecord::Base
830
932
  fields do
831
- allow_list :string, limit: 255, serialize: true, null: true, default: []
832
- allow_hash :string, limit: 255, serialize: true, null: true, default: {}
833
- allow_string :string, limit: 255, serialize: true, null: true, default: ['abc']
834
- allow_null :string, limit: 255, serialize: true, null: true, default: nil
933
+ allow_list :string, limit: 250, serialize: true, null: true, default: []
934
+ allow_hash :string, limit: 250, serialize: true, null: true, default: {}
935
+ allow_string :string, limit: 250, serialize: true, null: true, default: ['abc']
936
+ allow_null :string, limit: 250, serialize: true, null: true, default: nil
835
937
  end
836
938
  end
837
939
 
@@ -846,7 +948,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
846
948
  it 'allows serialize: Array' do
847
949
  class Ad < ActiveRecord::Base
848
950
  fields do
849
- allow_list :string, limit: 255, serialize: Array, null: true
951
+ allow_list :string, limit: 250, serialize: Array, null: true
850
952
  end
851
953
  end
852
954
 
@@ -856,10 +958,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
856
958
  it 'allows Array defaults' do
857
959
  class Ad < ActiveRecord::Base
858
960
  fields do
859
- allow_list :string, limit: 255, serialize: Array, null: true, default: [2]
860
- allow_string :string, limit: 255, serialize: Array, null: true, default: ['abc']
861
- allow_empty :string, limit: 255, serialize: Array, null: true, default: []
862
- allow_null :string, limit: 255, serialize: Array, null: true, default: nil
961
+ allow_list :string, limit: 250, serialize: Array, null: true, default: [2]
962
+ allow_string :string, limit: 250, serialize: Array, null: true, default: ['abc']
963
+ allow_empty :string, limit: 250, serialize: Array, null: true, default: []
964
+ allow_null :string, limit: 250, serialize: Array, null: true, default: nil
863
965
  end
864
966
  end
865
967
 
@@ -874,7 +976,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
874
976
  it 'allows serialize: Hash' do
875
977
  class Ad < ActiveRecord::Base
876
978
  fields do
877
- allow_list :string, limit: 255, serialize: Hash, null: true
979
+ allow_list :string, limit: 250, serialize: Hash, null: true
878
980
  end
879
981
  end
880
982
 
@@ -884,9 +986,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
884
986
  it 'allows Hash defaults' do
885
987
  class Ad < ActiveRecord::Base
886
988
  fields do
887
- allow_loc :string, limit: 255, serialize: Hash, null: true, default: { 'state' => 'CA' }
888
- allow_hash :string, limit: 255, serialize: Hash, null: true, default: {}
889
- allow_null :string, limit: 255, serialize: Hash, null: true, default: nil
989
+ allow_loc :string, limit: 250, serialize: Hash, null: true, default: { 'state' => 'CA' }
990
+ allow_hash :string, limit: 250, serialize: Hash, null: true, default: {}
991
+ allow_null :string, limit: 250, serialize: Hash, null: true, default: nil
890
992
  end
891
993
  end
892
994
 
@@ -900,7 +1002,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
900
1002
  it 'allows serialize: JSON' do
901
1003
  class Ad < ActiveRecord::Base
902
1004
  fields do
903
- allow_list :string, limit: 255, serialize: JSON
1005
+ allow_list :string, limit: 250, serialize: JSON
904
1006
  end
905
1007
  end
906
1008
 
@@ -910,10 +1012,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
910
1012
  it 'allows JSON defaults' do
911
1013
  class Ad < ActiveRecord::Base
912
1014
  fields do
913
- allow_hash :string, limit: 255, serialize: JSON, null: true, default: { 'state' => 'CA' }
914
- allow_empty_array :string, limit: 255, serialize: JSON, null: true, default: []
915
- allow_empty_hash :string, limit: 255, serialize: JSON, null: true, default: {}
916
- allow_null :string, limit: 255, serialize: JSON, null: true, default: nil
1015
+ allow_hash :string, limit: 250, serialize: JSON, null: true, default: { 'state' => 'CA' }
1016
+ allow_empty_array :string, limit: 250, serialize: JSON, null: true, default: []
1017
+ allow_empty_hash :string, limit: 250, serialize: JSON, null: true, default: {}
1018
+ allow_null :string, limit: 250, serialize: JSON, null: true, default: nil
917
1019
  end
918
1020
  end
919
1021
 
@@ -950,7 +1052,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
950
1052
  it 'allows serialize: ValueClass' do
951
1053
  class Ad < ActiveRecord::Base
952
1054
  fields do
953
- allow_list :string, limit: 255, serialize: ValueClass
1055
+ allow_list :string, limit: 250, serialize: ValueClass
954
1056
  end
955
1057
  end
956
1058
 
@@ -960,9 +1062,9 @@ RSpec.describe 'DeclareSchema Migration Generator' do
960
1062
  it 'allows ValueClass defaults' do
961
1063
  class Ad < ActiveRecord::Base
962
1064
  fields do
963
- allow_hash :string, limit: 255, serialize: ValueClass, null: true, default: ValueClass.new([2])
964
- allow_empty_array :string, limit: 255, serialize: ValueClass, null: true, default: ValueClass.new([])
965
- allow_null :string, limit: 255, serialize: ValueClass, null: true, default: nil
1065
+ allow_hash :string, limit: 250, serialize: ValueClass, null: true, default: ValueClass.new([2])
1066
+ allow_empty_array :string, limit: 250, serialize: ValueClass, null: true, default: ValueClass.new([])
1067
+ allow_null :string, limit: 250, serialize: ValueClass, null: true, default: nil
966
1068
  end
967
1069
  end
968
1070
 
@@ -1003,7 +1105,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1003
1105
 
1004
1106
  class Advert < ActiveRecord::Base
1005
1107
  fields do
1006
- name :string, limit: 255, null: true
1108
+ name :string, limit: 250, null: true
1007
1109
  category_id :integer, limit: 8
1008
1110
  nullable_category_id :integer, limit: 8, null: true
1009
1111
  end
@@ -1108,6 +1210,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do
1108
1210
  migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
1109
1211
  expect(migrations.size).to eq(1), migrations.inspect
1110
1212
 
1213
+ if defined?(Mysql2) && Rails::VERSION::MAJOR < 5
1214
+ ActiveRecord::Base.connection.execute("ALTER TABLE adverts ADD PRIMARY KEY (id)")
1215
+ end
1216
+
1111
1217
  class Advert < active_record_base_class.constantize
1112
1218
  fields do
1113
1219
  price :integer, limit: 8