declare_schema 1.3.2 → 1.3.3.colin.1

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: 474856e02a14224230a41cc4ef32234b8d20b69a647a30f810bce457c220261e
4
- data.tar.gz: 13994a873d83d5bce533b71f36c3057a0a0caf8c7559f809091a7dc6627f5f7c
3
+ metadata.gz: 2cc1b63a3d66a299428ec32493d79aa3ef2a3953a663c66c661887f28dffe96e
4
+ data.tar.gz: 6712668fe9c41feb156cd0127ceacf57802bbb17c633da408038a0f5b8067509
5
5
  SHA512:
6
- metadata.gz: 7b298b54b826e8bb464c544ab2015ddca0a761cda03f03724598158617b89cef0b0f19521a103898e92157cad11d32e9feb71c1293a36bbc2c3a666c123d444f
7
- data.tar.gz: 5e0c12a370ed83eeb31f398e124597a00dd7b5872d08b8c47e1eb2fb5842c6b295b251d2b58ff26619af8c92ca0342ac8bf585652c9822409dfab40798d0f086
6
+ metadata.gz: ad29f584d6b7bd42b6e5b547578b8a0004a5602376e015117b811e726c8d62d2b69bb97a1af32af1635788e6b18a9cfbbc89e185ee496fac3e35567246c9185d
7
+ data.tar.gz: 14fc6510af10b9158919f23d8125f9d15cd2c4b34b5cb81ee990332fa924a82f52ca41e08c514be2157539900a10ea19238f0be49ec9fe8ec9c5fb404b0e2b3d
data/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@ 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.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
+
7
12
  ## [1.3.2] - 2024-01-12
8
13
  ### Fixed
9
14
  - Fix bug in migrator when table option definitions differ
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- declare_schema (1.3.2)
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"
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
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