我有一个查询,它运行良好:
ModelName.where('true')
我可以将其与其他AR调用链接,如哪里、订单等。但是,当我使用时:
ModelName.all
我收到了"相同"的响应,但无法将位置或订单链接到它,因为它是一个数组,而不是AR集合。虽然我使用第一种方法没有实际问题,但它似乎有点难看/没有必要。有没有更干净的方法可以做到这一点,也许是.to_active_record_collection之类的?
有一个简单的解决方案。而不是使用
ModelName.where('true')
用途:
ModelName.scoped
正如您所说:
ModelName.where('true').class #=> ActiveRecord::Relation
ModelName.all.class #=> Array
因此,只要不使用触发查询的all
、first
或last
,就可以进行尽可能多的延迟加载。
在考虑缓存时,了解这些差异非常重要。
但我还是不明白什么样的情况会让你陷入这样的境地:
ModelName.all.where(foobar)
除非您需要一整堆资产用于一个目的,然后从数据库中加载它,并需要其中的一个子集用于其他目的。对于这种情况,您需要使用ruby的Array过滤方法。
旁注:
ModelName.all
不应该使用,这是一种反模式,因为您无法控制要检索的项目数量。希望:
ModelName.limit(20).class #=> ActiveRecord::Relation
正如您所说,后者返回一个元素数组,而前者是一个ActiveRecord::Relation
。您可以使用Ruby方法对数组进行排序和筛选。例如,要按id排序,可以调用sort_by(&:id)
。要过滤元素,可以调用select
或reject
。对于ActiveRecord::Relation
,您可以将where
或order
链接到它,正如您所说。
不同之处在于排序和处理的方向。对于Array,它是由应用程序完成的;对于关系-通过数据库。当有更多的记录时,后者通常更快。它的内存效率也更高。