在Rails 4中,是否可以向LEFT OUTER JOIN添加条件?

5

考虑以下结构:

class Account < ActiveRecord::Base
    has_many :users
    has_many :teams
    validates :name, presence: true
end

class User < ActiveRecord::Base
    belongs_to :account
    has_and_belongs_to_many :teams
    validates :name, presence: true
end

class Team < ActiveRecord::Base
    belongs_to :account
    has_and_belongs_to_many :users
    validates :name, presence: true
end

目标是获取一个账户下所有团队的id/名称列表,以及指示给定用户是否属于该团队的标志。

在SQL中,我可以通过以下方式获得这个结果:

SELECT teams.id, teams.name, 
     teams_users.team_id IS NOT NULL AS member FROM teams 
    LEFT OUTER JOIN teams_users ON 
        (teams.id = teams_users.team_id AND team_users.user_id = ?)
    WHERE teams.account_id = ?

有没有Rails 4 / ActiveRecord的方法可以获得相同的结果?我尝试过的每个尝试都把teams_users.user_id = ?条件推入WHERE子句中,这只返回用户是成员的团队列表,而不是与账户关联的所有团队。

你能解决这个问题吗?我还需要在左联接的"on"中添加一个"and"条件。 - opensource-developer
1个回答

6

使用字符串形式的joins应该是可行的。在将用户输入插入字符串之前,对其进行清理。

Team.select(:id, :name).
  select("teams_users.team_id IS NOT NULL AS member FROM teams").
  joins("LEFT OUTER JOIN teams_users ON (teams.id = teams_users.team_id AND team_users.user_id = #{current_user.id})").
  where(account_id: account.id)

1
谢谢 - 这大概是我目前正在使用的!我真的希望能找到一种不涉及在连接中使用糟糕的字符串插值的方法... - MZB
如果你喜欢,我可以构建一个Arel版本。然而,我更喜欢字符串版本。 - messanjah
您可以避免插值并使用标准查询转义符?,例如joins('LEFT OUTER JOIN ... team_users.user_id = ?', current_user.id) - TTT
1
@TTT,至少在Rails 5.0中不支持该表单在joins中(请注意问题指定版本4)。Model.joins('LEFT OUTER JOIN ... models.user_id.id = ?', 1).to_a => NoMethodError: undefined method 'class_name' for 1:Integer - messanjah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接