如果所需的密钥不存在,如何在 link_to 中传递参数而不中断?

How do you pass params in a link_to without breaking if a required key is not present?

首先,我可以正常工作,但我想知道是否有更好的方法。

我有很多索引页面,用户可以在其中应用过滤器,然后将结果导出到 .csv.xls 文件。

我所做的是将 params 存在的任何内容(在应用过滤器之后)转发到再次查询数据库的控制器操作,并将结果发送到构建文件的服务,就像这样:

link_to:

      <li>
        <% if params.dig(:q).present? %>
          <%= link_to export_payments_admin_payments_path(params: { q: params.require(:q).permit(params[:q].keys, status_in: [], payment_type_in: [])}, format: "csv") do %>
            <span class="glyphicon glyphicon-download" aria-hidden="true"></span>
            Export
          <% end %>
        <% else %>
          <%= link_to export_payments_admin_payments_path(format: "csv") do %>
            <span class="glyphicon glyphicon-download" aria-hidden="true"></span>
            Export
          <% end %>
        <% end %>
      </li>

控制器动作:

  def export_payments
    @pre_search = current_account.payments.includes(:user)
    @search = @pre_search.ordered.ransack(params[:q])
    @payments = @search.result.paginate(page: params[:page], per_page: 20)

    respond_to do |format|
      format.csv do
        send_data FileManager::PaymentsExporter.new(@payments).call,
                  filename: "payments_#{Date.today}" + ".csv"
      end
    end
  end

如您所知,link_to 必须包含在条件语句中,因为如果我 require(:q) 但它不存在(未应用过滤器),视图将中断,因为必需 :q 密钥不存在。

有更好的方法吗?我试过删除 require(:q) 但如果我这样做的话根本不会传递任何参数。

您应该将所有这些逻辑移至控制器或助手。

首先创建一个方法来挂载在 link 中发送的参数,这样您就不需要将其包装成条件

# controller

def export_payments
  ...
  @q_params = q_params
  ...
end

def q_params
  if params.dig(:q).present?
    params.require(:q).permit(params[:q].keys, status_in: [], payment_type_in: [])
  else
    {}
  end
end

然后,使用方法渲染 link:

# view

<%= link_to export_payments_admin_payments_path(format: "csv", params: { q: @q_params }) do %>
  <span class="glyphicon glyphicon-download" aria-hidden="true"></span>
  Export
<% end %>