我试图重构一段代码(并提高我对Arel::Nodes::Case的理解),我想转换这个Arel.sql语句
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,但我没有得到任何好的结果。有什么能帮上忙的吗?
在此之前,非常感谢您。
更新
我这么做了,但我一点也不喜欢。难以阅读和理解的:
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。
发布于 2020-12-28 18:35:14
您不能总是期望Arel是漂亮的。Arel是一个非常复杂和灵活的查询汇编程序,这种复杂性的副作用通常是冗长的。
尽管如此,在我看来,使用Arel而不是原始sql总是优先考虑的,因为它是卫生的、动态的和数据库无关的。
我们可以通过使用then方法,而不是使用when的第二个参数,将您的更新修改得更加可读性。这将导致代码读起来更像一个CASE语句,比如.when(condition).then(value)。
修改后的情况如下:
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来处理这个问题:
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:
(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_stmnt和arel_applications[:code]列,例如case_stmnt.asc或case_stmnt.desc
https://stackoverflow.com/questions/65477244
复制相似问题