Ransack export results to CSV
Asked Answered
P

3

5

I'm trying to export a list of Ransack (Railscast) results to a CSV file (Railcast). However, it keeps exporting all of the objects, instead of the results returned by the Ransack search. Can anyone tell me where I'm going wrong?

In the Reports controller, I've tried passing both @bookings and @search.result:

  def index
    @search = current_user.bookings.search(params[:q])
    @bookings = @search.result
    @search.build_condition
    respond_to do |format|
      format.html 
      format.csv { render text: Booking.to_csv(@bookings) }\
    end
  end

And then the Booking to_csv method:

  def self.to_csv list
    CSV.generate do |csv|
      csv << column_names
      list.each do |booking|
        csv << booking.attributes.values_at(*column_names)
      end
    end
  end

Yet every time, I get the unfiltered list of current_user.bookings. Why?

Pinnate answered 7/6, 2013 at 15:2 Comment(4)
Does @bookings contain what you want?Jabot
Yes - when the index action displays the HTML page, the list of @bookings is filtered correctly (with the @search.result). But for some reason the CSV file just contains everything. Is it to do with the way I'm passing it to the Booking model?Pinnate
I don't see anything immediately wrong with your code. I dislike that you don't wrap your list method argument in parens, but that's not a syntax issue. Have you tried logging list and each booking from within your to_csv method?Jabot
I haven't - but I'm also not quite sure how. Can you point me in the right direction as to what you mean (a link would be ace)? Thanks!Pinnate
S
13

To export only the filtered results as csv, you should make sure that the search parameters are included in the url you call to generate the csv.

Hence, if you want to export the results that you see on the html page you should call: reports_path(params.merge(format: 'csv')

Sporozoite answered 14/6, 2013 at 17:20 Comment(2)
= link_to 'csv', search_servers_path(params.merge(format: 'csv')), class: 'btn' #It rolls all your search query parameters into the link press so your controller receives all the search params. You have to be using GET in your search_form_for. Otherwise the POST'ed parameters won't show up.Ivers
As per this answer you might now need to use request.parameters.merge to comply with strong parameters changes in newer rails versions. I got mine working like products_path(request.parameters.merge({format: 'csv'}))Dilisio
S
1

Try this:

def index

  session[:q] = params[:q] if params[:q]
  @search = current_user.bookings.search(session[:q])

  @bookings = @search.result
  @search.build_condition
  respond_to do |format|
    format.html 
    format.csv { render text: Booking.to_csv(@bookings) }\
  end
end
Suneya answered 3/7, 2013 at 18:23 Comment(1)
If you use more than one report on your app, you need to change the session[:q] for session[:q_SOME_ID] to avoid conflicts.Suneya
C
0

Binoy Michael's answer is on the money, but needs to be updated for strong params since Rails 5 (2016) as discussed in this answer. Unfortunately getting the exact syntax right is a bit tricky - if you simply permit a nested hash with your search query like this:

<%= link_to 'Export to CSV with search options', 
    objects_path(params.permit(q:[:attribute_one_eq, :attribute_two_cont])
    .merge({format: :csv})) %>

then the format will also get passed as a param rather than modifying the actual link, yielding:

www.example.com/objects?format=csv&q= ...

Your controller will parse this correctly and return the right format, but it still causes issues because the user's browser won't correctly populate the ".csv" file extension when saving the file.

In order to get the desired link format like so:

www.example.com/objects.csv?q= ...

You need to counterintuitively re-nest the search parameters in your query object, like so:

    <% if params[:q] %>
      <%= link_to 'Export CSV with search options', objects_path(
              {q: params.require(:q).permit(:attribute_one_eq, :attribute_two_cont)}
              .merge({format: :csv})) %>
    <% else %>
      <%= link_to 'Export all to CSV', impairments_path(format: 'csv') %>
    <% end %>

Credit to Jay Kileen's comment for setting me on the right path, but I figured I'd post a full answer here because I spent way too long getting the syntax exactly right for myself.

Coady answered 21/7, 2023 at 1:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.