今天我学会了如何使用Arel来构建需要带有标准ActiveRecord的SQL片段的SQL查询。到目前为止,我见过的所有Rails应用程序都有(最多)包装原始SQL的范围,如下所示:
# in class Post
scope :select_comment_count, -> {
join_comments.select('COUNT(comments.id)')
}
scope :join_comments, -> {
joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id AND comments.is_most_recent_edit = '1'")
}
哪些都可以在Arel中使用无SQL重写。
我的第一个问题是,使用Arel而不是SQL片段有什么具体的优点和缺点,为什么看起来似乎每个应用程序和每个RoR开发人员都忽略了Arel?
此外,默认情况下,我的Arel似乎非常混乱,部分原因是因为我的Arel必须知道我的外键名称:
scope :select_comment_count, -> {
comments = Comment.arel_table
joins_comments.select(comments[:id].count)
}
scope :join_comments, -> {
posts = Post.arel_table
comments = Comment.arel_table
# Bypasses ActiveRecord associations completely.
# We're using Arel to generate the above SQL
# Isn't this exactly the same as using Raw SQL, but slower?
# In some cases we would still lose DB independence,
# for instance if we did an update_all with a join in MySQL
# (not allowed in PostgreSQL)
sql = posts.
join(comments, Arel::Nodes::OuterJoin).
on(
(comments[:post_id].eq(posts[:id])). # Here we duplicate the knowledge of how our foreign key names relate to our associations
.and(comments[:is_most_recent_edit].eq(false))
).join_sql
joins(join_sql)
}
是否有任何好的工具或库可以统一ActiveRecord查询界面和Arel更多,或者保持Arel简单美观的任何好方法?我真的很喜欢使用Arel,但这种方式利用了ActiveRecord关联的强大功能,并且感觉不像是一个完全独立的API或SQL之上的额外复杂层。
答案 0 :(得分:1)
首先,第一个查询可以写成comments.count
,当然可以吗?
当您回顾问题中的代码时,人们更倾向于使用SQL的原因很明显。 SQL更简单,更易于阅读。
虽然SQL的实现存在差异,但值得记住的是SQL是标准,因此很多它也适用于许多不同的数据库服务器。
另一方面,您可能对Squeel gem感兴趣。