使用范围仅显示具有关联对象的项目

时间:2011-10-28 19:23:57

标签: ruby-on-rails ruby-on-rails-3 scope associations arel

我正在使用meta_search来过滤汽车列表。汽车模型定义如下:

class Car < ActiveRecord::Base
  has_many    :images, :class_name => "CarImage"
  ......
end

我想定义一个可以与meta_search一起使用的范围,并且仅返回至少具有图像的汽车。我可以使其工作的唯一方法是在范围内编写连接,但这似乎返回重复的汽车对象:

scope :with_images, joins(:images)

如果我尝试仅选择不同的值,例如:

scope :with_images, joins(:images).select('DISTINCT cars.*')

...我搞砸了依赖我的搜索结果的其他方法(例如avg和count聚合器,以及group子句)。

在浏览Ruby on Rails Guides时,我找到了一个奇怪的例子,可以解决我的问题,但无法让它工作,我真的不明白它是如何完成的:

scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))

如果我使用self.arel_table[:images_count],那么它表示这是一个零对象。

在整个应用程序中,我们确实遇到了使用关联表中的属性进行搜索和过滤的问题。我们通过简单地将属性移动到主cars表来解决了一些问题,但这有点愚蠢,尽管它执行速度很快。

在考虑之后,我认为可行的是,该关联首先会获得当前搜索中至少有一个图像的所有车辆ID的列表(这可以通过简单的{{ 1}}和INNER JOIN查询)然后使用id-s列表获取正常的列表查询,但带有DISTINCT id子句。

这对你来说是否合情合理?那我该怎么办? :d

另外,如果我能在没有SQL的情况下做到这一点会很好,只需使用Arel或MetaWhere ......

1 个答案:

答案 0 :(得分:2)

您在Rals指南中找到的是最简单的方法,即使是最快的方式。

comments_count是一个counter_cache htat,您可以设置关联以获取子项数。

轻松实施:

has_many    :images, :class_name => "CarImage", :counter_cache => true

然后您就可以访问之前不存在的images_count

See doc