From fd3532204c7302ec80a245c72852a11288ec38b5 Mon Sep 17 00:00:00 2001
From: Guilherme Mansur <guilherme.mansur@shopify.com>
Date: Tue, 14 May 2019 15:13:29 -0400
Subject: Better error message for calling columns_hash

When a record does not have a table name, as in the case for a record
with `self.abstract_class = true` and no `self.table_name` set the error
message raises a cryptic:
"ActiveRecord::StatementInvalid: Could not find table ''" this patch now
raises a new `TableNotSpecified Error`

Fixes: #36274

Co-Authored-By: Eugene Kenny <elkenny@gmail.com>
---
 activerecord/CHANGELOG.md                      | 4 ++++
 activerecord/lib/active_record/errors.rb       | 4 ++++
 activerecord/lib/active_record/model_schema.rb | 3 +++
 activerecord/test/cases/base_test.rb           | 8 ++++++++
 4 files changed, 19 insertions(+)

diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8d4b01e995..8642227a2b 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+*   Loading the schema for a model that has no `table_name` raises a `TableNotSpecified` error.
+
+    *Guilherme Mansur*, *Eugene Kenny*
+
 *   PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute.
 
     Fixes #36022.
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index 60cf9818c1..c8c06375a3 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -38,6 +38,10 @@ module ActiveRecord
   class AdapterNotSpecified < ActiveRecordError
   end
 
+  # Raised when a model makes a query but it has not specified an associated table.
+  class TableNotSpecified < ActiveRecordError
+  end
+
   # Raised when Active Record cannot find database adapter specified in
   # +config/database.yml+ or programmatically.
   class AdapterNotFound < ActiveRecordError
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 2a45f63d64..18f19af6be 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -482,6 +482,9 @@ module ActiveRecord
         end
 
         def load_schema!
+          unless table_name
+            raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
+          end
           @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
           @columns_hash.each do |name, column|
             define_attribute(
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 983a46a2d0..1324bdf9b8 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1415,6 +1415,14 @@ class BasicsTest < ActiveRecord::TestCase
     assert_not_includes SymbolIgnoredDeveloper.columns_hash.keys, "first_name"
   end
 
+  test ".columns_hash raises an error if the record has an empty table name" do
+    expected_message = "FirstAbstractClass has no table configured. Set one with FirstAbstractClass.table_name="
+    exception = assert_raises(ActiveRecord::TableNotSpecified) do
+      FirstAbstractClass.columns_hash
+    end
+    assert_equal expected_message, exception.message
+  end
+
   test "ignored columns have no attribute methods" do
     assert_not_respond_to Developer.new, :first_name
     assert_not_respond_to Developer.new, :first_name=
-- 
cgit v1.2.3