mirror of https://github.com/rails/rails
Add where.associated to check association presence
This commit is contained in:
parent
dda5e28a60
commit
ccdf6b8d42
|
@ -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.
|
||||
|
||||
Fixes #35204.
|
||||
|
|
|
@ -48,6 +48,34 @@ module ActiveRecord
|
|||
@scope
|
||||
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
|
||||
# missing relations.
|
||||
#
|
||||
|
|
|
@ -12,6 +12,22 @@ module ActiveRecord
|
|||
class WhereChainTest < ActiveRecord::TestCase
|
||||
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
|
||||
assert posts(:authorless).author.blank?
|
||||
assert_equal [posts(:authorless)], Post.where.missing(:author).to_a
|
||||
|
|
Loading…
Reference in New Issue