ActiveRecord Arel vs SQL和最佳实践

时间:2013-06-24 19:51:25

标签: ruby-on-rails activerecord arel

今天我学会了如何使用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之上的额外复杂层。

1 个答案:

答案 0 :(得分:1)

首先,第一个查询可以写成comments.count,当然可以吗?

当您回顾问题中的代码时,人们更倾向于使用SQL的原因很明显。 SQL更简单,更易于阅读。

虽然SQL的实现存在差异,但值得记住的是SQL是标准,因此很多它也适用于许多不同的数据库服务器。

另一方面,您可能对Squeel gem感兴趣。