Rails从SQL到AREL的复杂查询

时间:2012-03-27 18:40:33

标签: sql ruby-on-rails-3 activerecord associations arel

对于来自非ActiveRecord环境的人来说,复杂的查询具有挑战性。我在编写SQL时非常了解自己,但是我很难找到如何在AREL中实现某些查询。我试着自己弄清楚下面的例子,但我似乎无法找到正确的答案。

以下是我选择AREL方式而非当前find_by_sql方式的原因:

  • 我模型中的清洁代码。
  • 更简单的代码(当此查询因链接而与分页结合使用时。)
  • 更多的多数据库兼容性(例如我习惯GROUP BY topics.id而不是指定我在SELECT子句中使用的所有列。

以下是我的模型的简化版本:

class Support::Forum < ActiveRecord::Base
  has_many :topics

  def self.top
    Support::Forum.find_by_sql "SELECT forum.id, forum.title, forum.description, SUM(topic.replies_count) AS count FROM support_forums forum, support_topics topic WHERE forum.id = topic.forum_id AND forum.group = 'theme support' GROUP BY forum.id, forum.title, forum.description ORDER BY count DESC, id DESC LIMIT 4;"
  end

  def ordered_topics
    Support::Topic.find_by_sql(["SELECT topics.* FROM support_forums forums, support_topics topics, support_replies replies WHERE forums.id = ? AND forums.id = topics.forum_id AND topics.id = replies.topic_id GROUP BY topics.id ORDER BY topics.pinned DESC, MAX(replies.id) DESC;", self.id])
  end

  def last_topic
    Support::Topic.find_by_sql(["SELECT topics.id, topics.title FROM support_forums forums, support_topics topics, support_replies replies WHERE forums.id = ? AND forums.id = topics.forum_id AND topics.id = replies.topic_id GROUP BY topics.id, topics.title, topics.pinned ORDER BY MAX(replies.id) DESC LIMIT 1;", self.id]).first
  end
end

class Support::Topic < ActiveRecord::Base
  belongs_to :forum, counter_cache: true
  has_many :replies
end

class Support::Reply < ActiveRecord::Base
  belongs_to :topic, counter_cache: true
end

每当我可以的时候,我尝试通过AREL而不是在SQL中编写这样的东西(由于之前提到的原因),但我无法理解上面的非基本示例。

Fyi我并不是真的希望将这些方法直接转换为AREL,欢迎任何方向或对解决方案的见解。 如果您认为这是使用sql-finder编写这些查询的完全可接受的解决方案的另一个评论,请分享您的想法。

注意:如果我需要提供其他示例,请说明,我会:)

1 个答案:

答案 0 :(得分:1)

对于不需要自定义连接或子句的任何内容 - 即可以映射到AR关系 - 您可能希望使用squeel而不是arel。 AREL基本上是一个重量级的关系代数DSL,你可以用它在ruby中从头开始编写SQL查询。对于活动记录查询而言,Squeel更像是一个更加漂亮的DSL,它消除了大多数使用SQL文字语句的情况。

相关问题