在 Rails 中,如何在单个查找器中查询两个 has_many 关联?
In Rails, how do I query two has_many associations in a single finder?
我正在使用 Rails 4.2。我有以下用户模型和几个 has_many 关联
class User < ActiveRecord::Base
…
has_many :roles, through: :roles_users
has_many :addresses, dependent: :destroy, as: :addressable, inverse_of: :addressable
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :roles_users
class RolesUser < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
alias :user :addressable
我想查找没有任何地址的特定角色的所有用户。我认为下面会做到这一点
> users = User.includes(:roles, :addresses).where(:roles => {:name => 'User'}, :addresses => {:user_id => nil})
但是当我检查结果时,我仍然得到有地址的结果……
2.7.1 :012 > users.last.addresses.count
…
=> 2
编写查询这两个 has_many 关联的查找器的正确方法是什么?
检查父 ID 为 nil 的子记录与 Rails 4 中的方法类似。但是如果这不起作用,您可以使用 NOT IN 子句组合:
User
.where
.not(
id: User
.joins(:addresses, :roles)
.where(roles: { name: 'User' })
.select(:id)
)
它基本上是通过用户 ID 过滤掉所有具有关联地址、具有角色且角色名称正好是“用户”的用户行。您最终会得到这样的 SQL 查询:
SELECT "users".*
FROM "users"
WHERE "users"."id" NOT IN (
SELECT "users"."id"
FROM "users"
INNER JOIN "roles_users" ON "roles_users"."user_id" = "users"."id"
INNER JOIN "roles" ON "roles"."id" = "roles_users"."role_id"
WHERE "roles"."name" = 'User'
)
我正在使用 Rails 4.2。我有以下用户模型和几个 has_many 关联
class User < ActiveRecord::Base
…
has_many :roles, through: :roles_users
has_many :addresses, dependent: :destroy, as: :addressable, inverse_of: :addressable
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :roles_users
class RolesUser < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
alias :user :addressable
我想查找没有任何地址的特定角色的所有用户。我认为下面会做到这一点
> users = User.includes(:roles, :addresses).where(:roles => {:name => 'User'}, :addresses => {:user_id => nil})
但是当我检查结果时,我仍然得到有地址的结果……
2.7.1 :012 > users.last.addresses.count
…
=> 2
编写查询这两个 has_many 关联的查找器的正确方法是什么?
检查父 ID 为 nil 的子记录与 Rails 4 中的方法类似。但是如果这不起作用,您可以使用 NOT IN 子句组合:
User
.where
.not(
id: User
.joins(:addresses, :roles)
.where(roles: { name: 'User' })
.select(:id)
)
它基本上是通过用户 ID 过滤掉所有具有关联地址、具有角色且角色名称正好是“用户”的用户行。您最终会得到这样的 SQL 查询:
SELECT "users".*
FROM "users"
WHERE "users"."id" NOT IN (
SELECT "users"."id"
FROM "users"
INNER JOIN "roles_users" ON "roles_users"."user_id" = "users"."id"
INNER JOIN "roles" ON "roles"."id" = "roles_users"."role_id"
WHERE "roles"."name" = 'User'
)