From 8246b593bff71f2cebf274c133bb8917f1e094c8 Mon Sep 17 00:00:00 2001
From: Sean Griffin <sean@seantheprogrammer.com>
Date: Thu, 19 Nov 2015 09:30:18 -0700
Subject: Allow specifying the default table options for mysql adapters

It's often the case that you want to have an option that you cannot
specify at the database level, but want applied to *all* tables that you
create. For example, you might want to specify `ROW_FORMAT=DYNAMIC` to
not have to limit text columns to length 171 for indexing when using
utf8mb4. This allows an easy way to specify this in your database
configuration.

While this change affects both MySQL and MySQL2, the test only covers
MySQL2, as the legacy mysql adapter appears to always return ASCII
strings, and is tangential to what we're actually doing.
---
 activerecord/CHANGELOG.md                             |  5 +++++
 .../connection_adapters/abstract_mysql_adapter.rb     |  3 ++-
 activerecord/test/cases/migration_test.rb             | 19 +++++++++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 2461dd517b..31bdbdf1d1 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,8 @@
+*   Allow specifying the default options for new tables on mysql and mysql2 in
+    database.yml, via the key `default_table_options`.
+
+    *Sean Griffin*
+
 *   Except keys of `build_record`'s argument from `create_scope` in `initialize_attributes`.
 
     Fixes #21893.
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index deef246c37..a6adc06633 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -597,7 +597,8 @@ module ActiveRecord
       end
 
       def create_table(table_name, options = {}) #:nodoc:
-        super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB"))
+        default_table_options = @config.fetch(:default_table_options, "ENGINE=InnoDB")
+        super(table_name, options.reverse_merge(options: default_table_options))
       end
 
       def bulk_change_table(table_name, operations) #:nodoc:
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index c3c204cf9f..58cbb80e31 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -1020,4 +1020,23 @@ class CopyMigrationsTest < ActiveRecord::TestCase
     ActiveRecord::Base.logger = old
   end
 
+  if current_adapter?(:Mysql2Adapter)
+    def test_default_table_options
+      config = ActiveRecord::Base.configurations['arunit'].merge(
+        encoding: 'utf8mb4',
+        default_table_options: "ENGINE=InnoDB CHARACTER SET utf8mb4",
+      )
+      ActiveRecord::Base.establish_connection(config)
+
+      ActiveRecord::Base.connection.create_table(:foos) do |t|
+        t.string :emoji
+      end
+      ActiveRecord::Base.connection.execute("INSERT INTO foos (emoji) VALUES ('💩')")
+      emoji = ActiveRecord::Base.connection.execute("SELECT emoji FROM foos").first.first
+      assert_equal "💩", emoji
+    ensure
+      ActiveRecord::Base.connection.drop_table(:foos, if_exists: true)
+      ActiveRecord::Base.establish_connection(:arunit)
+    end
+  end
 end
-- 
cgit v1.2.3