活动管理员:如何在嵌套模型的json列上添加sortable

Puf*_*ffo 6 postgresql json ruby-on-rails activeadmin columnsorting

如何将jsonb顺序查询传递到sortable:Active Admin列的选项?

我的模型结构如下:

# 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
Run Code Online (Sandbox Code Playgroud)

:ranked_scoreJSON结构是:

# level.ranked_scores
{"stage_1"=>111, "stage_2"=>222, "stage_3"=>333} 
Run Code Online (Sandbox Code Playgroud)

我试图排序User使用Level:ranked_scores属性如下:

# 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
Run Code Online (Sandbox Code Playgroud)

生成的用于对列进行排序的URL是

http://localhost:3000/admin?order=levels.ranked_scores%5B%27stage_1%27%5D_desc

但是列没有按降序排序stage_1.

对于这里出了什么问题的任何想法?

dim*_*ura 5

您应该对配置进行 2 个小更改admin/user.rb,以使其可行。

#1周围有空格->,应该将其删除以使 ActiveAdmin 满意。

这里的问题是由 ActiveAdmin 的排序验证 regexp引起的,它与您的可排序选项不匹配。删除周围的空白->可以被视为解决 ActiveAdmin 错误的方法。

#2 Level的表应该被引用为levels,而不是level

所以最后我们有:

column "Stage 1 Score", sortable: "levels.ranked_scores->'stage_1'"
Run Code Online (Sandbox Code Playgroud)

然后你就得到了你想要得到的东西。

关于->>操作员的注意事项

还有另一个 Postgres 运算符 ,->>它与->. 看这里

两者之间的区别在于,它->>总是返回文本值(字符串化的json),而->可以返回json对象。在您的示例中,它们的使用完全相同,因为排名分数是数字。

但在一般情况下,您可能->>还需要运算符。不幸的是,ActiveAdmin 仍然没有修复问题 #3173 和 #3085,@bigsolom 在他的回复中提到了这些问题。因此您无法->>在当前版本的 ActiveAdmin 中使用操作员。

不幸的是,我无法想出任何解决方法,就像我们对->操作员所做的那样。

您仍然可以使用一个 hack 来启用此操作符。它需要在ActiveAdmin的源代码中添加2个字符。

您需要将这行代码更改为以下代码:

clause =~ /^([\w\_\.]+)(->>?'\w+')?_(desc|asc)$/
Run Code Online (Sandbox Code Playgroud)

我们>?在中间添加了。2 个字符,正如所承诺的。