diff --git a/config/initializers/db_encoding.rb b/config/initializers/db_encoding.rb new file mode 100644 index 0000000..7ee0780 --- /dev/null +++ b/config/initializers/db_encoding.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Only applicable for MySQL +if ActiveRecord::Base.connection_config[:adapter] == 'mysql2' + # Get the configured encoding + configured_encoding = ActiveRecord::Base.connection_config[:encoding] + + # Get the actual character set from the DB + database_charset = ActiveRecord::Base.connection.exec_query('SELECT @@character_set_database as charset').first['charset'] + + msg = <<~LOG + WARNING: The configured db encoding `#{configured_encoding}` is different from the actual one `#{database_charset}`! + This is likely to cause issues with special characters. + Please see https://maestrano.atlassian.net/wiki/x/rQ0nBg or run: + $ rails g connector:charset_migration + LOG + + if configured_encoding != database_charset + Rails.logger.warn msg + warn msg + end +end diff --git a/lib/generators/connector/charset_migration/charset_migration_generator.rb b/lib/generators/connector/charset_migration/charset_migration_generator.rb new file mode 100644 index 0000000..d184f17 --- /dev/null +++ b/lib/generators/connector/charset_migration/charset_migration_generator.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails/generators/named_base' +require 'rails/generators/active_record/migration' + +module Connector + module Generators + class CharsetMigrationGenerator < ::Rails::Generators::Base + include ActiveRecord::Generators::Migration + + source_root File.expand_path('templates', __dir__) + + def copy_migration + migration_template 'migration.rb', 'db/migrate/convert_tables_to_utf8.rb' + end + end + end +end diff --git a/lib/generators/connector/charset_migration/templates/migration.rb b/lib/generators/connector/charset_migration/templates/migration.rb new file mode 100644 index 0000000..7efb1d2 --- /dev/null +++ b/lib/generators/connector/charset_migration/templates/migration.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class ConvertTablesToUtf8 < ActiveRecord::Migration + def change_encoding(encoding, collation) + # Allow for different adapter in different environment + unless ActiveRecord::Base.connection_config[:adapter] == 'mysql2' + say "Skipping conversion as non MySQL database (#{ActiveRecord::Base.connection_config[:adapter]})" + return + end + tables = connection.tables + dbname = ActiveRecord::Base.connection_config[:database] + say_with_time "Converting database to #{encoding}" do + execute <<-SQL + ALTER DATABASE `#{dbname}` CHARACTER SET #{encoding} COLLATE #{collation}; + SQL + end + tables.each do |tablename| + say_with_time "Converting table `#{tablename}` to #{encoding}" do + execute <<-SQL + ALTER TABLE `#{dbname}`.`#{tablename}` CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation}; + SQL + end + end + end + + def change + reversible do |dir| + dir.up do + change_encoding('utf8', 'utf8_general_ci') + end + dir.down do + change_encoding('latin1', 'latin1_swedish_ci') + end + end + end +end