提交 30ef715d 编写于 作者: Y yui-knk

Automatically guess the inverse associations for STI

ActiveRecord associations automatically guess the inverse associations.
But this feature does not work correctly on assoctions for STI.
For example, before this commit

```
class Post < ActiveRecord::Base
  belongs_to :author
end

class SpecialPost < Post; end

class Author < ActiveRecord::Base
  has_many :posts
  has_many :special_posts
end
```

`author.posts.first.author` works correctly, but
`author.special_posts.first.author` does not work correctly.
上级 1fe41329
* Automatically guess the inverse associations for STI.
*Yuichiro Kaneko*
* Ensure `sum` honors `distinct` on `has_many :through` associations
Fixes #16791.
......
......@@ -657,7 +657,7 @@ def automatic_inverse_of
# from calling +klass+, +reflection+ will already be set to false.
def valid_inverse_reflection?(reflection)
reflection &&
klass.name == reflection.active_record.name &&
klass <= reflection.active_record &&
can_find_inverse_of_automatically?(reflection)
end
......
......@@ -18,6 +18,8 @@
require "models/developer"
require "models/company"
require "models/project"
require "models/author"
require "models/post"
class AutomaticInverseFindingTests < ActiveRecord::TestCase
fixtures :ratings, :comments, :cars
......@@ -60,6 +62,20 @@ def test_has_many_and_belongs_to_should_find_inverse_automatically
assert_equal rating_reflection, comment_reflection.inverse_of, "The Comment reflection's inverse should be the Rating reflection"
end
def test_has_many_and_belongs_to_should_find_inverse_automatically_for_sti
author_reflection = Author.reflect_on_association(:posts)
author_child_reflection = Author.reflect_on_association(:special_posts)
post_reflection = Post.reflect_on_association(:author)
assert_respond_to author_reflection, :has_inverse?
assert author_reflection.has_inverse?, "The Author reflection should have an inverse"
assert_equal post_reflection, author_reflection.inverse_of, "The Author reflection's inverse should be the Post reflection"
assert_respond_to author_child_reflection, :has_inverse?
assert author_child_reflection.has_inverse?, "The Author reflection should have an inverse"
assert_equal post_reflection, author_child_reflection.inverse_of, "The Author reflection's inverse should be the Post reflection"
end
def test_has_one_and_belongs_to_automatic_inverse_shares_objects
car = Car.first
bulb = Bulb.create!(car: car)
......@@ -267,7 +283,7 @@ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
end
class InverseHasManyTests < ActiveRecord::TestCase
fixtures :men, :interests
fixtures :men, :interests, :posts, :authors
def test_parent_instance_should_be_shared_with_every_child_on_find
m = men(:gordon)
......@@ -281,6 +297,27 @@ def test_parent_instance_should_be_shared_with_every_child_on_find
end
end
def test_parent_instance_should_be_shared_with_every_child_on_find_for_sti
a = authors(:david)
ps = a.posts
ps.each do |p|
assert_equal a.name, p.author.name, "Name of man should be the same before changes to parent instance"
a.name = "Bongo"
assert_equal a.name, p.author.name, "Name of man should be the same after changes to parent instance"
p.author.name = "Mungo"
assert_equal a.name, p.author.name, "Name of man should be the same after changes to child-owned instance"
end
sps = a.special_posts
sps.each do |sp|
assert_equal a.name, sp.author.name, "Name of man should be the same before changes to parent instance"
a.name = "Bongo"
assert_equal a.name, sp.author.name, "Name of man should be the same after changes to parent instance"
sp.author.name = "Mungo"
assert_equal a.name, sp.author.name, "Name of man should be the same after changes to child-owned instance"
end
end
def test_parent_instance_should_be_shared_with_eager_loaded_children
m = Man.all.merge!(where: { name: "Gordon" }, includes: :interests).first
is = m.interests
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册