declare_schema 1.4.0.colin.9 → 1.4.0.colin.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/lib/declare_schema/model/index_definition.rb +1 -1
- data/lib/declare_schema/model.rb +17 -2
- data/lib/declare_schema/schema_change/column_add.rb +4 -2
- data/lib/declare_schema/version.rb +1 -1
- data/lib/declare_schema.rb +13 -3
- data/lib/generators/declare_schema/migration/migrator.rb +1 -1
- data/spec/lib/declare_schema/migration_generator_spec.rb +48 -0
- data/spec/lib/declare_schema_spec.rb +40 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13075fb086e36e6be6818fd28620cb9015c257083e994f68c216ca790e463896
|
4
|
+
data.tar.gz: 4668a054c8d87a7612ba739e3937a4faf817b3ac558083c8e0af59668aa1c42a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86d9f02bb9cabbb23ecec2eb68098b625b753b04890811858e4a43963d111ac54e5d2e10cd5468dfbdc2c6af39d1cab779002b033dbcbc05e869e4f0bc11f151
|
7
|
+
data.tar.gz: fbc233f25183279a309a23dc9afb395b4c4a47e52a95661126c99d9a9109100c5bd5ac3b200171fca479bd9c569f1a9aa34dbe15c79e8cfe50a95387f683ab7e
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,15 @@ Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0
|
|
10
10
|
### Changed
|
11
11
|
- Deprecate index: 'name' and unique: true|false in favor of index: { name: 'name', unique: true|false }.
|
12
12
|
|
13
|
+
## [1.3.6] - 2024-01-22
|
14
|
+
### Fixed
|
15
|
+
- Add missing commits around connection: and Array check for composite declared primary key.
|
16
|
+
|
17
|
+
## [1.3.5] - 2024-01-22
|
18
|
+
### Fixed
|
19
|
+
- Make `default_charset=` and `default_collation=` lazy so they don't use the database connection to check the
|
20
|
+
MySQL version. Instead, that is checked the first time `default_charset` or `default_collation` is called.
|
21
|
+
|
13
22
|
## [1.3.4] - 2024-01-18
|
14
23
|
### Fixed
|
15
24
|
- Add test for migrating `has_and_belongs_to_many` associations and fix them to properly declare their
|
data/Gemfile.lock
CHANGED
@@ -18,7 +18,7 @@ module DeclareSchema
|
|
18
18
|
|
19
19
|
def initialize(columns, table_name:, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil)
|
20
20
|
@table_name = table_name
|
21
|
-
@name = name || self.class.default_index_name(table_name, columns)
|
21
|
+
@name = (name || self.class.default_index_name(table_name, columns)).to_s
|
22
22
|
@columns = Array.wrap(columns).map(&:to_s)
|
23
23
|
@explicit_name = @name if !allow_equivalent
|
24
24
|
unique.in?([false, true]) or raise ArgumentError, "unique must be true or false: got #{unique.inspect}"
|
data/lib/declare_schema/model.rb
CHANGED
@@ -50,10 +50,23 @@ module DeclareSchema
|
|
50
50
|
|
51
51
|
module ClassMethods
|
52
52
|
def index(columns, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil)
|
53
|
-
|
53
|
+
index_definition = ::DeclareSchema::Model::IndexDefinition.new(
|
54
54
|
columns,
|
55
55
|
name: name, table_name: table_name, allow_equivalent: allow_equivalent, unique: unique, where: where, length: length
|
56
56
|
)
|
57
|
+
|
58
|
+
if (equivalent = index_definitions.find { index_definition.equivalent?(_1) }) # differs only by name
|
59
|
+
if equivalent == index_definition
|
60
|
+
# identical is always idempotent
|
61
|
+
else
|
62
|
+
# equivalent is idempotent iff allow_equivalent: true passed
|
63
|
+
allow_equivalent or
|
64
|
+
raise ArgumentError, "equivalent index definition found (pass allow_equivalent: true to ignore):\n" \
|
65
|
+
"#{index_definition.inspect}\n#{equivalent.inspect}"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
index_definitions << index_definition
|
69
|
+
end
|
57
70
|
end
|
58
71
|
|
59
72
|
def primary_key_index(*columns)
|
@@ -61,11 +74,13 @@ module DeclareSchema
|
|
61
74
|
end
|
62
75
|
|
63
76
|
def constraint(foreign_key_column, parent_table_name: nil, constraint_name: nil, parent_class_name: nil, dependent: nil)
|
64
|
-
|
77
|
+
constraint_definition = ::DeclareSchema::Model::ForeignKeyDefinition.new(
|
65
78
|
foreign_key_column.to_s,
|
66
79
|
constraint_name: constraint_name,
|
67
80
|
child_table_name: table_name, parent_table_name: parent_table_name, parent_class_name: parent_class_name, dependent: dependent
|
68
81
|
)
|
82
|
+
|
83
|
+
constraint_definitions << constraint_definition # Set<> implements idempotent insert.
|
69
84
|
end
|
70
85
|
|
71
86
|
# tell the migration generator to ignore the named index. Useful for existing indexes, or for indexes
|
@@ -6,8 +6,10 @@ module DeclareSchema
|
|
6
6
|
module SchemaChange
|
7
7
|
class ColumnAdd < Base
|
8
8
|
def initialize(table_name, column_name, column_type, **column_options)
|
9
|
-
|
10
|
-
|
9
|
+
table_name.is_a?(String) || table_name.is_a?(Symbol) or raise ArgumentError, "must provide String|Symbol table_name; got #{table_name.inspect}"
|
10
|
+
column_name.is_a?(String) || column_name.is_a?(Symbol) or raise ArgumentError, "must provide String|Symbol column_name; got #{column_name.inspect}"
|
11
|
+
@table_name = table_name
|
12
|
+
@column_name = column_name
|
11
13
|
@column_type = column_type or raise ArgumentError, "must provide column_type"
|
12
14
|
@column_options = column_options
|
13
15
|
end
|
data/lib/declare_schema.rb
CHANGED
@@ -36,7 +36,7 @@ module DeclareSchema
|
|
36
36
|
|
37
37
|
class << self
|
38
38
|
attr_writer :mysql_version
|
39
|
-
attr_reader :
|
39
|
+
attr_reader :default_text_limit, :default_string_limit, :default_null,
|
40
40
|
:default_generate_foreign_keys, :default_generate_indexing, :db_migrate_command,
|
41
41
|
:max_index_and_constraint_name_length
|
42
42
|
|
@@ -81,12 +81,22 @@ module DeclareSchema
|
|
81
81
|
|
82
82
|
def default_charset=(charset)
|
83
83
|
charset.is_a?(String) or raise ArgumentError, "charset must be a string (got #{charset.inspect})"
|
84
|
-
@
|
84
|
+
@default_charset_before_normalization = charset
|
85
|
+
@default_charset = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_charset
|
89
|
+
@default_charset ||= normalize_charset(@default_charset_before_normalization)
|
85
90
|
end
|
86
91
|
|
87
92
|
def default_collation=(collation)
|
88
93
|
collation.is_a?(String) or raise ArgumentError, "collation must be a string (got #{collation.inspect})"
|
89
|
-
@
|
94
|
+
@default_collation_before_normalization = collation
|
95
|
+
@default_collation = nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_collation
|
99
|
+
@default_collation ||= normalize_collation(@default_collation_before_normalization)
|
90
100
|
end
|
91
101
|
|
92
102
|
def default_text_limit=(text_limit)
|
@@ -352,7 +352,7 @@ module Generators
|
|
352
352
|
|
353
353
|
db_columns = model.connection.columns(current_table_name).index_by(&:name)
|
354
354
|
if (pk = model._declared_primary_key.presence)
|
355
|
-
pk_was_in_db_columns = db_columns.delete(pk)
|
355
|
+
pk_was_in_db_columns = pk.is_a?(Array) || db_columns.delete(pk)
|
356
356
|
end
|
357
357
|
|
358
358
|
model_column_names = model.field_specs.keys.map(&:to_s)
|
@@ -1437,5 +1437,53 @@ RSpec.describe 'DeclareSchema Migration Generator' do
|
|
1437
1437
|
end
|
1438
1438
|
end
|
1439
1439
|
end
|
1440
|
+
|
1441
|
+
context 'index' do
|
1442
|
+
before do
|
1443
|
+
class Advert < active_record_base_class.constantize
|
1444
|
+
declare_schema { }
|
1445
|
+
belongs_to :ad_category
|
1446
|
+
end
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
it "is idempotent and doesn't raise" do
|
1450
|
+
expect do
|
1451
|
+
Advert.index [:ad_category_id], name: :index_adverts_on_ad_category_id
|
1452
|
+
end.to_not change { Advert.index_definitions.size }
|
1453
|
+
end
|
1454
|
+
|
1455
|
+
it "when equivalent but not marked to allow, it raises" do
|
1456
|
+
expect do
|
1457
|
+
Advert.index [:ad_category_id], name: :on_ad_category_id
|
1458
|
+
end.to raise_exception(ArgumentError, /equivalent index definition found/i)
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
it "when equivalent and marked to allow, it is idempotent and doesn't raise" do
|
1462
|
+
expect do
|
1463
|
+
Advert.index [:ad_category_id], name: :on_ad_category_id, allow_equivalent: true
|
1464
|
+
end.to_not change { Advert.index_definitions.size }
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
context 'constraint' do
|
1468
|
+
before do
|
1469
|
+
class Advert < active_record_base_class.constantize
|
1470
|
+
declare_schema { }
|
1471
|
+
belongs_to :ad_category
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
|
1475
|
+
it "when exactly equal, it is idempotent and doesn't raise" do
|
1476
|
+
expect do
|
1477
|
+
Advert.constraint :ad_category_id, parent_table_name: 'ad_categories', constraint_name: :index_adverts_on_ad_category_id, parent_class_name: 'AdCategory'
|
1478
|
+
end.to_not change { Advert.index_definitions.size }
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
it "when equivalent, it is idempotent and doesn't raise" do
|
1482
|
+
expect do
|
1483
|
+
Advert.constraint :ad_category_id, parent_table_name: 'ad_categories', constraint_name: :constraint_1, parent_class_name: 'AdCategory'
|
1484
|
+
end.to_not change { Advert.index_definitions.size }
|
1485
|
+
end
|
1486
|
+
end
|
1487
|
+
end
|
1440
1488
|
end
|
1441
1489
|
end
|
@@ -37,6 +37,26 @@ RSpec.describe DeclareSchema do
|
|
37
37
|
it { is_expected.to eq("utf8mb3") }
|
38
38
|
end
|
39
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
|
59
|
+
end
|
40
60
|
end
|
41
61
|
|
42
62
|
describe '#default_collation' do
|
@@ -81,6 +101,26 @@ RSpec.describe DeclareSchema do
|
|
81
101
|
it { is_expected.to eq("utf8mb3_general_ci") }
|
82
102
|
end
|
83
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
|
123
|
+
end
|
84
124
|
end
|
85
125
|
|
86
126
|
describe '#default_text_limit' do
|
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.
|
4
|
+
version: 1.4.0.colin.11
|
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-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|