Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a CSV file in action?

I am trying to generate a CSV output with data from my database. I would like to provide these data to a third party, so I picture I would give to someone a URL (website.com/api_data/cars) and by accessing this URL the person would be able to work with it - I think I want to access the URL and then to see there (in the action) data displayed and separated by , or ;.

But how to do that?

So far, I am trying following approach:

csv_string = CSV.generate do |csv|
  cols = ["column one", "column two", "column three"]
  csv << cols
  csv << ["A", "B", "C"]

  @filename = "data-#{Time.now.to_date.to_s}.csv"  
end
send_data(csv_string, :type => 'text/csv; charset=utf-8; header=present', :filename => @filename)  

This is in the controller generate_data and action csv_cars.

When I run this action (webste.com/generate_data/csv_cars), it will automatically pop up a window to download the file.

But how to write the CSV content to the action? So when I open the URL, I'll see there written the content from the database?

like image 995
user984621 Avatar asked Aug 01 '15 14:08

user984621


People also ask

How do I automate a CSV file in Excel?

Power Automate allows you to open comma-delimited and tab-delimited CSV files directly through the Launch Excel action. To convert a CSV file of this type to XLSX, open the file and then save it as a new Excel workbook using the Save document as option in the Close Excel action.

How do I create a CSV file from text?

Go to File > Save As. Click Browse. In the Save As dialog box, under Save as type box, choose the text file format for the worksheet; for example, click Text (Tab delimited) or CSV (Comma delimited). Note: The different formats support different feature sets.


1 Answers

I know this is an old thread but I came across it in my search so in case someone else does the same, here's my answer and what worked for me.

I think bhanu had a good way of going about it but I did change something. Instead of doing @cars within the respond_to, I just called send_data Cars.to_csv since, as Rob stated, it was made as a class method. It worked beautifully for me.

class Car < ActiveRecord::Base
  def self.to_csv(make)
    attributes = %w{id name price} #customize columns here
    cars = Car.where(maker_name: make)

    CSV.generate(headers: true) do |csv|
      csv << attributes

      cars.each do |car|
        csv << attributes.map{ |attr| car.send(attr) }
      end
    end
  end
end

And then in the controller

class CarsController < ApplicationController
  def index
    send_data Cars.to_csv('Chevy'), filename: "cars-#{Date.today}.csv"
  end
end

I understand that this will be called when you go to cars/index but you can put that into any method, if statement or anything you want and just have it called whenever you would like from there. You can also have arguments, as I did above with make, and query for certain fields. It was definitely a lot easier than I thought it was going to be. Hope this helped someone.

like image 177
nmrichards Avatar answered Oct 19 '22 23:10

nmrichards