ActiveRelation 将如何影响 Rails? include() 的功能?
我已经查看了 Arel 源代码以及 Rails 3.0 的一些 activerecord 源代码,但我似乎无法为自己找到一个很好的答案,即 Arel 是否会改变我们在构造查询时使用 include() 的能力,为了更好。
在某些情况下,人们可能想要修改 2.3.5 及之前版本中的 activerecord :include 查询的条件,以获取将返回的关联记录。但据我所知,这并不是以编程方式适用于所有 :include 查询:(
我知道一些 AR-find-includes 使 t#{n}.c#{m} 重命名所有属性,并且可以想象添加条件这些查询来限制连接集的结果;但其他人会迭代地对 id 集进行 n_joins + 1 次查询,我不确定如何破解 AR 来编辑这些迭代查询。)
Arel 是否允许我们构建ActiveRecord 查询在使用includes() 时指定生成的关联模型对象?
前任:
User :has_many posts( has_many :comments)
User.all(:include => :posts) #say I wanted the post objects to have their
#comment counts loaded without adding a comment_count column to `posts`.
#At the post level, one could do so by:
posts_with_counts = Post.all(:select => 'posts.*, count(comments.id) as comment_count',
:joins => 'left outer join comments on comments.post_id = posts.id',
:group_by => 'posts.id') #i believe
#But it seems impossible to do so while linking these post objects to each
#user as well, without running User.all() and then zippering the objects into
#some other collection (ugly)
#OR running posts.group_by(&:user) (even uglier, with the n user queries)
I've looked over the Arel sources, and some of the activerecord sources for Rails 3.0, but I can't seem to glean a good answer for myself as to whether Arel will be changing our ability to use includes(), when constructing queries, for the better.
There are instances when one might want to modify the conditions on an activerecord :include query in 2.3.5 and before, for the association records which would be returned. But as far as I know, this is not programmatically tenable for all :include queries:
(I know some AR-find-includes make t#{n}.c#{m} renames for all the attributes, and one could conceivably add conditions to these queries to limit the joined sets' results; but others do n_joins + 1 number of queries over the id sets iteratively, and I'm not sure how one might hack AR to edit these iterated queries.)
Will Arel allow us to construct ActiveRecord queries which specify the resulting associated model objects when using includes()?
Ex:
User :has_many posts( has_many :comments)
User.all(:include => :posts) #say I wanted the post objects to have their
#comment counts loaded without adding a comment_count column to `posts`.
#At the post level, one could do so by:
posts_with_counts = Post.all(:select => 'posts.*, count(comments.id) as comment_count',
:joins => 'left outer join comments on comments.post_id = posts.id',
:group_by => 'posts.id') #i believe
#But it seems impossible to do so while linking these post objects to each
#user as well, without running User.all() and then zippering the objects into
#some other collection (ugly)
#OR running posts.group_by(&:user) (even uglier, with the n user queries)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么不真正使用 AREL 作为其核心呢?一旦您了解实际的表范围,您就可以使用 Arel::Relation,它与 ActiveRecord 实现本身完全不同。我确实相信 ActiveRecord::Relation 是 Arel::Relation & 包装器的完全不同(且已损坏)的实现。阿雷尔::表。我选择通过执行 Thing.scoped.table (Arel::Table) (这是活动记录样式)或 Arel::Table.new(:table_name) 来使用 Arel 的核心,这给了我一个新的 Arel::Table (我的首选方法)。由此您可以执行以下操作。
Arel::Row 从集合中返回元组的 TRUE 定义,该集合由 Arel::Header(Arel::Attributes 集合)和元组组成。
另外稍微详细一点,我之所以使用 Arel 作为其核心,是因为它真正向我公开了关系模型,这就是 ActiveRelation 背后的力量。我注意到 ActiveRecord 暴露了 Arel 所提供功能的 20%,我担心开发人员不会意识到这一点,也不会理解关系代数的真正核心。使用条件哈希对我来说是“老派”,是关系代数世界中的 ActiveRecord 风格编程。一旦我们学会摆脱基于 Martin Fowler 模型的方法并采用基于 EF Codd 关系模型的方法,这实际上就是 RDBMS 几十年来一直在尝试做的事情,但结果却大错特错。
我冒昧地为 Ruby 社区启动了一个关于 Arel 和关系代数的七部分学习系列。这些将包括短片,范围从绝对初学者到高级技术,例如自引用关系和构图下的闭合。第一个视频位于 http://Innovative-Studios.com/#pilot 请告诉我如果您需要更多信息或者这对您来说描述性不够。
阿雷尔的未来一片光明。
Why don't you actually use AREL at its core. Once you get down to the actual table scope you can use Arel::Relation which is COMPLETELY different from ActiveRecord implementation itself. I truly believe that the ActiveRecord::Relation is a COMPLETELY different (and busted) implementation of a wrapper around an Arel::Relation & Arel::Table. I choose to use Arel at its core by either doing Thing.scoped.table (Arel::Table) which is the active record style OR Arel::Table.new(:table_name) which gives me a fresh Arel::Table (my preferred method). From this you can do the following.
An Arel::Row returns a TRUE definition of a tuple from the set which will consist of an Arel::Header (set of Arel::Attributes) and a tuple.
Also slightly more verbose, the reason why I use Arel at its core is because it truly exposes the relational model to me which is the power behind ActiveRelation. I have noticed that ActiveRecord is exposing like 20% of what Arel has to offer and I am affraid that developers will not realize this NOR will they understand the true core of Relational Algebra. Using the conditions hash is to me "old school" and an ActiveRecord style programming in a Relational Algebra world. Once we learn to break away from the Martin Fowler model based approach and adopt the E.F. Codd Relational Model based approach this is actually what RDBMS have been trying to do for decades but gotten very wrong.
I've taken the liberty to start a seven part learning series on Arel and Relational Algebra for the ruby community. These will consist of short videos ranging from absolute beginner to advanced techniques like self referencing relations and closure under composition. The first video is at http://Innovative-Studios.com/#pilot Please let me know if you need more information or this was not descriptive enough for you.
The future looks bright with Arel.
ActiveRecord::Relation 是 Base#find_by_sql 的一个相当弱的包装器,因此 :include 查询不会通过其包含以任何方式扩展。
ActiveRecord::Relation is a fairly weak wrapper around Base#find_by_sql, so :include queries are not extended in any way by its inclusion.
这不是
您要找的吗? (取自官方文档)
Isn't
what you're looking for? (taken from the official docs)