From 26d19b4661f3d89a075b5f05d926c578ff0c730f Mon Sep 17 00:00:00 2001
From: wangjohn <wangjohn@mit.edu>
Date: Fri, 1 Mar 2013 16:49:33 -0500
Subject: Created a method to automatically find inverse associations and cache
 the results. Added tests to check to make sure that inverse associations are
 automatically found when has_many, has_one, or belongs_to associations are
 defined.

---
 .../associations/inverse_associations_test.rb      | 82 ++++++++++++++++++++++
 activerecord/test/cases/nested_attributes_test.rb  |  2 +
 activerecord/test/models/club.rb                   |  2 +-
 activerecord/test/models/interest.rb               |  2 +-
 activerecord/test/models/man.rb                    |  2 +-
 activerecord/test/models/member.rb                 |  2 +-
 activerecord/test/models/member_detail.rb          |  2 +-
 7 files changed, 89 insertions(+), 5 deletions(-)

(limited to 'activerecord/test')

diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index ec128acf28..b1f0be3204 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -5,6 +5,88 @@ require 'models/interest'
 require 'models/zine'
 require 'models/club'
 require 'models/sponsor'
+require 'models/rating'
+require 'models/comment'
+require 'models/car'
+require 'models/bulb'
+
+class AutomaticInverseFindingTests < ActiveRecord::TestCase
+  fixtures :ratings, :comments, :cars
+
+  def test_has_one_and_belongs_to_should_find_inverse_automatically
+    car_reflection = Car.reflect_on_association(:bulb)
+    bulb_reflection = Bulb.reflect_on_association(:car)
+
+    assert_respond_to car_reflection, :has_inverse?
+    assert car_reflection.has_inverse?, "The Car reflection should have an inverse"
+    assert_equal bulb_reflection, car_reflection.inverse_of, "The Car reflection's inverse should be the Bulb reflection"
+
+    assert_respond_to bulb_reflection, :has_inverse?
+    assert bulb_reflection.has_inverse?, "The Bulb reflection should have an inverse"
+    assert_equal car_reflection, bulb_reflection.inverse_of, "The Bulb reflection's inverse should be the Car reflection"
+  end
+
+  def test_has_many_and_belongs_to_should_find_inverse_automatically
+    comment_reflection = Comment.reflect_on_association(:ratings)
+    rating_reflection = Rating.reflect_on_association(:comment)
+
+    assert_respond_to comment_reflection, :has_inverse?
+    assert comment_reflection.has_inverse?, "The Comment reflection should have an inverse"
+    assert_equal rating_reflection, comment_reflection.inverse_of, "The Comment reflection's inverse should be the Rating reflection"
+  end
+
+  def test_has_one_and_belongs_to_automatic_inverse_shares_objects
+    car = Car.first
+    bulb = Bulb.create!(car: car)
+
+    assert_equal car.bulb, bulb, "The Car's bulb should be the original bulb"
+
+    car.bulb.color = "Blue"
+    assert_equal car.bulb.color, bulb.color, "Changing the bulb's color on the car association should change the bulb's color"
+
+    bulb.color = "Red"
+    assert_equal bulb.color, car.bulb.color, "Changing the bulb's color should change the bulb's color on the car association"
+  end
+
+  def test_has_many_and_belongs_to_automatic_inverse_shares_objects_on_rating
+    comment = Comment.first
+    rating = Rating.create!(comment: comment)
+
+    assert_equal rating.comment, comment, "The Rating's comment should be the original Comment"
+
+    rating.comment.body = "Brogramming is the act of programming, like a bro."
+    assert_equal rating.comment.body, comment.body, "Changing the Comment's body on the association should change the original Comment's body"
+
+    comment.body = "Broseiden is the king of the sea of bros."
+    assert_equal comment.body, rating.comment.body, "Changing the original Comment's body should change the Comment's body on the association"
+  end
+
+  def test_has_many_and_belongs_to_automatic_inverse_shares_objects_on_comment
+    rating = Rating.create!
+    comment = Comment.first
+    rating.comment = comment
+
+    assert_equal rating.comment, comment, "The Rating's comment should be the original Comment"
+
+    rating.comment.body = "Brogramming is the act of programming, like a bro."
+    assert_equal rating.comment.body, comment.body, "Changing the Comment's body on the association should change the original Comment's body"
+
+    comment.body = "Broseiden is the king of the sea of bros."
+    assert_equal comment.body, rating.comment.body, "Changing the original Comment's body should change the Comment's body on the association"
+  end
+
+  def test_polymorphic_and_has_many_through_relationships_should_not_have_inverses
+    sponsor_reflection = Sponsor.reflect_on_association(:sponsorable)
+
+    assert_respond_to sponsor_reflection, :has_inverse?
+    assert !sponsor_reflection.has_inverse?, "A polymorphic association should not find an inverse automatically"
+
+    club_reflection = Club.reflect_on_association(:members)
+
+    assert_respond_to club_reflection, :has_inverse?
+    assert !club_reflection.has_inverse?, "A has_many_through association should not find an inverse automatically"
+  end
+end
 
 class InverseAssociationTests < ActiveRecord::TestCase
   def test_should_allow_for_inverse_of_options_in_associations
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 165b7454b7..6fe81e0d96 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -800,7 +800,9 @@ module NestedAttributesOnACollectionAssociationTests
   def test_validate_presence_of_parent_fails_without_inverse_of
     Man.accepts_nested_attributes_for(:interests)
     Man.reflect_on_association(:interests).options.delete(:inverse_of)
+    Man.reflect_on_association(:interests).clear_inverse_of_cache!
     Interest.reflect_on_association(:man).options.delete(:inverse_of)
+    Interest.reflect_on_association(:man).clear_inverse_of_cache!
 
     repair_validations(Interest) do
       Interest.validates_presence_of(:man)
diff --git a/activerecord/test/models/club.rb b/activerecord/test/models/club.rb
index 24a65b0f2f..7d7c205041 100644
--- a/activerecord/test/models/club.rb
+++ b/activerecord/test/models/club.rb
@@ -1,6 +1,6 @@
 class Club < ActiveRecord::Base
   has_one :membership
-  has_many :memberships
+  has_many :memberships, :automatic_inverse_of => false
   has_many :members, :through => :memberships
   has_many :current_memberships
   has_one :sponsor
diff --git a/activerecord/test/models/interest.rb b/activerecord/test/models/interest.rb
index d5d9226204..f772bb1c7f 100644
--- a/activerecord/test/models/interest.rb
+++ b/activerecord/test/models/interest.rb
@@ -1,5 +1,5 @@
 class Interest < ActiveRecord::Base
-  belongs_to :man, :inverse_of => :interests
+  belongs_to :man, :inverse_of => :interests, :automatic_inverse_of => false
   belongs_to :polymorphic_man, :polymorphic => true, :inverse_of => :polymorphic_interests
   belongs_to :zine, :inverse_of => :interests
 end
diff --git a/activerecord/test/models/man.rb b/activerecord/test/models/man.rb
index 4bff92dc98..49f002aa9a 100644
--- a/activerecord/test/models/man.rb
+++ b/activerecord/test/models/man.rb
@@ -1,7 +1,7 @@
 class Man < ActiveRecord::Base
   has_one :face, :inverse_of => :man
   has_one :polymorphic_face, :class_name => 'Face', :as => :polymorphic_man, :inverse_of => :polymorphic_man
-  has_many :interests, :inverse_of => :man
+  has_many :interests, :inverse_of => :man, :automatic_inverse_of => false
   has_many :polymorphic_interests, :class_name => 'Interest', :as => :polymorphic_man, :inverse_of => :polymorphic_man
   # These are "broken" inverse_of associations for the purposes of testing
   has_one :dirty_face, :class_name => 'Face', :inverse_of => :dirty_man
diff --git a/activerecord/test/models/member.rb b/activerecord/test/models/member.rb
index 1134b09d8b..b81304b8e0 100644
--- a/activerecord/test/models/member.rb
+++ b/activerecord/test/models/member.rb
@@ -9,7 +9,7 @@ class Member < ActiveRecord::Base
   has_one :hairy_club, -> { where :clubs => {:name => "Moustache and Eyebrow Fancier Club"} }, :through => :membership, :source => :club
   has_one :sponsor, :as => :sponsorable
   has_one :sponsor_club, :through => :sponsor
-  has_one :member_detail
+  has_one :member_detail, :automatic_inverse_of => false
   has_one :organization, :through => :member_detail
   belongs_to :member_type
 
diff --git a/activerecord/test/models/member_detail.rb b/activerecord/test/models/member_detail.rb
index fe619f8732..a256c73c7e 100644
--- a/activerecord/test/models/member_detail.rb
+++ b/activerecord/test/models/member_detail.rb
@@ -1,5 +1,5 @@
 class MemberDetail < ActiveRecord::Base
-  belongs_to :member
+  belongs_to :member, :automatic_inverse_of => false
   belongs_to :organization
   has_one :member_type, :through => :member
 
-- 
cgit v1.2.3