【问题标题】:Rails Persist Search Results to CSV OutputRails 将搜索结果保存到 CSV 输出
【发布时间】:2014-01-25 19:14:19
【问题描述】:

我有一个 Rails 3.2.x 应用程序,其中有一个报告控制器,它在 Call 模型上进行搜索。我放在一起的代码工作正常,并允许在页面上显示多个条件。我遇到的问题是将特定搜索结果导出到 CSV 文件。到目前为止,我只能将整个数据库导出为 CSV 而不是特定的搜索结果。

我想弄清楚如何让我的搜索参数保持不变并能够仅将这些记录导出到 CSV。

这是我的相关代码:

reports_controller.rb

  def index    
     @calls = Call.report(params[:search])
     respond_to do |format|
         format.html do
           @calls = @calls.paginate(:per_page => params[:per_page] || 10, :page => params[:page]).order('incident_number ASC')
         end
         format.csv { send_data @calls.to_csv }
         format.xls  { send_data @calls.to_csv(col_sep: "\t") }
       end
   end

调用.rb

def self.report(search)
    search ||= { type: "all" }

    # Determine which scope to search by
    results = case search[:type]
              when "open"
                open_status
              when "canceled"
                cancel
              when "closed"
                closed
              when "waitreturn"
                waitreturn
              when "wheelchair"
                wheelchair
              else
                scoped
              end

    results = results.by_unit_name(search[:unit_name]) if search[:unit_name].present?
    results = results.by_service_level(search[:service_level]) if search[:service_level].present?
    results = results.from_facility(search[:transferred_from]) if search[:transferred_from].present?
    results = results.to_facility(search[:transferred_to]) if search[:transferred_to].present?

    # If searching with BOTH a start and end date
    if search[:start_date].present? && search[:end_date].present?
      results = results.search_between(Date.parse(search[:start_date]), Date.parse(search[:end_date]))

      # If search with any other date parameters (including none)
    else
      results = results.search_by_start_date(Date.parse(search[:start_date])) if search[:start_date].present?
      results = results.search_by_end_date(Date.parse(search[:end_date])) if search[:end_date].present?
    end

    results
  end

 def self.to_csv(options = {})
    CSV.generate(options) do |csv|
      csv << ["Call ID", "Caller Name", "Caller Phone", "Call Created At", "Call Status", "Incident Number", "Diagnosis", "Service Level", "Patient Name", "Patient Age", "Patient Sex", "Transfer From", "Transfer To", "Insurance", "Transfer Date", "Unit", "IMX Number"]
      all.each do |call|
        csv << [call.id, call.caller_name, call.caller_phone, call.created_at, call.call_status, call.incident_number, call.nature.determinant, call.service_level.level_of_service, call.patient_name, call.patient_age, call.patient_sex.sex, transfer_from_name(call), transfer_to_name(call), call.insurance.insurance_type, call.transfer_date, call.units.map(&:unit_name).join(", "), call.imx_num]
      end
    end
  end

index.html.erb

<h2>Reports</h2>
<%= render 'search'%>
<%= render 'results'%>

_search.html.erb

<div>
  <%= form_tag reports_path, :method => 'get' do %>  
    <p>
        <%= select_tag "search[type]", options_for_select([["All Statuses", "all"], ["Open", "open"], ["Closed", "closed"], ["Canceled", "canceled"], ["Wait & Return", "waitreturn"]], selected: params[:search].try(:[], :type)) %>
        <%= select_tag "search[service_level]", options_from_collection_for_select(ServiceLevel.order(:level_of_service), :level_of_service, :level_of_service, selected: params[:search].try(:[], :service_level)), prompt: "All Service Levels" %>
    </p>
    <p>
        <%= text_field_tag "search[start_date]", params[:search].try(:[], :start_date), :placeholder => 'Start Date', :class => 'input-large search-query ', id: 'start_date_select' %>
        to 
        <%= text_field_tag "search[end_date]", params[:search].try(:[], :end_date), :placeholder => 'End Date', :class => 'input-large search-query', id: 'end_date_select'   %>
      </p>

      <p>
        Unit
        <%= select_tag "search[unit_name]", options_from_collection_for_select(Unit.order(:unit_name), :unit_name, :unit_name, selected: params[:search].try(:[], :unit_name)), prompt: "Any Unit" %>

      </p>

      <p>
        From
        <%= select_tag "search[transferred_from]", options_from_collection_for_select(Facility.order(:facility_name), :id, :facility_name, selected: params[:search].try(:[], :transferred_from)), prompt: "Any Facility" %>
        To
      <%= select_tag "search[transferred_to]", options_from_collection_for_select(Facility.order(:facility_name), :id, :facility_name, selected: params[:search].try(:[], :transferred_to)), prompt: "Any Facility" %>
      </p> 

      <p>
        Results Per Page
        <%= select_tag "per_page", options_for_select([["10", 10], ["25", 25] , ["50", 50], ["100", 100], ["All", 100000]], selected: params[:per_page]), class: "span1" %>
        <%= submit_tag "Search", :name => nil, :class => 'btn' %>
      </p>
  <% end %>
</div>

_results.html.erb

<table class="table table-striped">
  <thead>
    <tr>
      <th>Incident Number</th>
      <th>Patient Name</th>
      <th>Transfer Date</th>
      <th>Transferred From</th>
      <th>Transferred To</th>
      <th>Determinant</th>
      <th>Unit</th>
      <th>Insurance</th>
      <th>Cancelation Reason</th>
      <th>IMX Number</th>
      <th></th>
    </tr>
  </thead>

  <tbody>
    <% @calls.each do |c| %>
      <tr>
        <td><%= c.incident_number %></td>
        <td><%= c.patient_name %></td>
        <td><%= c.transfer_date.strftime("%m/%d/%y") %></td>
        <td><%= transferred_from(c) %><br/><%= transferred_from_address(c) %></td>
        <td><%= transferred_to(c) %><br/><%= transferred_to_address(c) %></td>
        <td><%= c.nature.try(:determinant)%></td>
        <td><%= c.units.map(&:unit_name).join(", ") %></td>
        <td><%= c.insurance.try(:insurance_type)%></td>
        <td><%= c.cancel_reason.try(:reason) %></td>
        <td><%= c.imx_num %></td>
        <td><%= link_to 'View', c, :class => 'btn btn-close btn-mini'%></td>
      </tr>
    <% end %>
  </tbody>
</table>

<%= will_paginate @calls, :renderer => BootstrapPagination::Rails %>

【问题讨论】:

  • 调用 CSV 页面的 HTML 代码是什么?
  • 我正在使用它来生成一个 CSV 文件以供下载,它似乎正在使用 params.merge: "btn btn-info" %>

标签: ruby-on-rails-3 search activerecord export-to-csv


【解决方案1】:

在我看来,这是需要保留参数并合并它们的代码。

 <%= link_to "Export Results to CSV", reports_path(params.merge(format: "csv")), :class => "btn btn-info" %>

注意params.merge,它获取所有选定的参数,合并它们,然后将它们传递给控制器​​。

【讨论】:

  • 这是我的 excel 输出所需的。太棒了!
【解决方案2】:

在您的 Call#to_csv 方法中,您有:

all.each do |call|
        csv << [call.id, call.caller_name, call.caller_phone, call.created_at, call.call_status, call.incident_number, call.nature.determinant, call.service_level.level_of_service, call.patient_name, call.patient_age, call.patient_sex.sex, transfer_from_name(call), transfer_to_name(call), call.insurance.insurance_type, call.transfer_date, call.units.map(&:unit_name).join(", "), call.imx_num]
      end

我认为 all 是加载整个数据集的内容,而不是您的过滤版本。

如何传入实际行以转换为 CSV,例如:

def self.to_csv(records = [], options = {})
    CSV.generate(options) do |csv|
      csv << ["Call ID", "Caller Name", "Caller Phone", "Call Created At", "Call Status", "Incident Number", "Diagnosis", "Service Level", "Patient Name", "Patient Age", "Patient Sex", "Transfer From", "Transfer To", "Insurance", "Transfer Date", "Unit", "IMX Number"]
      records.each do |call|
        csv << [call.id, call.caller_name, call.caller_phone, call.created_at, call.call_status, call.incident_number, call.nature.determinant, call.service_level.level_of_service, call.patient_name, call.patient_age, call.patient_sex.sex, transfer_from_name(call), transfer_to_name(call), call.insurance.insurance_type, call.transfer_date, call.units.map(&:unit_name).join(", "), call.imx_num]
      end
    end
  end

然后更新你的控制器:

format.csv { send_data Call.to_csv(@calls }

【讨论】:

  • 好的,我试过了。通过这种方式,它仍然会导出所有呼叫记录,而忽略搜索查询。还必须在控制器中添加一个 ) 到 format.csv { send_data Call.to_csv(@calls) } 以使其工作。我认为你有一个语法错误。我想我不明白如何将搜索参数传递给 to_csv 方法。您描述的方式只是导出所有调用。提前致谢。
  • 您没有将搜索参数传递给 to_csv 方法。您正在使用Call.report 生成过滤集,然后将记录传递给to_csv,以便将其转换为所需的CSV 格式。换句话说,to_csv 不应该自己进行任何获取 - 您只需将之前获取的记录传递给按摩以供显​​示
  • 我现在关注你了。那么在我的视图代码中,我将如何制作一个按钮来生成过滤结果的 CSV?我正在使用: "btn btn-info" %> 但它只是导出所有调用而不是实例变量@calls。
  • 我想我明白了。 "btn btn-info" %> 似乎只导出特定的搜索结果。这听起来对吗?
  • @shakycode,您的评论就是答案,现有答案需要编辑
【解决方案3】:

params.merge 在这样的情况下创造奇迹。此外,为表单设置两个提交按钮也可以。例如,一个是导出 csv。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多