declare_schema 1.4.0.colin.7 → 1.4.0.colin.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,6 +11,7 @@ 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 }
14
15
 
15
16
  context 'Using declare_schema' do
16
17
  before do
@@ -34,23 +35,19 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
34
35
  end
35
36
  end
36
37
 
38
+ # TODO: create model_spec.rb and move the Model specs below into it. -Colin
37
39
  describe 'instance methods' do
38
40
  let(:model) { model_class.new }
41
+ let(:table_name) { "index_definition_test_models" }
39
42
  let(:fields) { ['last_name', 'first_name'] }
40
- let(:options) { {} }
41
- subject(:instance) { described_class.new(model_class, fields, **options) }
43
+ let(:options) { { table_name: table_name } }
44
+ subject(:instance) { described_class.new(fields, **options) }
42
45
 
43
46
  describe 'attr_readers' do
44
- describe '#table' do
45
- subject { instance.table }
47
+ describe '#table_name' do
48
+ subject { instance.table_name }
46
49
 
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
50
+ it { is_expected.to eq(table_name) }
54
51
  end
55
52
 
56
53
  describe '#fields' do
@@ -62,18 +59,22 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
62
59
  describe '#explicit_name' do
63
60
  subject { instance.explicit_name }
64
61
 
65
- it { is_expected.to eq(nil) }
62
+ context 'with allow_equivalent' do
63
+ let(:options) { { table_name: table_name, allow_equivalent: true } }
64
+
65
+ it { is_expected.to eq(nil) }
66
+ end
66
67
 
67
68
  context 'with name option' do
68
- let(:options) { { name: 'index_auth_users_on_last_name_and_first_name' } }
69
+ let(:options) { { table_name: table_name, name: 'index_auth_users_on_names' } }
69
70
 
70
- it { is_expected.to eq('index_auth_users_on_last_name_and_first_name') }
71
+ it { is_expected.to eq('index_auth_users_on_names') }
71
72
  end
72
73
  end
73
74
 
74
75
  describe '#length' do
75
76
  subject { instance.length }
76
- let(:options) { { length: length } }
77
+ let(:options) { { table_name: table_name, length: length } }
77
78
 
78
79
  context 'with integer length' do
79
80
  let(:length) { 2 }
@@ -90,9 +91,9 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
90
91
 
91
92
  describe '#options' do
92
93
  subject { instance.options }
93
- let(:options) { { name: 'my_index', unique: false, where: "(name like 'a%')", length: 10 } }
94
+ let(:options) { { name: 'my_index', table_name: table_name, unique: false, where: "(name like 'a%')", length: 10 } }
94
95
 
95
- it { is_expected.to eq(options) }
96
+ it { is_expected.to eq(options.except(:table_name)) }
96
97
  end
97
98
 
98
99
  describe '#with_name' do
@@ -105,33 +106,25 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
105
106
  end
106
107
  end
107
108
 
108
- describe 'class methods' do
109
- let(:model) { model_class.new }
110
-
111
- describe 'index_definitions' do
112
- it do
113
- expect(model_class.index_definitions.size).to eq(1)
109
+ describe 'Model class methods' do
110
+ describe '.has index_definitions' do
111
+ subject { model_class.index_definitions }
114
112
 
115
- sample = model_class.index_definitions.to_a.first
116
- expect(sample.name).to eq('index_index_definition_test_models_on_name')
117
- expect(sample.fields).to eq(['name'])
118
- expect(sample.unique).to eq(false)
113
+ it 'returns indexes without primary key' do
114
+ expect(subject.map(&:to_key)).to eq([
115
+ ['index_index_definition_test_models_on_name', ['name'], { length: nil, unique: false, where: nil }],
116
+ ])
119
117
  end
120
118
  end
121
119
 
122
- describe 'has index_definitions_with_primary_key' do
123
- it do
124
- expect(model_class.index_definitions_with_primary_key).to be_kind_of(Set)
125
- result = model_class.index_definitions_with_primary_key.sort_by(&:name)
126
- expect(result.size).to eq(2)
120
+ describe '.has index_definitions_with_primary_key' do
121
+ subject { model_class.index_definitions_with_primary_key }
127
122
 
128
- expect(result[0].name).to eq('PRIMARY')
129
- expect(result[0].fields).to eq(['id'])
130
- expect(result[0].unique).to eq(true)
131
-
132
- expect(result[1].name).to eq('index_index_definition_test_models_on_name')
133
- expect(result[1].fields).to eq(['name'])
134
- expect(result[1].unique).to eq(false)
123
+ it 'returns indexes with primary key' do
124
+ expect(subject.map(&:to_key)).to eq([
125
+ ['index_index_definition_test_models_on_name', ['name'], { length: nil, unique: false, where: nil }],
126
+ ['PRIMARY', ['id'], { length: nil, unique: true, where: nil }],
127
+ ])
135
128
  end
136
129
  end
137
130
  end
@@ -147,6 +140,11 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
147
140
  ActiveRecord::Base.connection.execute <<~EOS
148
141
  CREATE UNIQUE INDEX index_definition_test_models_on_name ON index_definition_test_models(name)
149
142
  EOS
143
+ if defined?(Mysql2)
144
+ ActiveRecord::Base.connection.execute <<~EOS
145
+ CREATE INDEX index_definition_test_models_on_name_partial ON index_definition_test_models(name(10))
146
+ EOS
147
+ end
150
148
  ActiveRecord::Base.connection.execute <<~EOS
151
149
  CREATE TABLE index_definition_compound_index_models (
152
150
  fk1_id INTEGER NOT NULL,
@@ -157,29 +155,38 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do
157
155
  ActiveRecord::Base.connection.schema_cache.clear!
158
156
  end
159
157
 
160
- describe 'for_model' do
161
- subject { described_class.for_model(model_class) }
158
+ describe 'for_table' do
159
+ let(:ignore_indexes) { model_class.ignore_indexes }
160
+ subject { described_class.for_table(model_class.table_name, ignore_indexes, model_class.connection) }
162
161
 
163
162
  context 'with single-column PK' do
164
163
  it 'returns the indexes for the model' do
165
- expect(subject.size).to eq(2), subject.inspect
166
- expect(subject[0].name).to eq('index_definition_test_models_on_name')
167
- expect(subject[0].columns).to eq(['name'])
168
- expect(subject[0].unique).to eq(true)
169
- expect(subject[1].name).to eq('PRIMARY')
170
- expect(subject[1].columns).to eq(['id'])
171
- expect(subject[1].unique).to eq(true)
164
+ expect(subject.map(&:to_key)).to eq([
165
+ ["index_definition_test_models_on_name", ["name"], { unique: true, where: nil, length: nil }],
166
+ (["index_definition_test_models_on_name_partial", ["name"], { unique: false, where: nil, length: 10 }] if defined?(Mysql2)),
167
+ ["PRIMARY", ["id"], { unique: true, where: nil, length: nil }]
168
+ ].compact)
172
169
  end
173
170
  end
174
171
 
175
- context 'with compound-column PK' do
172
+ context 'with composite (multi-column) PK' do
176
173
  let(:model_class) { IndexDefinitionCompoundIndexModel }
177
174
 
178
175
  it 'returns the indexes for the model' do
179
- expect(subject.size).to eq(1), subject.inspect
180
- expect(subject[0].name).to eq('PRIMARY')
181
- expect(subject[0].columns).to eq(['fk1_id', 'fk2_id'])
182
- expect(subject[0].unique).to eq(true)
176
+ expect(subject.map(&:to_key)).to eq([
177
+ ["PRIMARY", ["fk1_id", "fk2_id"], { length: nil, unique: true, where: nil }]
178
+ ])
179
+ end
180
+ end
181
+
182
+ context 'with ignored_indexes' do
183
+ let(:ignore_indexes) { ['index_definition_test_models_on_name'] }
184
+
185
+ it 'skips the ignored index' do
186
+ expect(subject.map(&:to_key)).to eq([
187
+ (["index_definition_test_models_on_name_partial", ["name"], { unique: false, where: nil, length: 10 }] if defined?(Mysql2)),
188
+ ["PRIMARY", ["id"], { length: nil, unique: true, where: nil }]
189
+ ].compact)
183
190
  end
184
191
  end
185
192
  end
@@ -9,6 +9,8 @@ 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+
12
14
 
13
15
  context 'Using declare_schema' do
14
16
  before do
@@ -27,27 +29,45 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
27
29
 
28
30
  describe '#to_key' do
29
31
  subject { model.to_key }
30
- it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}']) }
32
+ it { is_expected.to eq(['table_options_definition_test_models', "{:charset=>#{charset.inspect}, :collation=>#{collation.inspect}}"]) }
31
33
  end
32
34
 
33
35
  describe '#settings' do
34
36
  subject { model.settings }
35
- it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
37
+ it { is_expected.to eq("CHARACTER SET #{charset} COLLATE #{collation}") }
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
36
56
  end
37
57
 
38
58
  describe '#hash' do
39
59
  subject { model.hash }
40
- it { should eq(['table_options_definition_test_models', '{:charset=>"utf8", :collation=>"utf8_general"}'].hash) }
60
+ it { is_expected.to eq(['table_options_definition_test_models', "{:charset=>#{charset.inspect}, :collation=>#{collation.inspect}}"].hash) }
41
61
  end
42
62
 
43
63
  describe '#to_s' do
44
64
  subject { model.to_s }
45
- it { should eq("CHARACTER SET utf8 COLLATE utf8_general") }
65
+ it { is_expected.to eq("CHARACTER SET #{charset} COLLATE #{collation}") }
46
66
  end
47
67
 
48
68
  describe '#alter_table_statement' do
49
69
  subject { model.alter_table_statement }
50
- it { should match(/execute "ALTER TABLE .*table_options_definition_test_models.* CHARACTER SET utf8 COLLATE utf8_general"/) }
70
+ it { is_expected.to match(/execute "ALTER TABLE .*table_options_definition_test_models.* CHARACTER SET #{charset} COLLATE #{collation}"/) }
51
71
  end
52
72
  end
53
73
 
@@ -67,7 +87,7 @@ RSpec.describe DeclareSchema::Model::TableOptionsDefinition do
67
87
  generate_migrations '-n', '-m'
68
88
  end
69
89
 
70
- it { should eq(described_class.new(model_class.table_name, **options)) }
90
+ it { is_expected.to eq(described_class.new(model_class.table_name, **options)) }
71
91
  end
72
92
  end
73
93
  end
@@ -8,10 +8,34 @@ RSpec.describe DeclareSchema do
8
8
  it { is_expected.to eq("utf8mb4") }
9
9
  end
10
10
 
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") }
11
+ context 'when running on MySQL 5.7' do
12
+ around do |spec|
13
+ described_class.mysql_version = Gem::Version.new('5.7.48')
14
+ spec.run
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
15
39
  end
16
40
  end
17
41
 
@@ -22,10 +46,40 @@ RSpec.describe DeclareSchema do
22
46
  it { is_expected.to eq("utf8mb4_bin") }
23
47
  end
24
48
 
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") }
49
+ context 'when running on MySQL 5.7' do
50
+ around do |spec|
51
+ described_class.mysql_version = Gem::Version.new('5.7.48')
52
+ spec.run
53
+ ensure
54
+ described_class.remove_instance_variable('@mysql_version')
55
+ end
56
+
57
+ context 'when explicitly set' do
58
+ before { described_class.default_collation = "utf8_general_ci" }
59
+ after { described_class.default_collation = "utf8mb4_bin" }
60
+ it { is_expected.to eq("utf8_general_ci") }
61
+ end
62
+ end
63
+
64
+ context 'when running on MySQL 8.0' do
65
+ around do |spec|
66
+ described_class.mysql_version = Gem::Version.new('8.0.21')
67
+ spec.run
68
+ ensure
69
+ described_class.remove_instance_variable('@mysql_version')
70
+ end
71
+
72
+ context 'when explicitly set without _ci' do
73
+ before { described_class.default_collation = "utf8_general" }
74
+ after { described_class.default_collation = "utf8mb4_bin" }
75
+ it { is_expected.to eq("utf8mb3_general") }
76
+ end
77
+
78
+ context 'when explicitly set with _ci' do
79
+ before { described_class.default_collation = "utf8_general_ci" }
80
+ after { described_class.default_collation = "utf8mb4_bin" }
81
+ it { is_expected.to eq("utf8mb3_general_ci") }
82
+ end
29
83
  end
30
84
  end
31
85
 
@@ -12,6 +12,8 @@ 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+
15
17
 
16
18
  describe '#before_generating_migration' do
17
19
  it 'requires a block be passed' do
@@ -29,7 +31,7 @@ module Generators
29
31
  context 'when explicitly set' do
30
32
  before { described_class.default_charset = "utf8" }
31
33
  after { described_class.default_charset = "utf8mb4" }
32
- it { should eq("utf8") }
34
+ it { should eq(charset) }
33
35
  end
34
36
 
35
37
  it 'should output deprecation warning' do
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
- require "declare_schema"
5
- require "climate_control"
3
+ require 'bundler/setup'
4
+ require 'declare_schema'
5
+ require 'climate_control'
6
+ require 'pry'
6
7
 
7
8
  require_relative "./support/acceptance_spec_helpers"
8
9
 
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.0.colin.7
4
+ version: 1.4.0.colin.8
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-16 00:00:00.000000000 Z
11
+ date: 2024-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails