续集渴望加载单个ORM对象的一些关联

时间:2014-08-03 18:36:21

标签: ruby sequel

我正在为一个小应用程序构建数据模型,并希望在某些方法中利用急切加载 - 即我事先知道某些关联将被使用的那些方法。

我已阅读.eager方法的the Sequel::Model::Association指南,但它让我感到困惑。一个典型的例子可能是:

Artist.eager( :albums => :tracks ).all

加载所有Artist对象及其预加载的所有专辑字段,并使用三个查询预加载所有曲目。到目前为止,非常好。

但是说我想通过其主键加载一个艺术家,并且仍然预先加载了专辑+曲目(仍然有三个查询,可能比跟踪每个专辑的关联少很多)?我看不到任何这样的例子。一点实验给了我

Artist.eager( :albums => :tracks ).where( :id => id ).all.first

这似乎至少有效。我通过调用它确认了急切的加载,然后关闭了数据库,并显示我仍然可以访问关联。

然而,我觉得我错过了一些东西。构造必须将主键传递给where子句,得到一个完整的数据集然后要求第一个项目似乎很尴尬。我正在寻找这样的东西:

Artist.eager( :albums => :tracks )[ id ]

。 。 。一种简单的方式来声明我想加载一个对象,并急切加载它的一些关联。

发现我可以创建这样的自定义关联:

def eager_albums
  albums_dataset.eager( :tracks ).all
end

但使用起来很尴尬,因为代码必须以不同的方式请求关联。

我的问题:我的构造Artist.eager( :albums => :tracks ).where( :id => id ).all.first是否按照我在<续集中所做的那样思考,我可以做得更好(更简单的代码)吗?

1 个答案:

答案 0 :(得分:7)

致电Artist.eager( :albums => :tracks ).where( :id => id ).all.first即可抓取所有id等于&#39; id&#39;然后从结果数组中提取第一个艺术家(调用all实现数组)。通常,此查询将仅返回包含单个艺术家的数组。

直到您实际要求关系artist.albums或相册之外的关联才会运行其他查询。

您可以Artist.eager( :albums => :tracks ).where( :id => id ).first

我使用tactical eager loading plugin所以几乎没有必要使用eager,因为它检测到何时从作为更大结果集的一部分的模型实例使用关联并且相关模型的急切加载自动完成整个结果集。您的查询现在变为Artist[id]Artist[id].albums.all

我使用的另一个方便的插件是association proxies plugin,所以我不必处理使用association.some_array_method vs association_dataset.some_ds_method

最后,dataset associations plugin允许您描述从某个模型或模型类开始的查询,并通过与目标模型的关联进行链接,同时允许您在此过程中定义约束(或不约束)。

例如&#34;发现在过去两周内在英国出生的艺术家发布的任何专辑中超过3分钟的所有曲目&#34;:

Artist.where(country_of_birth: 'UK').albums.where{ release_date > Date.today - 14}.tracks.where{ duration > 3.minutes }.all

希望这会有所启发。