Module: MigrationExtensions::EncodingChanges

Defined in:
lib/migration_extensions/encoding_changes.rb

Overview

Include in an ActiveRecord::Migration to add the ability to easily migrate schema encodings using change_encoding

Constant Summary collapse

ENCODING_COLLATIONS =

Default collation for listed character encodings

{
  'latin1' => 'latin1_swedish_ci',
  'utf8mb4' => 'utf8mb4_unicode_ci',
  'utf8' => 'utf8_general_ci'
}.freeze
DEFAULT_TARGET_ROW_FORMAT =
'DYNAMIC'
DEFAULT_SOURCE_ROW_FORMAT =
'COMPACT'

Instance Method Summary collapse

Instance Method Details

#alter_encoding(table, row_format, character_set, collation) ⇒ Object

rubocop:enable Metrics/MethodLength



58
59
60
61
62
63
64
# File 'lib/migration_extensions/encoding_changes.rb', line 58

def alter_encoding(table, row_format, character_set, collation)
  say "Updating Encoding on #{table}"
  say "Update row format to #{row_format}", :subitem
  connection.execute("ALTER TABLE #{table} ROW_FORMAT=#{row_format}")
  say "Convert character set to #{character_set}, collation #{collation}", :subitem
  connection.execute("ALTER TABLE #{table} CONVERT TO CHARACTER SET #{character_set} COLLATE #{collation}")
end

#change_encoding(table, from:, to:) ⇒ void

Note:

DYNAMIC row formats are the 5.7 defaults, and allow for larger indexes. This is important as otherwise it reduces the max size of an indexed varchar column from 255 to 191 when dealing with utf8mb4 characters.

This method returns an undefined value.

Converts the table to a new character_encoding. Can be used in a reversible ‘change’ migration rubocop:todo Metrics/MethodLength

Examples:

migrating a table from latin1 to utf8mb4

change_encoding 'study_metadata', from: 'latin1', to: 'utf8mb4'

Parameters:

  • table (String)

    The name of the table to convert

  • to (String)

    The target character set of the converted table, or a hash of options

  • from (String, Hash)

    The current character set, or a hash of options. Used in the event of a down migration.

Options Hash (from:):

  • character_set: (String)

    The current character set of the table

  • collation: (String)

    The current colaltion set of the table. Default based on ENCODING_COLLATIONS

  • row_format: (String)

    The current row_format of the table (COMPACT by default)

Options Hash (to:):

  • character_set: (String)

    The target character set of the converted table

  • collation: (String)

    The target colaltion set of the converted table. Default based on ENCODING_COLLATIONS

  • row_format: (String)

    The row_format of the target table (DYNAMIC by default)



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/migration_extensions/encoding_changes.rb', line 36

def change_encoding(table, from:, to:) # rubocop:todo Metrics/AbcSize
  from_options = from.is_a?(String) ? { character_set: from } : from
  to_options = to.is_a?(String) ? { character_set: to } : to

  reversible do |dir|
    dir.up do
      row_format = to_options.fetch(:row_format, DEFAULT_TARGET_ROW_FORMAT)
      character_set = to_options.fetch(:character_set)
      collation = to_options.fetch(:collation, ENCODING_COLLATIONS[character_set])
      alter_encoding(table, row_format, character_set, collation)
    end
    dir.down do
      row_format = from_options.fetch(:row_format, DEFAULT_SOURCE_ROW_FORMAT)
      character_set = from_options.fetch(:character_set)
      collation = from_options.fetch(:collation, ENCODING_COLLATIONS[character_set])
      alter_encoding(table, row_format, character_set, collation)
    end
  end
end