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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e20de5eeec8ea9436d2fd674f5ff33f20888cfb87e17456fd278a38504bbede
4
- data.tar.gz: 259d8dd463292836e40d3fe07261743e714d588440d8a988183daa32f0c8a4d9
3
+ metadata.gz: 13075fb086e36e6be6818fd28620cb9015c257083e994f68c216ca790e463896
4
+ data.tar.gz: 4668a054c8d87a7612ba739e3937a4faf817b3ac558083c8e0af59668aa1c42a
5
5
  SHA512:
6
- metadata.gz: 18dc843b60c81ace18bc692f1e8d76038d50695081ab846b14f0653aa4d6a755666417f4d7190429aa83e9eb9fffba02d61c71b2a5c44ef7dbf69baf401e7e31
7
- data.tar.gz: 94bf1af85ecdc252e08f6453018edc6a2f216e65aa6d7fce0ab7399058097d6a0e1a834e02d350789e8e6fb3485050979dde543e2036e048cc914dd6ffb5cdad
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (1.4.0.colin.9)
4
+ declare_schema (1.4.0.colin.11)
5
5
  rails (>= 5.0)
6
6
 
7
7
  GEM
@@ -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}"
@@ -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
- index_definitions << ::DeclareSchema::Model::IndexDefinition.new(
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
- constraint_definitions << ::DeclareSchema::Model::ForeignKeyDefinition.new(
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
- @table_name = table_name or raise ArgumentError, "must provide table_name"
10
- @column_name = column_name or raise ArgumentError, "must provide column_name"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "1.4.0.colin.9"
4
+ VERSION = "1.4.0.colin.11"
5
5
  end
@@ -36,7 +36,7 @@ module DeclareSchema
36
36
 
37
37
  class << self
38
38
  attr_writer :mysql_version
39
- attr_reader :default_charset, :default_collation, :default_text_limit, :default_string_limit, :default_null,
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
- @default_charset = normalize_charset(charset)
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
- @default_collation = normalize_collation(collation)
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.9
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-20 00:00:00.000000000 Z
11
+ date: 2024-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails