From 3e018eca32dd5bedaefe03845f076849a6fc5e4b Mon Sep 17 00:00:00 2001
From: Kir Shatrov <shatrov@me.com>
Date: Thu, 15 Dec 2016 15:19:34 -0500
Subject: Throw friendly error message when fixture is not a hash

Right now, when fixture is not a Hash we throw an error message
saying "fixture is not a hash". This is not very user friendly because
it's not saying which fixture is invalid.
---
 activerecord/lib/active_record/fixture_set/file.rb         |  7 +++++--
 activerecord/test/cases/fixtures_test.rb                   | 14 ++++++++++++--
 .../test/fixtures/naked/yml/courses_with_invalid_key.yml   |  3 +++
 3 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml

diff --git a/activerecord/lib/active_record/fixture_set/file.rb b/activerecord/lib/active_record/fixture_set/file.rb
index 5ba354d758..6cf2e01179 100644
--- a/activerecord/lib/active_record/fixture_set/file.rb
+++ b/activerecord/lib/active_record/fixture_set/file.rb
@@ -66,10 +66,13 @@ module ActiveRecord
         # Validate our unmarshalled data.
         def validate(data)
           unless Hash === data || YAML::Omap === data
-            raise Fixture::FormatError, "fixture is not a hash"
+            raise Fixture::FormatError, "fixture is not a hash: #{@file}"
           end
 
-          raise Fixture::FormatError unless data.all? { |name, row| Hash === row }
+          invalid = data.reject { |_, row| Hash === row }
+          if invalid.any?
+            raise Fixture::FormatError, "fixture key is not a hash: #{@file}, keys: #{invalid.keys.inspect}"
+          end
           data
         end
     end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index f3d0e4a1b1..ea3e8d7727 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -211,9 +211,19 @@ class FixturesTest < ActiveRecord::TestCase
   end
 
   def test_dirty_dirty_yaml_file
-    assert_raise(ActiveRecord::Fixture::FormatError) do
-      ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, FIXTURES_ROOT + "/naked/yml/courses")
+    fixture_path = FIXTURES_ROOT + "/naked/yml/courses"
+    error = assert_raise(ActiveRecord::Fixture::FormatError) do
+      ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path)
     end
+    assert_equal "fixture is not a hash: #{fixture_path}.yml", error.to_s
+  end
+
+  def test_yaml_file_with_one_invalid_fixture
+    fixture_path = FIXTURES_ROOT + "/naked/yml/courses_with_invalid_key"
+    error = assert_raise(ActiveRecord::Fixture::FormatError) do
+      ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path)
+    end
+    assert_equal "fixture key is not a hash: #{fixture_path}.yml, keys: [\"two\"]", error.to_s
   end
 
   def test_yaml_file_with_invalid_column
diff --git a/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml b/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml
new file mode 100644
index 0000000000..6f9da79b45
--- /dev/null
+++ b/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml
@@ -0,0 +1,3 @@
+one:
+  id: 1
+two: ['not a hash']
-- 
cgit v1.2.3