aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md9
-rw-r--r--activerecord/lib/active_record/relation/merger.rb2
-rw-r--r--activerecord/test/cases/relation/merging_test.rb5
-rw-r--r--activerecord/test/models/comment.rb8
-rw-r--r--activerecord/test/models/post.rb9
5 files changed, 32 insertions, 1 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index f6cd5efb45..6c927dd353 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,12 @@
+* `ActiveRecord::Relation::Merger#filter_binds` now compares equivalent symbols and
+ strings in column names as equal.
+
+ This fixes a rare case in which more bind values are passed than there are
+ placeholders for them in the generated SQL statement, which can make PostgreSQL
+ throw a `StatementInvalid` exception.
+
+ *Nat Budin*
+
* `change_column_default` allows `[]` as argument to `change_column_default`.
Fixes #11586.
diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb
index fcb28a18f6..ac41d0aa80 100644
--- a/activerecord/lib/active_record/relation/merger.rb
+++ b/activerecord/lib/active_record/relation/merger.rb
@@ -156,7 +156,7 @@ module ActiveRecord
def filter_binds(lhs_binds, removed_wheres)
return lhs_binds if removed_wheres.empty?
- set = Set.new removed_wheres.map { |x| x.left.name }
+ set = Set.new removed_wheres.map { |x| x.left.name.to_s }
lhs_binds.dup.delete_if { |col,_| set.include? col.name }
end
diff --git a/activerecord/test/cases/relation/merging_test.rb b/activerecord/test/cases/relation/merging_test.rb
index 48f45d45b1..7c9543e5ae 100644
--- a/activerecord/test/cases/relation/merging_test.rb
+++ b/activerecord/test/cases/relation/merging_test.rb
@@ -108,6 +108,11 @@ class RelationMergingTest < ActiveRecord::TestCase
merged = left.merge(right)
assert_equal post, merged.first
end
+
+ def test_merging_compares_symbols_and_strings_as_equal
+ post = PostThatLoadsCommentsInAnAfterSaveHook.create!(title: "First Post", body: "Blah blah blah.")
+ assert_equal "First comment!", post.comments.where(body: "First comment!").first_or_create.body
+ end
end
class MergingDifferentRelationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index f82df417ce..d44befbfd2 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -40,3 +40,11 @@ end
class VerySpecialComment < Comment
end
+
+class CommentThatAutomaticallyAltersPostBody < Comment
+ belongs_to :post, class_name: "PostThatLoadsCommentsInAnAfterSaveHook", foreign_key: :post_id
+
+ after_save do |comment|
+ comment.post.update_attributes(body: "Automatically altered")
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index b1e56c14d1..4ee67a4bb3 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -208,3 +208,12 @@ class SpecialPostWithDefaultScope < ActiveRecord::Base
self.table_name = 'posts'
default_scope { where(:id => [1, 5,6]) }
end
+
+class PostThatLoadsCommentsInAnAfterSaveHook < ActiveRecord::Base
+ self.table_name = 'posts'
+ has_many :comments, class_name: "CommentThatAutomaticallyAltersPostBody", foreign_key: :post_id
+
+ after_save do |post|
+ post.comments.load
+ end
+end