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.
- checksums.yaml +4 -4
- data/.github/workflows/declare_schema_build.yml +21 -5
- data/Appraisals +21 -4
- data/CHANGELOG.md +40 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +7 -9
- data/README.md +3 -3
- data/Rakefile +17 -4
- data/bin/declare_schema +1 -1
- data/declare_schema.gemspec +1 -1
- data/gemfiles/rails_4_mysql.gemfile +22 -0
- data/gemfiles/{rails_4.gemfile → rails_4_sqlite.gemfile} +1 -2
- data/gemfiles/rails_5_mysql.gemfile +22 -0
- data/gemfiles/{rails_5.gemfile → rails_5_sqlite.gemfile} +1 -2
- data/gemfiles/rails_6_mysql.gemfile +22 -0
- data/gemfiles/{rails_6.gemfile → rails_6_sqlite.gemfile} +2 -3
- data/lib/declare_schema/command.rb +10 -3
- data/lib/declare_schema/model/column.rb +168 -0
- data/lib/declare_schema/model/field_spec.rb +59 -143
- data/lib/declare_schema/model/foreign_key_definition.rb +36 -25
- data/lib/declare_schema/model/table_options_definition.rb +8 -6
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migration_generator.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +142 -116
- data/spec/lib/declare_schema/field_declaration_dsl_spec.rb +1 -1
- data/spec/lib/declare_schema/field_spec_spec.rb +135 -38
- data/spec/lib/declare_schema/generator_spec.rb +4 -2
- data/spec/lib/declare_schema/interactive_primary_key_spec.rb +8 -2
- data/spec/lib/declare_schema/migration_generator_spec.rb +277 -171
- data/spec/lib/declare_schema/model/column_spec.rb +141 -0
- data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +93 -0
- data/spec/lib/declare_schema/model/index_definition_spec.rb +4 -5
- data/spec/lib/declare_schema/model/table_options_definition_spec.rb +19 -29
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +12 -26
- data/spec/support/acceptance_spec_helpers.rb +3 -3
- 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
|
-
|
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
|
-
|
9
|
-
it '
|
10
|
-
subject =
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
#
|
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:
|
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:
|
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
|
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
|
-
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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,
|
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
|
-
|
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
|
-
|
215
|
-
|
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:
|
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
|
-
|
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
|
-
|
280
|
+
Advert.field_specs.delete :notes
|
248
281
|
|
249
|
-
|
282
|
+
# Limits that are too high for MySQL will raise an exception.
|
250
283
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
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
|
-
|
293
|
+
Advert.field_specs.delete :notes
|
260
294
|
|
261
|
-
|
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
|
-
|
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
|
-
|
277
|
-
|
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
|
-
|
306
|
+
# Now migrate to an unstated text limit:
|
280
307
|
|
281
|
-
|
282
|
-
|
283
|
-
|
308
|
+
class Advert < ActiveRecord::Base
|
309
|
+
fields do
|
310
|
+
description :text
|
311
|
+
end
|
284
312
|
end
|
285
|
-
end
|
286
313
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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
|
-
|
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
|
-
|
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
|
569
|
-
|
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:
|
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:
|
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
|
-
|
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:
|
700
|
+
add_column :adverts, :name, :string, limit: 250, null: true#{charset_and_collation}
|
603
701
|
|
604
702
|
rename_table :advertisements, :adverts
|
605
703
|
|
606
|
-
|
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(
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
825
|
+
change_column :ads, :title, :string, limit: 250, null: false, default: \"Untitled\"#{charset_and_collation}
|
732
826
|
|
733
|
-
|
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:
|
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
|
-
|
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:
|
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:
|
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:
|
832
|
-
allow_hash :string, limit:
|
833
|
-
allow_string :string, limit:
|
834
|
-
allow_null :string, limit:
|
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:
|
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:
|
860
|
-
allow_string :string, limit:
|
861
|
-
allow_empty :string, limit:
|
862
|
-
allow_null :string, limit:
|
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:
|
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:
|
888
|
-
allow_hash :string, limit:
|
889
|
-
allow_null :string, limit:
|
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:
|
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:
|
914
|
-
allow_empty_array :string, limit:
|
915
|
-
allow_empty_hash :string, limit:
|
916
|
-
allow_null :string, limit:
|
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:
|
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:
|
964
|
-
allow_empty_array :string, limit:
|
965
|
-
allow_null :string, limit:
|
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:
|
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
|