ActiveRecord -如何“选择”多态连接作为布尔值



我一直在绞尽脑汁试图想出这个问题,所以我认为是时候在这里发表了。

我有一个类称为Flair -它是多态的,因为很多东西可以有Flair:

class Flair < ActiveRecord::Base
  belongs_to :flairable, polymorphic: true, touch: true
  belongs_to :user
end

一个Comment有多个Flairs:

class Comment < ActiveRecord::Base
  has_many :flairs, as: :flairable
end

当获得评论列表时,我还想知道哪些评论具有属于给定用户的Flair。

到目前为止我能想到的最好的是

# don't worry about the interpolation; just for the example
# and assume we have valid @comments and user_id
  @comments.select('comments.*').
    select('flairs.id as has_flaired').
    joins("left join flairs on flairable_id = comments.id and flairs.user_id = #{user_id}")

但是这将为Comment上的每个Flair返回一个结果(正如左连接所期望的那样),有效地将数组中每个Comment的出现次数乘以其拥有的Flair数量。

我试过使用distinct on (user_id),应用limit等,但这些努力只会出现语法错误。

谁能提供一些指导?特别有用的是一个指向文档中某个地方的指针,那里有比这里提供的例子更复杂的例子:http://www.postgresql.org/docs/9.4/static/sql-select.html。我也尝试了http://www.postgresql.org/docs/9.4/static/queries-table-expressions.html上的建议,但似乎没有什么能坚持下去。

谢谢!

www.postgresql.org/docs/9.4/static/queries-table-expressions.html中的7.2.1.3节和这里的第一个例子,以及一个非常耐心的老板最终帮助解决了这个问题。最后(在敲击键盘一段时间之后),我终于设法用语法正确的查询来取悦Postgres/ActiveRecord神(我们在将user_id传递给joins语句之前对其进行了消毒)。

@comments.select(
  "comments.*,
   flairs.id as has_flaired"
).joins(
  "left join
   flairs on flairs.id = (
     select id from flairs where flairs.user_id = #{user_id}
     and flairs.flairable_id = comments.id
     limit 1
   )"
)

这是有效的,因为我只感兴趣的行与该用户和flairable_id是否存在于flairs表,所以我们只是检查表在子查询和使用主查询的结果。

现在我已经写出来了,但我将把它留在这里,以防其他人同样感到困惑。

最新更新