declare_schema 1.3.2.rp.1 → 1.3.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 177fdef8d03843627f34a461487ec92d222e5d18efe3a4881bc1b4326a069e99
4
- data.tar.gz: d5dac684d51bfad5e7e92214fcc9a7e1b4020a70aa4cd2fd8a5bbb0c718f1c71
3
+ metadata.gz: 2cc1b63a3d66a299428ec32493d79aa3ef2a3953a663c66c661887f28dffe96e
4
+ data.tar.gz: 6712668fe9c41feb156cd0127ceacf57802bbb17c633da408038a0f5b8067509
5
5
  SHA512:
6
- metadata.gz: 7bdc6408f561f9aa70dad7e2208ae2022f8b30adce1c1350f598cae1c93b4dbd9f65f61a97324282fad9f0d2dd2126e90dda199781040f08564bc6998121c670
7
- data.tar.gz: 1057a1c6202b77f5854b119208227c7a7341f2c3d0cab7eb7a743322ebb60bddaec4eb77671d60035e610789a9d73c7b345868262aebe0e6052ff2c17c8a6d81
6
+ metadata.gz: ad29f584d6b7bd42b6e5b547578b8a0004a5602376e015117b811e726c8d62d2b69bb97a1af32af1635788e6b18a9cfbbc89e185ee496fac3e35567246c9185d
7
+ data.tar.gz: 14fc6510af10b9158919f23d8125f9d15cd2c4b34b5cb81ee990332fa924a82f52ca41e08c514be2157539900a10ea19238f0be49ec9fe8ec9c5fb404b0e2b3d
data/CHANGELOG.md CHANGED
@@ -4,7 +4,12 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4
4
 
5
5
  Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [1.3.2] - Unreleased
7
+ ## [1.3.3] - Unreleased
8
+ ### Fixed
9
+ - Fix a MySQL 8 bug where MySQL 8+ renames charset 'utf8' to 'utf8mb3' and collation 'utf8_general_ci' to
10
+ 'utf8mb3_unicode_ci'.
11
+
12
+ ## [1.3.2] - 2024-01-12
8
13
  ### Fixed
9
14
  - Fix bug in migrator when table option definitions differ
10
15
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (1.3.2.rp.1)
4
+ declare_schema (1.3.3.colin.1)
5
5
  rails (>= 5.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -213,6 +213,9 @@ turn all tables into `utf8mb4` supporting tables:
213
213
  DeclareSchema.default_charset = "utf8mb4"
214
214
  DeclareSchema.default_collation = "utf8mb4_bin"
215
215
  ```
216
+ Note: MySQL 8+ aliases charset 'utf8' to 'utf8mb3', and 'utf8_general_ci' to 'utf8mb3_unicode_ci',
217
+ so when running on MySQL 8+, those aliases will be applied by `DeclareSchema`.
218
+
216
219
  #### db:migrate Command
217
220
  `declare_schema` can run the migration once it is generated, if the `--migrate` option is passed.
218
221
  If not, it will display the command to run later. By default this command is
@@ -107,7 +107,9 @@ module DeclareSchema
107
107
  if @type.in?([:text, :string])
108
108
  if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
109
109
  @options[:charset] ||= model._table_options&.[](:charset) || ::DeclareSchema.default_charset
110
+ @options[:charset] = DeclareSchema.normalize_charset(@options[:charset])
110
111
  @options[:collation] ||= model._table_options&.[](:collation) || ::DeclareSchema.default_collation
112
+ @options[:collation] = DeclareSchema.normalize_collation(@options[:collation])
111
113
  else
112
114
  @options.delete(:charset)
113
115
  @options.delete(:collation)
@@ -50,7 +50,17 @@ module DeclareSchema
50
50
 
51
51
  def initialize(table_name, **table_options)
52
52
  @table_name = table_name
53
- @table_options = table_options
53
+ @table_options = table_options.each_with_object({}) do |(k, v),result|
54
+ result[k] =
55
+ case k
56
+ when :charset
57
+ DeclareSchema.normalize_charset(v)
58
+ when :collation
59
+ DeclareSchema.normalize_collation(v)
60
+ else
61
+ v
62
+ end
63
+ end
54
64
  end
55
65
 
56
66
  def to_key
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeclareSchema
4
- VERSION = "1.3.2.rp.1"
4
+ VERSION = "1.3.3.colin.1"
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'active_support'
4
4
  require 'active_support/all'
5
5
  require_relative 'declare_schema/version'
6
+ require 'rubygems/version'
6
7
 
7
8
  ActiveSupport::Dependencies.autoload_paths |= [__dir__]
8
9
 
@@ -21,6 +22,8 @@ module DeclareSchema
21
22
  text: String
22
23
  }.freeze
23
24
 
25
+ SEMVER_8 = Gem::Version.new('8.0.0').freeze
26
+
24
27
  @default_charset = "utf8mb4"
25
28
  @default_collation = "utf8mb4_bin"
26
29
  @default_text_limit = 0xffff_ffff
@@ -32,6 +35,7 @@ module DeclareSchema
32
35
  @max_index_and_constraint_name_length = 64 # limit for MySQL
33
36
 
34
37
  class << self
38
+ attr_writer :mysql_version
35
39
  attr_reader :default_charset, :default_collation, :default_text_limit, :default_string_limit, :default_null,
36
40
  :default_generate_foreign_keys, :default_generate_indexing, :db_migrate_command,
37
41
  :max_index_and_constraint_name_length
@@ -47,14 +51,42 @@ module DeclareSchema
47
51
  end
48
52
  end
49
53
 
54
+ def mysql_version
55
+ if defined?(@mysql_version)
56
+ @mysql_version
57
+ else
58
+ @mysql_version =
59
+ if ActiveRecord::Base.connection.class.name.match?(/mysql/i)
60
+ version_string = ActiveRecord::Base.connection.select_value('SELECT VERSION()')
61
+ Gem::Version.new(version_string)
62
+ end
63
+ end
64
+ end
65
+
66
+ def normalize_charset(charset)
67
+ if mysql_version && mysql_version >= SEMVER_8 && charset == 'utf8'
68
+ 'utf8mb3'
69
+ else
70
+ charset
71
+ end
72
+ end
73
+
74
+ def normalize_collation(collation)
75
+ if mysql_version && mysql_version >= SEMVER_8
76
+ collation.sub(/\Autf8_/, 'utf8mb3_')
77
+ else
78
+ collation
79
+ end
80
+ end
81
+
50
82
  def default_charset=(charset)
51
83
  charset.is_a?(String) or raise ArgumentError, "charset must be a string (got #{charset.inspect})"
52
- @default_charset = charset
84
+ @default_charset = normalize_charset(charset)
53
85
  end
54
86
 
55
87
  def default_collation=(collation)
56
88
  collation.is_a?(String) or raise ArgumentError, "collation must be a string (got #{collation.inspect})"
57
- @default_collation = collation
89
+ @default_collation = normalize_collation(collation)
58
90
  end
59
91
 
60
92
  def default_text_limit=(text_limit)
@@ -5,6 +5,11 @@ begin
5
5
  rescue LoadError
6
6
  end
7
7
 
8
+ begin
9
+ require 'sqlite3'
10
+ rescue LoadError
11
+ end
12
+
8
13
  RSpec.describe DeclareSchema::Model::FieldSpec do
9
14
  let(:model) { double('model', _table_options: {}, _declared_primary_key: 'id') }
10
15
  let(:col_spec) { double('col_spec', type: :string) }
@@ -58,8 +63,23 @@ RSpec.describe DeclareSchema::Model::FieldSpec do
58
63
  end
59
64
  end
60
65
 
61
- it 'raises error when default_string_limit option is nil when not explicitly set in field spec' do
62
- if defined?(Mysql2)
66
+ if defined?(Mysql2)
67
+ context 'when running on MySQL 8.0' do
68
+ around do |spec|
69
+ DeclareSchema.mysql_version = '8.0.21'
70
+ spec.run
71
+ ensure
72
+ DeclareSchema.remove_instance_variable('@mysql_version') rescue nil
73
+ end
74
+
75
+ it 'normalizes charset and collation' do
76
+ subject = described_class.new(model, :title, :string, limit: 100, null: true, charset: 'utf8', collation: 'utf8_general', position: 0)
77
+
78
+ expect(subject.schema_attributes(col_spec)).to eq(type: :string, limit: 100, null: true, charset: 'utf8mb3', collation: 'utf8mb3_general')
79
+ end
80
+ end
81
+
82
+ it 'raises error when default_string_limit option is nil when not explicitly set in field spec' do
63
83
  expect(::DeclareSchema).to receive(:default_string_limit) { nil }
64
84
  expect do
65
85
  described_class.new(model, :title, :string, null: true, charset: 'utf8mb4', position: 0)
@@ -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.3.2.rp.1
4
+ version: 1.3.3.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-12 00:00:00.000000000 Z
11
+ date: 2024-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails