Rails Persist Search Results to CSV Output
activerecord, export-to-csv, ruby-on-rails-3, search
Solution
In your `Call#to_csv` method you have:
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
I'm thinking the `all` is what is loading up the entire data-set, not your filtered version.
How about passing in the actual rows to convert to CSV, like:
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
And then updating your controller:
format.csv { send_data Call.to_csv(@calls }
Problem
I have a Rails 3.2.x app where I have a reporting controller that does search on the Call model. The code I put together works fine and allows for multiple conditions that will display on the page. The problem I'm having is with exporting the specific search results to a CSV file. So far I've only been able to export the entire database to CSV instead of the specific search results. I'd like to figure out how to get my search params to persist and be able to export only those records to CSV. Here is my relevant code: 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 %> ```