【问题标题】:Rails ransack and paper_trail search for a key in a postgresql json columnRails ransack 和 paper_trail 在 postgresql json 列中搜索键
【发布时间】:2017-04-28 20:21:39
【问题描述】:

我正在使用 Ruby on Rails 创建我的网站。我正在使用 paper_trail gem 来保存我的模型的历史性更改,并使用 ransack gem 来执行搜索表单。一切正常,但我想创建一个搜索表单来过滤对我的模型所做的更改。

这是要在erb中过滤的代码框架:

  <%= search_form_for [@q, @q_deleted], url: ticket_index_path, class: 'form-inline' do |f| %>
    <div class="row">
      <div class="col-sm-6 col-lg-4">
        <%= f.label :versions_whodunnit_eq, t('audit.view.text.user').capitalize, {class: "control-label"} %>
        <%= f.select :versions_whodunnit_eq, User.all.collect { |p| [p.name, p.id] }, {include_blank: true}, {class: 'form-control input-sm'} %>
      </div>
      <div class="col-sm-6 col-lg-4">
        <%= f.label :versions_event_eq, t('audit.view.text.event').capitalize, {class: "control-label"} %>
        <%= f.select :versions_event_eq, {t('common.versions_event.create') => 'create', t('common.versions_event.update') => 'update', t('common.versions_event.destroy') => 'destroy'}, {include_blank: true}, {class: 'form-control input-sm'}  %>
      </div>
      <div class="col-sm-6 col-lg-4">
        <%= f.label :versions_object_changes_eq, t('audit.view.text.change').capitalize, {class: "control-label"} %>
        <%= f.select :versions_object_changes_eq, Audit::TicketsController::COLUMNS.collect { |column| [t("audit.view.text.column_change.#{column}"), column] }, {include_blank: true}, {class: 'form-control input-sm'} %>
      </div>
    </div>
    <div class="row">
      <div class="col-sm-6 col-lg-3">
        <br>
        <%= f.submit 'Buscar', class: 'btn btn-primary' %>
        <%= link_to 'Limpiar', request.path, class: 'btn btn-default cancel-button' %>
      </div>
    </div>
  <% end %>

进入视图控制器:

params[:q] ||= {}

params[:page] = 1 if params[:page].blank?
params[:page_deleted] = 1 if params[:page_deleted].blank?

@q = Ticket.all.order(date: :desc).ransack(params[:q])
@q_deleted = Ticket.only_deleted.order(date: :desc).ransack(params[:q])

result = @q.result(distinct: true)
result_deleted = @q_deleted.result(distinct: true)

@active_count = result.count
@deleted_count = result_deleted.count

@tickets = result.paginate(page: params[:page], per_page: params[:per_page])
@tickets_deleted = result_deleted.paginate(page: params[:page_deleted], per_page: params[:per_page])

问题是,当我通过 :versions_object_changes_eq 进行过滤时,PostgreSQL 会引发一个可以比较 json 列的错误:

SELECT DISTINCT "tickets".* FROM "tickets" LEFT OUTER JOIN "versions" ON "versions"."item_id" = "tickets"."id" AND "versions"."item_type" = 'Ticket' WHERE "tickets"."deleted_at" IS NULL AND "versions"."object_changes" = 'date' ORDER BY "tickets"."date" DESC

该 SQL 的问题是访问 json 键是白衣 ->> 然后正确的方法是:

SELECT DISTINCT "tickets".* FROM "tickets" LEFT OUTER JOIN "versions" ON "versions"."item_id" = "tickets"."id" AND "versions"."item_type" = 'Ticket' WHERE "tickets"."deleted_at" IS NULL AND ("versions"."object_changes"->>'ticket_state' IS NOT NULL) ORDER BY "tickets"."date" DESC

我该怎么做?

【问题讨论】:

    标签: ruby-on-rails ransack paper-trail-gem


    【解决方案1】:

    我遇到了像你这样的问题,并通过添加以下内容解决了它:

    ransacker :ticket_state do |parent|
      Arel::Nodes::InfixOperation.new('->>', parent.table[:object_changes], Arel::Nodes.build_quoted('ticket_state'))
    end
    

    给我的模特。然后您可以在 ticket_state 上使用任何 Ransack 谓词,例如:

    Ticket.ticket_state_not_null
    

    【讨论】:

      【解决方案2】:

      .. 当我通过 :versions_object_changes_eq 过滤时 [我得到这个 SQL]

      where "versions"."object_changes" = 'date'
      

      [但我想要:]

      where "versions"."object_changes"->>'ticket_state' IS NOT NULL
      

      我认为 ransack 不支持 -&gt;&gt; 运算符。你可以尝试写一个custom ransacker,但他们没有很好的记录,所以我不推荐它。

      PaperTrail 确实支持-&gt;&gt; 运算符。使用PaperTrail::Version.where_object。但是,这可能很难与Ticket.ransack 结合使用。

      您可以尝试以下三件事:

      1. 使用 ActiveRecord 的merge 方法来组合Ticket.ransackVersion.where_object
      2. 执行两个单独的查询并获取结果的设置交集
      3. 有条件地将所需的原始 SQL 添加到 Relation

      【讨论】:

      • 谢谢,我会这样做,因为我真的没有找到任何方法来整合它们。
      • 如果您想根据您在 PT 上使用 ransack 的经验为其他人写一些提示,请随时在我们的自述文件中打开 PR。 (github.com/airblade/paper_trail)
      猜你喜欢
      • 1970-01-01
      • 2021-09-27
      • 2014-10-14
      • 2020-05-13
      • 1970-01-01
      • 2016-11-17
      • 2013-03-02
      • 2017-12-06
      • 1970-01-01
      相关资源
      最近更新 更多