Rails Exporting CSV ignore blanks - ruby-on-rails

I'm trying to create a simple CSV export in Rails. The export works fine except when deleting/archiving table items. I'm guessing this is because the export is encountering blanks.
This is working:
= link_to transactions_path(format: :csv) do
Except when there is a item missing from the transaction.
Tried this
= link_to transactions_path(format: :csv,skip_blanks: true) do
but I still get a ERR_INVALID_RESPONSE when calling the export
TransactionController:
respond_to :html, :json, :csv
def index
#shops = current_user.shops
respond_with(#shops) do |format|
format.csv do
response.headers['Content-Type'] = 'text/csv'
response.headers['Content-Disposition'] = "attachment; filename=transactions-#{Time.now.strftime('%Y%m%d%H%M')}.csv"
render inline: #shops.to_csv
end
end
end
Any suggestions?

Change to_csv to pass skip_blanks.
#shops.to_csv(skip_blanks: true)

If you want a link to download a CSV file, you should use send_data instead. If you want to display the file in the browser, use render text: #shops.to_csv
http://railscasts.com/episodes/362-exporting-csv-and-excel
respond_to :html, :json, :csv
def index
#shops = current_user.shops
respond_with(#shops) do |format|
format.csv do
send_data #shops.to_csv, type:'text/csv', filename: "transactions-#{Time.now.strftime('%Y%m%d%H%M')}.csv"
end
end
end
Change your link_to back to what you had before.
= link_to transactions_path(format: :csv)

Maybe using send_data:
def index
respond_to do |format|
format.csv { send_data #current_user.shops.to_csv, filename: "transactions-#{Time.now.strftime('%Y%m%d%H%M')}.csv" }
end
end
Also, is the to_csv an instance method?

Related

Why only first page results get exported to csv?

I am trying to get ALL the filtered results when exporting to CSV.
My to_csv is working fine, and I suspect something to do with my controller.
Search around with kaminari, ransack, but seems like even exporting to csv is rare using ransack.
Any help is much appreciated.
controller.rb
#search = Order.includes(:user, :order_items).ransack(params[:q])
#orders = #search.result.order(created_at: :desc).page(params[:page])
respond_to do
|format|
format.html
format.csv { send_data #orders.to_csv, filename: "orders-#{DateTime.now.strftime("%d%m%Y%H%M")}.csv" }
end
view.html.haml
= link_to 'Download as CSV', a_o_path(request.params.merge(format: 'csv')), { class: 'btn btn-primary', style: 'float: right;' }
You can do this with ransack and kaminari, but you'll need to update your controller just a bit. Here's what you have so far:
format.csv { send_data #orders.to_csv, filename: "orders-#{DateTime.now.strftime("%d%m%Y%H%M")}.csv" }
When your controller gets here, #orders has been filtered by ransack, but it has also been paginated by kaminari. Since you're responding with html in some cases and csv in others, you'll want to do something slightly different when you respond with csv.
Here's what I would try:
#search = Order.includes(:user, :order_items).ransack(params[:q])
#orders = #search.result.order(created_at: :desc)
respond_to do |format|
format.html { #orders = #orders.page(params[:page]) }
format.csv { send_data #orders.to_csv, filename: "orders-#{DateTime.now.strftime("%d%m%Y%H%M")}.csv" }
end
Basically, you only paginate the query when you respond with html. When csv is requested, all of the orders will still be there.

Why rails download csv file when I want to show html using render :text or html?

It's simple..
when I write it in my controller like this.
def index
#articles = News.order(:id)
respond_to do |format|
format.html
format.csv { render text: #articles.to_csv}
end
end
and in news.rb
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |product|
csv << product.attributes.values_at(*column_names)
end
end
end
What I expected when I open my site(http://localhost:3000/mycontroller.csv) is shows the text in my screen.
However, it just download csvfile..... Even when I changed render text to html.
What is wrong in my code?
You can try this code
class HomeController < ApplicationController
respond_to :html, :json, :csv
def index
#modelnames = Modelname.all
respond_with(#modelnames)
end
end

Creating collection of pdfs with wicked_pdf

I have problem collection of pdfs file and save it to file. I create this for show action so when I clink the link it generate pdf and store them in public folder:
def show
add_breadcrumb "Inovice details"
respond_to do |format|
format.html
format.pdf do
render :pdf => "file_name", :save_to_file => Rails.root.join('public', "Invoice no. #{#invoice.format_id}.pdf")
end
format.csv {send_data Invoice.where(id: #invoice.id).to_csv,
filename: "Invoice no. #{#invoice.format_id}.csv"}
end
end
Now I want to create the same functionality but for collection of objects. For examples I have 10 invoices and I want for all of them generate pdf and save it to public folder. I was trying something like that:
def index
#invoices = #company.invoices
respond_to do |format|
format.html
format.js
format.csv { send_data #invoices.to_csv }
format.pdf do
#invoices.each do |invoice|
render :pdf => "file_name", :save_to_file => Rails.root.join('public', "Invoice no. #{invoice.format_id}.pdf")
end
end
end
authorize #invoices
end
But it didnt work. I have no ideas how to solve this problem. I will be grateful for every help.
You can not send multiple PDF's in the same request.
I think a best solution is generate the PDF's in a background job ( https://github.com/mileszs/wicked_pdf/wiki/Background-PDF-creation-via-delayed_job-gem ) and present an HTML page with links to all you PDF's.
If that doesn't work for you, you can merge all the content in a big PDF file.

Ransack export results to CSV

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?
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')
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

CSV renders in Safari view but I want it to download a file

I have configured a custom mime type:
ActionController::Renderers.add :csv do |csv, options|
self.content_type ||= Mime::CSV
self.response_body = csv.respond_to?(:to_csv) ? csv.to_csv : csv
end
and a respond_to block in my controller:
respond_to do |format|
format.html
format.csv { render :csv => csv_code}
end
Using Firefox and Chrome, the .csv renders to a file which is downloaded. Using Safari the .csv is rendered as a view: How can I change this and force it to download as a file?
See a screen shot of the problem:
Try
respond_to do |format|
format.html
format.csv do
response.headers['Content-Type'] = 'text/csv'
response.headers['Content-Disposition'] = 'attachment; filename=thefile.csv'
render :csv => csv_code
end
end
if this doesn't work, try using
send_file "path/to/file.csv", :disposition => "attachment"
The way I have this working in an old Rails 2 app is using send_data instead of render in the controller. E.g.:
def csv
... # build data
send_data csv_data_as_string, :filename => "#{filename}.csv", :type => 'text/csv'
end

Resources