export CSV by rails
I will not save a file, just make it downloaded by Tempfile
.
I will not use database table, of course.
This is how my form looks (in new
page)
config/routes.rb
file
resources :accounts, only: [:new, :create]
app/views/accounts/new.html.erb
file
<%= form_with url: accounts_path, local: true do |f| %>
<%= f.text_area :names, rows: 10, required: true %>
<p>Add account names separated by newline.</p>
<%= f.submit 'Export CSV' %>
<% end %>
When the form is submitted, it triggers create
action. Form submit of form_with
makes POST request to accounts_path
with parameters. And rails syntax resources :accounts
makes create
action of accounts controller triggered by that POST request.
And this is not a model backed form. Sometimes simple things look difficult or not possible because the other complicated things look too easy. ActiveRecord is not needed (something like @account
in the form) in this case, because we are not going to save anything.
app/controllers/accounts_controller.rb
file
class AccountsController < ApplicationController
def create
# ...
end
end
At this point params[:names]
is available in create
method. (we call it an ‘action’ because it’s a method in a rails controller) So, we can use user input from the form here.
This is for instagram accounts. I wanted to show this code because this tool does not work. So do not use it for fetching data from instagram.
def create
headers = ['account_name', 'business_email', 'business']
filename = "business emails #{Date.today}.csv"
Tempfile.open do |tempfile|
CSV.open(tempfile.path, "wb", write_headers: true, headers: headers) do |csv|
params[:names].split("\r\n").each do |account_name|
account_name = account_name.tr(' ', '')
uri = URI("https://www.instagram.com/#{account_name}/?__a=1")
res = Net::HTTP.get_response(uri)
if res.is_a?(Net::HTTPSuccess)
body = JSON(res.body)
business_email = body['graphql']['user']['business_email']
is_business = body['graphql']['user']['is_business_account']
csv << [account_name, business_email, is_business]
end
end
end
send_data File.read(tempfile.path), filename: filename, type: 'text/csv'
end
end
ruby Tempfile
is used and CSV
is used (you may need require 'csv'
on top of the file). I put everything in the Tempfile.open
block because everything should happen before the tempfile is closed. Other than that, some net/http
code is used.
So now we can generate / export a CSV file without saving a file, without database. Thank you