aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Antropov <antropov.ivan@gmail.com>2013-11-10 12:28:54 +0700
committerIvan Antropov <antropov.ivan@gmail.com>2013-11-17 12:20:50 +0700
commitec0928076529e8f0b5a4ad58c95cfa1fe6ed5b60 (patch)
tree30ebc3fd0590552a2b175b83c5d99c6b0f347c39
parentfa13d8e6d926c601070104c7075be39618280272 (diff)
downloadrails-ec0928076529e8f0b5a4ad58c95cfa1fe6ed5b60.tar.gz
rails-ec0928076529e8f0b5a4ad58c95cfa1fe6ed5b60.tar.bz2
rails-ec0928076529e8f0b5a4ad58c95cfa1fe6ed5b60.zip
Fix insertion of records for hmt association with scope, fix #3548
-rw-r--r--activerecord/CHANGELOG.md6
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb6
-rw-r--r--activerecord/lib/active_record/relation.rb4
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb14
-rw-r--r--activerecord/test/cases/relation_test.rb4
-rw-r--r--activerecord/test/models/club.rb2
6 files changed, 32 insertions, 4 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 0bef057836..89fcc129ca 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,9 @@
+* Fix insertion of records via has_many_through association with scope
+
+ Fixes #3548
+
+ *Ivan Antropov*
+
* Checks to see if the record contains the foreign key to set the inverse automatically.
*Edo Balvers*
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 31b8d27892..53268372eb 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -84,12 +84,16 @@ module ActiveRecord
@through_records[record.object_id] ||= begin
ensure_mutable
- through_record = through_association.build
+ through_record = through_association.build through_scope_attributes
through_record.send("#{source_reflection.name}=", record)
through_record
end
end
+ def through_scope_attributes
+ scope.where_values_hash(through_association.reflection.name.to_s)
+ end
+
def save_through_record(record)
build_through_record(record).save!
ensure
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 6e0669a77f..5e38ed632d 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -527,9 +527,9 @@ module ActiveRecord
#
# User.where(name: 'Oscar').where_values_hash
# # => {name: "Oscar"}
- def where_values_hash
+ def where_values_hash(relation_table_name = table_name)
equalities = where_values.grep(Arel::Nodes::Equality).find_all { |node|
- node.left.relation.name == table_name
+ node.left.relation.name == relation_table_name
}
binds = Hash[bind_values.find_all(&:first).map { |column, v| [column.name, v] }]
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 47592f312e..8017ed169c 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -1095,7 +1095,19 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_equal [posts(:thinking)], person.reload.first_posts
end
- def test_has_many_through_with_includes_in_through_association_scope
+ test "has many through with includes in through association scope" do
assert_not_empty posts(:welcome).author_address_extra_with_address
end
+
+ test "insert records via has_many_through association with scope" do
+ club = Club.create!
+ member = Member.create!
+ Membership.create!(club: club, member: member)
+
+ club.favourites << member
+ assert_equal [member], club.favourites
+
+ club.reload
+ assert_equal [member], club.favourites
+ end
end
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 70d113fb39..e83aafc842 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -16,6 +16,10 @@ module ActiveRecord
def self.connection
Post.connection
end
+
+ def self.table_name
+ 'fake_table'
+ end
end
def test_construction
diff --git a/activerecord/test/models/club.rb b/activerecord/test/models/club.rb
index 566e0873f1..902a047f62 100644
--- a/activerecord/test/models/club.rb
+++ b/activerecord/test/models/club.rb
@@ -6,6 +6,8 @@ class Club < ActiveRecord::Base
has_one :sponsored_member, :through => :sponsor, :source => :sponsorable, :source_type => "Member"
belongs_to :category
+ has_many :favourites, -> { where(memberships: { favourite: true}) }, through: :memberships, source: :member
+
private
def private_method