与ActiveRecord和Rails 3的复杂JOIN

whi*_*red 9 sql activerecord join ruby-on-rails ruby-on-rails-3

我有以下型号:

class User < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships
end

class Group < ActiveRecord::Base
  has_many :memberships
  has_many :users, :through => :memberships
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end

class Post < ActiveRecord::Base
  belongs_to :group
end
Run Code Online (Sandbox Code Playgroud)

我必须找到属于用户所属组的所有帖子.我用这种方法做到了:

@post = Post
  .joins(:group => {:memberships => :user})
  .where(:memberships => {:user_id => current_user.id})
Run Code Online (Sandbox Code Playgroud)

但它会产生效率低下的SQL:

SELECT "posts".* FROM "posts" 
INNER JOIN "groups" ON "groups"."id" = "posts"."group_id" 
INNER JOIN "memberships" ON "memberships"."group_id" = "groups"."id" 
INNER JOIN "users" ON "users"."id" = "memberships"."user_id" 
WHERE "memberships"."user_id" = 1
Run Code Online (Sandbox Code Playgroud)

我想做一个像这样的查询:

SELECT posts.* FROM posts 
INNER JOIN memberships ON memberships.group_id = posts.group_id 
WHERE memberships.user_id = 1
Run Code Online (Sandbox Code Playgroud)

如何在不使用原始SQL的情况下执行此操作?

jam*_*raa 16

通过从通话中删除未使用的联接,您可以在不更改模型的情况下靠近:

Post.joins(group: :memberships).where(memberships: { user_id: 1 })
Run Code Online (Sandbox Code Playgroud)

编译为SQL

SELECT "posts".* FROM "posts"
INNER JOIN "groups" ON "groups"."id" = "posts"."group_id"
INNER JOIN "memberships" ON "memberships"."group_id" = "groups"."id" 
WHERE ("memberships"."user_id" = 1)
Run Code Online (Sandbox Code Playgroud)


Wil*_*Ayd 12

这样的东西应该适合你,虽然它需要混合一点原始SQL

Post
  .joins("INNER JOIN memberships ON memberships.group_id = posts.group_id")
  .where(:memberships => {:user_id => current_user.id})
Run Code Online (Sandbox Code Playgroud)