mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add where.associated to check association presence
This commit is contained in:
parent
dda5e28a60
commit
ccdf6b8d42
3 changed files with 58 additions and 0 deletions
|
@ -1,3 +1,17 @@
|
||||||
|
* Add `where.associated` to check for the presence of an association.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# Before:
|
||||||
|
account.users.joins(:contact).where.not(contact_id: nil)
|
||||||
|
|
||||||
|
# After:
|
||||||
|
account.users.where.associated(:contact)
|
||||||
|
```
|
||||||
|
|
||||||
|
Also mirrors `where.missing`.
|
||||||
|
|
||||||
|
*Kasper Timm Hansen*
|
||||||
|
|
||||||
* Fix odd behavior of inverse_of with multiple belongs_to to same class.
|
* Fix odd behavior of inverse_of with multiple belongs_to to same class.
|
||||||
|
|
||||||
Fixes #35204.
|
Fixes #35204.
|
||||||
|
|
|
@ -48,6 +48,34 @@ module ActiveRecord
|
||||||
@scope
|
@scope
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a new relation with joins and where clause to identify
|
||||||
|
# associated relations.
|
||||||
|
#
|
||||||
|
# For example, posts that are associated to a related author:
|
||||||
|
#
|
||||||
|
# Post.where.associated(:author)
|
||||||
|
# # SELECT "posts".* FROM "posts"
|
||||||
|
# # INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
|
||||||
|
# # WHERE "authors"."id" IS NOT NULL
|
||||||
|
#
|
||||||
|
# Additionally, multiple relations can be combined. This will return posts
|
||||||
|
# associated to both an author and any comments:
|
||||||
|
#
|
||||||
|
# Post.where.associated(:author, :comments)
|
||||||
|
# # SELECT "posts".* FROM "posts"
|
||||||
|
# # INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
|
||||||
|
# # INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
|
||||||
|
# # WHERE "authors"."id" IS NOT NULL AND "comments"."id" IS NOT NULL
|
||||||
|
def associated(*associations)
|
||||||
|
associations.each do |association|
|
||||||
|
reflection = @scope.klass._reflect_on_association(association)
|
||||||
|
@scope.joins!(association)
|
||||||
|
self.not(reflection.table_name => { reflection.association_primary_key => nil })
|
||||||
|
end
|
||||||
|
|
||||||
|
@scope
|
||||||
|
end
|
||||||
|
|
||||||
# Returns a new relation with left outer joins and where clause to identify
|
# Returns a new relation with left outer joins and where clause to identify
|
||||||
# missing relations.
|
# missing relations.
|
||||||
#
|
#
|
||||||
|
|
|
@ -12,6 +12,22 @@ module ActiveRecord
|
||||||
class WhereChainTest < ActiveRecord::TestCase
|
class WhereChainTest < ActiveRecord::TestCase
|
||||||
fixtures :posts, :comments, :authors, :humans, :essays
|
fixtures :posts, :comments, :authors, :humans, :essays
|
||||||
|
|
||||||
|
def test_associated_with_association
|
||||||
|
Post.where.associated(:author).tap do |relation|
|
||||||
|
assert_includes relation, posts(:welcome)
|
||||||
|
assert_includes relation, posts(:sti_habtm)
|
||||||
|
assert_not_includes relation, posts(:authorless)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_associated_with_multiple_associations
|
||||||
|
Post.where.associated(:author, :comments).tap do |relation|
|
||||||
|
assert_includes relation, posts(:welcome)
|
||||||
|
assert_not_includes relation, posts(:sti_habtm)
|
||||||
|
assert_not_includes relation, posts(:authorless)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_missing_with_association
|
def test_missing_with_association
|
||||||
assert posts(:authorless).author.blank?
|
assert posts(:authorless).author.blank?
|
||||||
assert_equal [posts(:authorless)], Post.where.missing(:author).to_a
|
assert_equal [posts(:authorless)], Post.where.missing(:author).to_a
|
||||||
|
|
Loading…
Reference in a new issue