declare_schema 1.3.6 → 1.4.0.colin.1
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/CHANGELOG.md +5 -18
- data/Gemfile.lock +1 -1
- data/README.md +82 -41
- data/lib/declare_schema/model/field_spec.rb +0 -2
- data/lib/declare_schema/model/foreign_key_definition.rb +43 -40
- data/lib/declare_schema/model/habtm_model_shim.rb +26 -26
- data/lib/declare_schema/model/index_definition.rb +41 -30
- data/lib/declare_schema/model/table_options_definition.rb +1 -11
- data/lib/declare_schema/model.rb +66 -60
- data/lib/declare_schema/schema_change/column_add.rb +2 -4
- data/lib/declare_schema/schema_change/index_add.rb +3 -1
- data/lib/declare_schema/version.rb +1 -1
- data/lib/declare_schema.rb +3 -45
- data/lib/generators/declare_schema/migration/migrator.rb +19 -29
- data/spec/lib/declare_schema/field_spec_spec.rb +2 -22
- data/spec/lib/declare_schema/migration_generator_spec.rb +81 -92
- data/spec/lib/declare_schema/model/foreign_key_definition_spec.rb +23 -22
- data/spec/lib/declare_schema/model/habtm_model_shim_spec.rb +61 -76
- data/spec/lib/declare_schema/model/index_definition_spec.rb +106 -37
- data/spec/lib/declare_schema/model/table_options_definition_spec.rb +6 -26
- data/spec/lib/declare_schema/schema_change/index_add_spec.rb +28 -1
- data/spec/lib/declare_schema_spec.rb +8 -102
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +1 -3
- data/spec/spec_helper.rb +3 -4
- metadata +2 -2
@@ -11,7 +11,6 @@ require_relative '../../../../lib/declare_schema/model/index_definition'
|
|
11
11
|
|
12
12
|
RSpec.describe DeclareSchema::Model::IndexDefinition do
|
13
13
|
let(:model_class) { IndexDefinitionTestModel }
|
14
|
-
let(:table_name) { model_class.table_name }
|
15
14
|
|
16
15
|
context 'Using declare_schema' do
|
17
16
|
before do
|
@@ -35,26 +34,103 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
describe 'instance methods' do
|
38
|
+
let(:model) { model_class.new }
|
39
|
+
let(:fields) { ['last_name', 'first_name'] }
|
40
|
+
let(:options) { {} }
|
41
|
+
subject(:instance) { described_class.new(model_class, fields, **options) }
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
describe 'attr_readers' do
|
44
|
+
describe '#table' do
|
45
|
+
subject { instance.table }
|
46
|
+
|
47
|
+
it { is_expected.to eq(model_class.table_name) }
|
48
|
+
|
49
|
+
context 'with table_name option' do
|
50
|
+
let(:options) { { table_name: 'auth_users' } }
|
51
|
+
|
52
|
+
it { is_expected.to eq('auth_users') }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#fields' do
|
57
|
+
subject { instance.fields }
|
58
|
+
|
59
|
+
it { is_expected.to eq(fields) }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#explicit_name' do
|
63
|
+
subject { instance.explicit_name }
|
64
|
+
|
65
|
+
it { is_expected.to eq(nil) }
|
66
|
+
|
67
|
+
context 'with name option' do
|
68
|
+
let(:options) { { name: 'index_auth_users_on_last_name_and_first_name' } }
|
69
|
+
|
70
|
+
it { is_expected.to eq('index_auth_users_on_last_name_and_first_name') }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#length' do
|
75
|
+
subject { instance.length }
|
76
|
+
let(:options) { { length: length } }
|
77
|
+
|
78
|
+
context 'with integer length' do
|
79
|
+
let(:length) { 2 }
|
80
|
+
|
81
|
+
it { is_expected.to eq(length) }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with Hash length' do
|
85
|
+
let(:length) { { name: 2 } }
|
86
|
+
|
87
|
+
it { is_expected.to eq(length) }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#options' do
|
92
|
+
subject { instance.options }
|
93
|
+
let(:options) { { name: 'my_index', unique: false, where: "(name like 'a%')", length: 10 } }
|
94
|
+
|
95
|
+
it { is_expected.to eq(options) }
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#with_name' do
|
99
|
+
subject { instance.with_name('new_name') }
|
100
|
+
|
101
|
+
it { is_expected.to be_kind_of(described_class) }
|
102
|
+
it { expect(instance.name).to eq('index_index_definition_test_models_on_last_name_and_first_name') }
|
103
|
+
it { expect(subject.name).to eq('new_name') }
|
47
104
|
end
|
48
105
|
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'class methods' do
|
109
|
+
let(:model) { model_class.new }
|
49
110
|
|
50
|
-
describe '
|
51
|
-
|
111
|
+
describe 'index_definitions' do
|
112
|
+
it do
|
113
|
+
expect(model_class.index_definitions.size).to eq(1)
|
52
114
|
|
53
|
-
|
54
|
-
expect(
|
55
|
-
|
56
|
-
|
57
|
-
|
115
|
+
expect(model_class.index_definitions[0].name).to eq('index_index_definition_test_models_on_name')
|
116
|
+
expect(model_class.index_definitions[0].fields).to eq(['name'])
|
117
|
+
expect(model_class.index_definitions[0].unique).to eq(false)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'has index_definitions_with_primary_key' do
|
122
|
+
it do
|
123
|
+
expect(model_class.index_definitions_with_primary_key).to be_kind_of(Array)
|
124
|
+
result = model_class.index_definitions_with_primary_key.sort_by(&:name)
|
125
|
+
expect(result.size).to eq(2)
|
126
|
+
|
127
|
+
expect(result[0].name).to eq('PRIMARY')
|
128
|
+
expect(result[0].fields).to eq(['id'])
|
129
|
+
expect(result[0].unique).to eq(true)
|
130
|
+
|
131
|
+
expect(result[1].name).to eq('index_index_definition_test_models_on_name')
|
132
|
+
expect(result[1].fields).to eq(['name'])
|
133
|
+
expect(result[1].unique).to eq(false)
|
58
134
|
end
|
59
135
|
end
|
60
136
|
end
|
@@ -80,36 +156,29 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
|
|
80
156
|
ActiveRecord::Base.connection.schema_cache.clear!
|
81
157
|
end
|
82
158
|
|
83
|
-
describe '
|
84
|
-
|
85
|
-
subject { described_class.for_table(model_class.table_name, ignore_indexes, model_class.connection) }
|
159
|
+
describe 'for_model' do
|
160
|
+
subject { described_class.for_model(model_class) }
|
86
161
|
|
87
162
|
context 'with single-column PK' do
|
88
163
|
it 'returns the indexes for the model' do
|
89
|
-
expect(subject.
|
90
|
-
|
91
|
-
|
92
|
-
])
|
164
|
+
expect(subject.size).to eq(2), subject.inspect
|
165
|
+
expect(subject[0].name).to eq('index_definition_test_models_on_name')
|
166
|
+
expect(subject[0].columns).to eq(['name'])
|
167
|
+
expect(subject[0].unique).to eq(true)
|
168
|
+
expect(subject[1].name).to eq('PRIMARY')
|
169
|
+
expect(subject[1].columns).to eq(['id'])
|
170
|
+
expect(subject[1].unique).to eq(true)
|
93
171
|
end
|
94
172
|
end
|
95
173
|
|
96
|
-
context 'with
|
174
|
+
context 'with compound-column PK' do
|
97
175
|
let(:model_class) { IndexDefinitionCompoundIndexModel }
|
98
176
|
|
99
177
|
it 'returns the indexes for the model' do
|
100
|
-
expect(subject.
|
101
|
-
|
102
|
-
])
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
context 'with ignored_indexes' do
|
107
|
-
let(:ignore_indexes) { ['index_definition_test_models_on_name'] }
|
108
|
-
|
109
|
-
it 'skips the ignored index' do
|
110
|
-
expect(subject.map(&:to_key)).to eq([
|
111
|
-
["PRIMARY", ["id"], true, nil]
|
112
|
-
])
|
178
|
+
expect(subject.size).to eq(1), subject.inspect
|
179
|
+
expect(subject[0].name).to eq('PRIMARY')
|
180
|
+
expect(subject[0].columns).to eq(['fk1_id', 'fk2_id'])
|
181
|
+
expect(subject[0].unique).to eq(true)
|
113
182
|
end
|
114
183
|
end
|
115
184
|
end
|
@@ -9,8 +9,6 @@ require_relative '../../../../lib/declare_schema/model/table_options_definition'
|
|
9
9
|
|
10
10
|
RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
|
11
11
|
let(:model_class) { TableOptionsDefinitionTestModel }
|
12
|
-
let(:charset) { DeclareSchema.normalize_charset('utf8') }
|
13
|
-
let(:collation) { DeclareSchema.normalize_collation('utf8_general') } # adapt so that tests will pass on MySQL 5.7 or 8+
|
14
12
|
|
15
13
|
context 'Using declare_schema' do
|
16
14
|
before do
|
@@ -29,45 +27,27 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
|
|
29
27
|
|
30
28
|
describe '#to_key' do
|
31
29
|
subject { model.to_key }
|
32
|
-
it {
|
30
|
+
it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}']) }
|
33
31
|
end
|
34
32
|
|
35
33
|
describe '#settings' do
|
36
34
|
subject { model.settings }
|
37
|
-
it {
|
38
|
-
|
39
|
-
if defined?(Mysql2)
|
40
|
-
context 'when running in MySQL 8' do
|
41
|
-
around do |spec|
|
42
|
-
DeclareSchema.mysql_version = Gem::Version.new('8.0.21')
|
43
|
-
spec.run
|
44
|
-
ensure
|
45
|
-
DeclareSchema.remove_instance_variable('@mysql_version') rescue nil
|
46
|
-
end
|
47
|
-
|
48
|
-
it { is_expected.to eq("CHARACTER SET utf8mb3 COLLATE utf8mb3_general") }
|
49
|
-
|
50
|
-
context 'when _ci collation' do
|
51
|
-
let(:table_options) { { charset: "utf8", collation: "utf8_general_ci"} }
|
52
|
-
it { is_expected.to eq("CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci") }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
35
|
+
it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
|
56
36
|
end
|
57
37
|
|
58
38
|
describe '#hash' do
|
59
39
|
subject { model.hash }
|
60
|
-
it {
|
40
|
+
it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}'].hash) }
|
61
41
|
end
|
62
42
|
|
63
43
|
describe '#to_s' do
|
64
44
|
subject { model.to_s }
|
65
|
-
it {
|
45
|
+
it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
|
66
46
|
end
|
67
47
|
|
68
48
|
describe '#alter_table_statement' do
|
69
49
|
subject { model.alter_table_statement }
|
70
|
-
it {
|
50
|
+
it { should match(/execute "ALTER TABLE .*table_options_definition_test_models.* CHARACTER SET utf8 COLLATE utf8_general"/) }
|
71
51
|
end
|
72
52
|
end
|
73
53
|
|
@@ -87,7 +67,7 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
|
|
87
67
|
generate_migrations '-n', '-m'
|
88
68
|
end
|
89
69
|
|
90
|
-
it {
|
70
|
+
it { should eq(described_class.new(model_class.table_name, **options)) }
|
91
71
|
end
|
92
72
|
end
|
93
73
|
end
|
@@ -30,7 +30,7 @@ RSpec.describe DeclareSchema::SchemaChange::IndexAdd do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'with where:' do
|
33
|
-
let(:where) { "'last_name like 'A%'"}
|
33
|
+
let(:where) { "'last_name like 'A%'" }
|
34
34
|
subject { described_class.new(table_name, column_names, name: name, unique: unique, where: where) }
|
35
35
|
|
36
36
|
it 'responds with command' do
|
@@ -45,6 +45,33 @@ RSpec.describe DeclareSchema::SchemaChange::IndexAdd do
|
|
45
45
|
expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, unique: true\n")
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
context 'with limit: nil' do
|
50
|
+
let(:limit) { nil }
|
51
|
+
subject { described_class.new(table_name, column_names, name: name, unique: unique, limit: limit) }
|
52
|
+
|
53
|
+
it 'responds with command' do
|
54
|
+
expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}\n")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with limit: 2' do
|
59
|
+
let(:limit) { 2 }
|
60
|
+
subject { described_class.new(table_name, column_names, name: name, unique: unique, limit: limit) }
|
61
|
+
|
62
|
+
it 'responds with command' do
|
63
|
+
expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, limit: #{limit}\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with limit: hash' do
|
68
|
+
let(:limit) { { last_name: 10, first_name: 1 } }
|
69
|
+
subject { described_class.new(table_name, column_names, name: name, unique: unique, limit: limit) }
|
70
|
+
|
71
|
+
it 'responds with command' do
|
72
|
+
expect(subject.up).to eq("add_index :#{table_name}, #{column_names.map(&:to_sym).inspect}, name: #{name.to_sym.inspect}, limit: { last_name: 10, first_name: 1 }\n")
|
73
|
+
end
|
74
|
+
end
|
48
75
|
end
|
49
76
|
|
50
77
|
describe '#down' do
|
@@ -8,54 +8,10 @@ RSpec.describe DeclareSchema do
|
|
8
8
|
it { is_expected.to eq("utf8mb4") }
|
9
9
|
end
|
10
10
|
|
11
|
-
context 'when
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
ensure
|
16
|
-
described_class.remove_instance_variable('@mysql_version') rescue nil
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'when explicitly set' do
|
20
|
-
before { described_class.default_charset = "utf8" }
|
21
|
-
after { described_class.default_charset = "utf8mb4" }
|
22
|
-
it { is_expected.to eq("utf8") }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'when running on MySQL 8.0' do
|
27
|
-
around do |spec|
|
28
|
-
described_class.mysql_version = Gem::Version.new('8.0.21')
|
29
|
-
spec.run
|
30
|
-
ensure
|
31
|
-
described_class.remove_instance_variable('@mysql_version') rescue nil
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when explicitly set' do
|
35
|
-
before { described_class.default_charset = "utf8" }
|
36
|
-
after { described_class.default_charset = "utf8mb4" }
|
37
|
-
it { is_expected.to eq("utf8mb3") }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context 'when MySQL version not known yet' do
|
42
|
-
before { described_class.remove_instance_variable('@mysql_version') rescue nil }
|
43
|
-
after { described_class.remove_instance_variable('@mysql_version') rescue nil }
|
44
|
-
|
45
|
-
context 'when set' do
|
46
|
-
let(:connection) { double("connection", select_value: "8.0.21") }
|
47
|
-
|
48
|
-
it "is lazy, so it doesn't use the database connection until read" do
|
49
|
-
expect(ActiveRecord::Base).to receive(:connection) do
|
50
|
-
@connection_called = true
|
51
|
-
connection
|
52
|
-
end
|
53
|
-
described_class.default_charset = "utf8"
|
54
|
-
expect(@connection_called).to be_falsey
|
55
|
-
described_class.default_charset
|
56
|
-
expect(@connection_called).to be_truthy
|
57
|
-
end
|
58
|
-
end
|
11
|
+
context 'when explicitly set' do
|
12
|
+
before { described_class.default_charset = "utf8" }
|
13
|
+
after { described_class.default_charset = "utf8mb4" }
|
14
|
+
it { is_expected.to eq("utf8") }
|
59
15
|
end
|
60
16
|
end
|
61
17
|
|
@@ -66,60 +22,10 @@ RSpec.describe DeclareSchema do
|
|
66
22
|
it { is_expected.to eq("utf8mb4_bin") }
|
67
23
|
end
|
68
24
|
|
69
|
-
context 'when
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
ensure
|
74
|
-
described_class.remove_instance_variable('@mysql_version')
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'when explicitly set' do
|
78
|
-
before { described_class.default_collation = "utf8_general_ci" }
|
79
|
-
after { described_class.default_collation = "utf8mb4_bin" }
|
80
|
-
it { is_expected.to eq("utf8_general_ci") }
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context 'when running on MySQL 8.0' do
|
85
|
-
around do |spec|
|
86
|
-
described_class.mysql_version = Gem::Version.new('8.0.21')
|
87
|
-
spec.run
|
88
|
-
ensure
|
89
|
-
described_class.remove_instance_variable('@mysql_version')
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when explicitly set without _ci' do
|
93
|
-
before { described_class.default_collation = "utf8_general" }
|
94
|
-
after { described_class.default_collation = "utf8mb4_bin" }
|
95
|
-
it { is_expected.to eq("utf8mb3_general") }
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'when explicitly set with _ci' do
|
99
|
-
before { described_class.default_collation = "utf8_general_ci" }
|
100
|
-
after { described_class.default_collation = "utf8mb4_bin" }
|
101
|
-
it { is_expected.to eq("utf8mb3_general_ci") }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
context 'when MySQL version not known yet' do
|
106
|
-
before { described_class.remove_instance_variable('@mysql_version') rescue nil }
|
107
|
-
after { described_class.remove_instance_variable('@mysql_version') rescue nil }
|
108
|
-
|
109
|
-
context 'when set' do
|
110
|
-
let(:connection) { double("connection", select_value: "8.0.21") }
|
111
|
-
|
112
|
-
it "is lazy, so it doesn't use the database connection until read" do
|
113
|
-
expect(ActiveRecord::Base).to receive(:connection) do
|
114
|
-
@connection_called = true
|
115
|
-
connection
|
116
|
-
end
|
117
|
-
described_class.default_collation = "utf8_general_ci"
|
118
|
-
expect(@connection_called).to be_falsey
|
119
|
-
described_class.default_collation
|
120
|
-
expect(@connection_called).to be_truthy
|
121
|
-
end
|
122
|
-
end
|
25
|
+
context 'when explicitly set' do
|
26
|
+
before { described_class.default_collation = "utf8mb4_general_ci" }
|
27
|
+
after { described_class.default_collation = "utf8mb4_bin" }
|
28
|
+
it { is_expected.to eq("utf8mb4_general_ci") }
|
123
29
|
end
|
124
30
|
end
|
125
31
|
|
@@ -12,8 +12,6 @@ module Generators
|
|
12
12
|
module Migration
|
13
13
|
RSpec.describe Migrator do
|
14
14
|
subject { described_class.new }
|
15
|
-
let(:charset) { ::DeclareSchema.normalize_charset('utf8') }
|
16
|
-
let(:collation) { ::DeclareSchema.normalize_collation('utf8_general') } # adapt so that tests will pass on MySQL 5.7 or 8+
|
17
15
|
|
18
16
|
describe '#before_generating_migration' do
|
19
17
|
it 'requires a block be passed' do
|
@@ -31,7 +29,7 @@ module Generators
|
|
31
29
|
context 'when explicitly set' do
|
32
30
|
before { described_class.default_charset = "utf8" }
|
33
31
|
after { described_class.default_charset = "utf8mb4" }
|
34
|
-
it { should eq(
|
32
|
+
it { should eq("utf8") }
|
35
33
|
end
|
36
34
|
|
37
35
|
it 'should output deprecation warning' do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'pry'
|
3
|
+
require "bundler/setup"
|
4
|
+
require "declare_schema"
|
5
|
+
require "climate_control"
|
7
6
|
|
8
7
|
require_relative "./support/acceptance_spec_helpers"
|
9
8
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: declare_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0.colin.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Invoca Development adapted from hobo_fields by Tom Locke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-01-
|
11
|
+
date: 2024-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|