aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorMatt Jones <al2o3cr@gmail.com>2008-11-15 01:59:12 -0500
committerMichael Koziarski <michael@koziarski.com>2008-11-15 18:20:39 +0100
commitd3fd9971093101712e4cc97ccc534631888b673d (patch)
tree5a26a28aeef593529ee7acf952da57ef7f0fe3c7 /activerecord
parent31be959de746da0b704684e858d1ca69dbf6bf7f (diff)
downloadrails-d3fd9971093101712e4cc97ccc534631888b673d.tar.gz
rails-d3fd9971093101712e4cc97ccc534631888b673d.tar.bz2
rails-d3fd9971093101712e4cc97ccc534631888b673d.zip
fix assignment to has_one :through associations.
Signed-off-by: Michael Koziarski <michael@koziarski.com>
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/has_one_through_association.rb7
-rw-r--r--activerecord/test/cases/associations/has_one_through_associations_test.rb40
-rw-r--r--activerecord/test/fixtures/organizations.yml5
-rw-r--r--activerecord/test/models/member.rb2
-rw-r--r--activerecord/test/models/member_detail.rb4
-rw-r--r--activerecord/test/models/organization.rb4
-rw-r--r--activerecord/test/schema/schema.rb10
7 files changed, 67 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb
index b78bd5d931..8073ebaf9f 100644
--- a/activerecord/lib/active_record/associations/has_one_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_through_association.rb
@@ -8,11 +8,10 @@ module ActiveRecord
current_object = @owner.send(@reflection.through_reflection.name)
if current_object
- klass.destroy(current_object)
- @owner.clear_association_cache
+ current_object.update_attributes(construct_join_attributes(new_value))
+ else
+ @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value)))
end
-
- @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value)))
end
private
diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb
index ff4021fe02..7d418de965 100644
--- a/activerecord/test/cases/associations/has_one_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb
@@ -3,9 +3,11 @@ require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
+require 'models/organization'
+require 'models/member_detail'
class HasOneThroughAssociationsTest < ActiveRecord::TestCase
- fixtures :members, :clubs, :memberships, :sponsors
+ fixtures :members, :clubs, :memberships, :sponsors, :organizations
def setup
@member = members(:groucho)
@@ -120,4 +122,40 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
clubs(:moustache_club).send(:private_method)
@member.club.send(:private_method)
end
+
+ def test_assigning_to_has_one_through_preserves_decorated_join_record
+ @organization = organizations(:nsa)
+ assert_difference 'MemberDetail.count', 1 do
+ @member_detail = MemberDetail.new(:extra_data => 'Extra')
+ @member.member_detail = @member_detail
+ @member.organization = @organization
+ end
+ assert_equal @organization, @member.organization
+ assert @organization.members.include?(@member)
+ assert_equal 'Extra', @member.member_detail.extra_data
+ end
+
+ def test_reassigning_has_one_through
+ @organization = organizations(:nsa)
+ @new_organization = organizations(:discordians)
+
+ assert_difference 'MemberDetail.count', 1 do
+ @member_detail = MemberDetail.new(:extra_data => 'Extra')
+ @member.member_detail = @member_detail
+ @member.organization = @organization
+ end
+ assert_equal @organization, @member.organization
+ assert_equal 'Extra', @member.member_detail.extra_data
+ assert @organization.members.include?(@member)
+ assert !@new_organization.members.include?(@member)
+
+ assert_no_difference 'MemberDetail.count' do
+ @member.organization = @new_organization
+ end
+ assert_equal @new_organization, @member.organization
+ assert_equal 'Extra', @member.member_detail.extra_data
+ assert !@organization.members.include?(@member)
+ assert @new_organization.members.include?(@member)
+ end
+
end
diff --git a/activerecord/test/fixtures/organizations.yml b/activerecord/test/fixtures/organizations.yml
new file mode 100644
index 0000000000..25295bff87
--- /dev/null
+++ b/activerecord/test/fixtures/organizations.yml
@@ -0,0 +1,5 @@
+nsa:
+ name: No Such Agency
+discordians:
+ name: Discordians
+
diff --git a/activerecord/test/models/member.rb b/activerecord/test/models/member.rb
index 688725f200..77a37abb38 100644
--- a/activerecord/test/models/member.rb
+++ b/activerecord/test/models/member.rb
@@ -6,4 +6,6 @@ class Member < ActiveRecord::Base
has_one :favourite_club, :through => :memberships, :conditions => ["memberships.favourite = ?", true], :source => :club
has_one :sponsor, :as => :sponsorable
has_one :sponsor_club, :through => :sponsor
+ has_one :member_detail
+ has_one :organization, :through => :member_detail
end \ No newline at end of file
diff --git a/activerecord/test/models/member_detail.rb b/activerecord/test/models/member_detail.rb
new file mode 100644
index 0000000000..e731454556
--- /dev/null
+++ b/activerecord/test/models/member_detail.rb
@@ -0,0 +1,4 @@
+class MemberDetail < ActiveRecord::Base
+ belongs_to :member
+ belongs_to :organization
+end
diff --git a/activerecord/test/models/organization.rb b/activerecord/test/models/organization.rb
new file mode 100644
index 0000000000..d79d5037c8
--- /dev/null
+++ b/activerecord/test/models/organization.rb
@@ -0,0 +1,4 @@
+class Organization < ActiveRecord::Base
+ has_many :member_details
+ has_many :members, :through => :member_details
+end \ No newline at end of file
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index ab5c7c520b..6217e3bc1c 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -197,6 +197,12 @@ ActiveRecord::Schema.define do
t.string :name
end
+ create_table :member_details, :force => true do |t|
+ t.integer :member_id
+ t.integer :organization_id
+ t.string :extra_data
+ end
+
create_table :memberships, :force => true do |t|
t.datetime :joined_on
t.integer :club_id, :member_id
@@ -249,6 +255,10 @@ ActiveRecord::Schema.define do
t.integer :shipping_customer_id
end
+ create_table :organizations, :force => true do |t|
+ t.string :name
+ end
+
create_table :owners, :primary_key => :owner_id ,:force => true do |t|
t.string :name
end