我使用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和计数聚合器,带有组子句)。
在浏览Ruby on Rails指南时,我发现了一个奇怪的例子,它可能解决了我的问题,但不能让它工作,我真的不明白它是如何完成的:
scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))
如果我使用self.arel_table[:images_count]
,它会说它是nil对象
在整个应用程序中,我们在使用关联表中的属性进行搜索和过滤时确实存在问题。我们通过简单地将属性移动到主cars
表来解决一些问题,但这有点愚蠢,尽管它执行得很快。
经过思考,在我看来可行的是,关联将首先获得当前搜索中至少有一个图像的所有汽车id的列表(这可以通过简单的INNER JOIN
和DISTINCT id
查询完成),然后使用id-s列表获得正常的列表查询,但使用WHERE id IN [id_1, id_2, id_3, ... , id_n]
子句。
你觉得合理吗?我该怎么做呢?: D
此外,如果我能做到这一点没有SQL,只是用Arel或MetaWhere…
您在Rals指南中找到的是最简单的方法,甚至是最快的方法。
comments_count
是一个counter_cache,你可以在关联上设置它来获得子节点的数量。
轻松实现:
has_many :images, :class_name => "CarImage", :counter_cache => true
然后你就可以访问之前不存在的images_count
。
看医生。