Active Admin:如何在嵌套模型的 json 列上添加可排序
Active Admin: how to add sortable on nested model's json column
如何将 jsonb 订单查询传递到 Active Admin 列的 sortable:
选项?
我的模型结构如下:
# User Model
class User < ActiveRecord::Base
has_one :level
end
# Level Model
class Level < ActiveRecord::Base
belongs_to :user
end
# Level Migration
create_table "levels", force: :cascade do |t|
t.integer "user_id"
t.jsonb "ranked_scores"
end
:ranked_score
json结构是:
# level.ranked_scores
{"stage_1"=>111, "stage_2"=>222, "stage_3"=>333}
我尝试使用 Level
的 :ranked_scores
属性对 User
进行排序,如下所示:
# app/admin/user.rb
ActiveAdmin.register User do
controller do
def scoped_collection
end_of_association_chain.includes(:level)
end
end
index do
column "Stage 1 Score", sortable: "level.ranked_scores -> 'stage_1'" do |user|
user.level.ranked_scores['stage_1']
end
end
end
ActiveAdmin.register Level do
belongs_to :user
end
生成的用于对列进行排序的 url 是
http://localhost:3000/admin?order=levels.ranked_scores%5B%27stage_1%27%5D_desc
但是 stage_1
的列未按降序排序。
对这里出了什么问题有什么想法吗?
您应该在 admin/user.rb
配置中做 2 处小改动,这将使其可用。
#1 ->
周围有空格,应将其删除以使 ActiveAdmin 满意。
这里的问题是由 ActiveAdmin 的 sort validation regexp 引起的,它与您的 sortable 选项不匹配。删除 ->
周围的空格可以被视为 ActiveAdmin 错误的解决方法。
#2 Level
的 table 应该引用为 levels
,而不是 level
.
最后我们有:
column "Stage 1 Score", sortable: "levels.ranked_scores->'stage_1'"
你得到了你想要的。
关于 ->>
运算符的注意事项
还有另一个 Postgres 运算符 ->>
,它与 ->
非常相似。 See here.
两者的区别在于,->>
总是return的文本值(字符串化json),而->
可以returnjson 对象。在您的示例中,它们的用法完全相同,因为排名分数是数字。
但在一般情况下,您可能还需要 ->>
运算符。不幸的是,ActiveAdmin 仍然没有解决问题 #3173 和 #3085,。因此,您不能在当前版本的 ActiveAdmin 中使用 ->>
运算符。
不幸的是,我想不出任何解决方法,就像我们对 ->
运算符所做的那样。
您还可以使用 hack 来启用此运算符。需要在ActiveAdmin的源代码中添加2个字符。
您需要将此 line of code 更改为以下内容:
clause =~ /^([\w\_\.]+)(->>?'\w+')?_(desc|asc)$/
我们在两者之间添加了 >?
。 2 个字符,如所承诺的那样。
对于 jsonb
列,您需要使用 ->>
而不是 ->
,但这会导致 ActiveAdmin 验证出现问题(请参阅未解决的问题:https://github.com/activeadmin/activeadmin/issues/3173 and https://github.com/activeadmin/activeadmin/issues/3085) .
我不确定他们是否修复了它,你可以试试
index do
column "Stage 1 Score", sortable: "levels.ranked_scores ->> 'stage_1'" do |user|
user.level.ranked_scores['stage_1']
end
end
我最近一直在为同样的老问题苦苦挣扎。此外,我想将 JSON 值排序为整数。
这是我的解决方案。它无需猴子修补 ActiveAdmin 错误即可工作,并提供比以前的答案更大的灵活性。
order_by(:json_field) do |order_clause|
"(json_column->>'json_field')::int #{order_clause.order} NULLS LAST"
end
index do
column :json_field, sortable: 'json_field'
end
参考 ActiveAdmin 自定义排序文档:https://activeadmin.info/3-index-pages/index-as-table.html
如何将 jsonb 订单查询传递到 Active Admin 列的 sortable:
选项?
我的模型结构如下:
# User Model
class User < ActiveRecord::Base
has_one :level
end
# Level Model
class Level < ActiveRecord::Base
belongs_to :user
end
# Level Migration
create_table "levels", force: :cascade do |t|
t.integer "user_id"
t.jsonb "ranked_scores"
end
:ranked_score
json结构是:
# level.ranked_scores
{"stage_1"=>111, "stage_2"=>222, "stage_3"=>333}
我尝试使用 Level
的 :ranked_scores
属性对 User
进行排序,如下所示:
# app/admin/user.rb
ActiveAdmin.register User do
controller do
def scoped_collection
end_of_association_chain.includes(:level)
end
end
index do
column "Stage 1 Score", sortable: "level.ranked_scores -> 'stage_1'" do |user|
user.level.ranked_scores['stage_1']
end
end
end
ActiveAdmin.register Level do
belongs_to :user
end
生成的用于对列进行排序的 url 是
http://localhost:3000/admin?order=levels.ranked_scores%5B%27stage_1%27%5D_desc
但是 stage_1
的列未按降序排序。
对这里出了什么问题有什么想法吗?
您应该在 admin/user.rb
配置中做 2 处小改动,这将使其可用。
#1 ->
周围有空格,应将其删除以使 ActiveAdmin 满意。
这里的问题是由 ActiveAdmin 的 sort validation regexp 引起的,它与您的 sortable 选项不匹配。删除 ->
周围的空格可以被视为 ActiveAdmin 错误的解决方法。
#2 Level
的 table 应该引用为 levels
,而不是 level
.
最后我们有:
column "Stage 1 Score", sortable: "levels.ranked_scores->'stage_1'"
你得到了你想要的。
关于 ->>
运算符的注意事项
还有另一个 Postgres 运算符 ->>
,它与 ->
非常相似。 See here.
两者的区别在于,->>
总是return的文本值(字符串化json),而->
可以returnjson 对象。在您的示例中,它们的用法完全相同,因为排名分数是数字。
但在一般情况下,您可能还需要 ->>
运算符。不幸的是,ActiveAdmin 仍然没有解决问题 #3173 和 #3085,->>
运算符。
不幸的是,我想不出任何解决方法,就像我们对 ->
运算符所做的那样。
您还可以使用 hack 来启用此运算符。需要在ActiveAdmin的源代码中添加2个字符。
您需要将此 line of code 更改为以下内容:
clause =~ /^([\w\_\.]+)(->>?'\w+')?_(desc|asc)$/
我们在两者之间添加了 >?
。 2 个字符,如所承诺的那样。
对于 jsonb
列,您需要使用 ->>
而不是 ->
,但这会导致 ActiveAdmin 验证出现问题(请参阅未解决的问题:https://github.com/activeadmin/activeadmin/issues/3173 and https://github.com/activeadmin/activeadmin/issues/3085) .
我不确定他们是否修复了它,你可以试试
index do
column "Stage 1 Score", sortable: "levels.ranked_scores ->> 'stage_1'" do |user|
user.level.ranked_scores['stage_1']
end
end
我最近一直在为同样的老问题苦苦挣扎。此外,我想将 JSON 值排序为整数。
这是我的解决方案。它无需猴子修补 ActiveAdmin 错误即可工作,并提供比以前的答案更大的灵活性。
order_by(:json_field) do |order_clause|
"(json_column->>'json_field')::int #{order_clause.order} NULLS LAST"
end
index do
column :json_field, sortable: 'json_field'
end
参考 ActiveAdmin 自定义排序文档:https://activeadmin.info/3-index-pages/index-as-table.html