Rails将搜索结果保持为CSV输出

时间:2014-01-07 22:04:39

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

我有一个Rails 3.2.x应用程序,我有一个报告控制器,可以搜索呼叫模型。我放在一起的代码工作正常,允许在页面上显示的多个条件。我遇到的问题是将特定搜索结果导出到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

Call.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 %>

3 个答案:

答案 0 :(得分:4)

在我看来,这是需要持久化并合并它们的代码。

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

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

答案 1 :(得分:3)

使用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 }

答案 2 :(得分:0)

在这样的情况下,

params.merge会产生奇迹。此外,为表单提供两个提交按钮。例如,一个是导出csv。