首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby:将Arel.sql转换为Arel::Node::Case的想法?

Ruby:将Arel.sql转换为Arel::Node::Case的想法?
EN

Stack Overflow用户
提问于 2020-12-28 11:56:06
回答 1查看 473关注 0票数 3

我试图重构一段代码(并提高我对Arel::Nodes::Case的理解),我想转换这个Arel.sql语句

代码语言:javascript
复制
    Arel.sql(default_order)
    def default_order
        "CASE
          WHEN applications.status = 'new' AND owner_id IS NULL THEN '1'
          WHEN applications.is_priority = '1' AND is_read = '0' AND owner_id = '#{current_user.id}'  THEN '2'
          WHEN applications.is_priority = '1' THEN '3'
          ELSE '4'
         END, applications.code"
    end

进入Arel::Nodes::Case,但我没有得到任何好的结果。有什么能帮上忙的吗?

在此之前,非常感谢您。

更新

我这么做了,但我一点也不喜欢。难以阅读和理解的:

代码语言:javascript
复制
  def default_order
    arel_applications = Application.arel_table
    Arel::Nodes::Case.new
        .when((arel_applications[:status].eq('new'))
                  .and(arel_applications[:owner_id].eq(nil)), 1)
        .when((arel_applications[:is_priority].eq(1))
                  .and(arel_applications[:is_read].eq(0))
                  .and(arel_applications[:owner_id].eq(current_user.id)), 2)
        .when(arel_applications[:is_priority].eq(1), 3)
        .else(4).to_sql
  end

即便如此,我也不知道如何获得在SQL中用于排序记录的applications.code

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-28 18:35:14

您不能总是期望Arel是漂亮的。Arel是一个非常复杂和灵活的查询汇编程序,这种复杂性的副作用通常是冗长的。

尽管如此,在我看来,使用Arel而不是原始sql总是优先考虑的,因为它是卫生的、动态的和数据库无关的。

我们可以通过使用then方法,而不是使用when的第二个参数,将您的更新修改得更加可读性。这将导致代码读起来更像一个CASE语句,比如.when(condition).then(value)

修改后的情况如下:

代码语言:javascript
复制
  def default_order
    arel_applications = Application.arel_table
    case_stmnt = Arel::Nodes::Case.new
        .when(arel_applications[:status].eq('new').and(
                 arel_applications[:owner_id].eq(nil)
             )
          ).then(1)
        .when(arel_applications[:is_priority].eq(1).and(
                arel_applications[:is_read].eq(0).and(
                  arel_applications[:owner_id].eq(current_user.id)
                )
              )
          ).then(2)
        .when(arel_applications[:is_priority].eq(1)
          ).then(3)
        .else(4)
  end

现在,为了处理问题的第二部分,“即使如此,我不知道如何获得在SQL中使用的applications.code来排序记录。”

我们可以使用Arel::Nodes::Grouping来处理这个问题:

代码语言:javascript
复制
def default_order
    arel_applications = Application.arel_table
    case_stmnt = Arel::Nodes::Case.new
        .when(arel_applications[:status].eq('new').and(
                 arel_applications[:owner_id].eq(nil)
             )
           ).then(1).
        .when(arel_applications[:is_priority].eq(1).and(
                arel_applications[:is_read].eq(0).and(
                  arel_applications[:owner_id].eq(current_user.id)
                )
              )
          ).then(2)
        .when(arel_applications[:is_priority].eq(1)
          ).then(3)
        .else(4)
    Arel::Nodes::Grouping.new(case_stmnt,arel_applications[:code])
  end

这将导致以下SQL:

代码语言:javascript
复制
(CASE 
  WHEN [applications].[status] = N'new' AND [applications].[owner_id] IS NULL THEN 1 
  WHEN [applications].[is_priority] = 1 AND [applications].[is_read] = 0 AND [applications].[owner_id] = 1 THEN 2 
  WHEN [applications].[is_priority] = 1 THEN 3 
  ELSE 4 END, 
[applications].[code])

然后您就可以使用它作为order的参数(不需要转换to_sql,因为rails会为您处理这个问题,例如Application.order(default_order) )。

还可以将排序方向附加到case_stmntarel_applications[:code]列,例如case_stmnt.asccase_stmnt.desc

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65477244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档