declare_schema 1.4.0.colin.9 → 1.4.0.colin.11

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 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