Rails export to CSV file - ruby-on-rails

It is partly working. It generates the file but the output is not how I want it.
Controller
#messages = Message.take(2)
respond_to do |format|
format.html
format.csv { send_data #messages.to_csv }
end
Message.rb
def self.to_csv
CSV.generate do |csv|
csv << Message.attribute_names
Message.all.each do |message|
csv << message.attributes.values
end
end
end
I get the CSV file downloaded, it contains the records itself but it does not show the columns and values
#<Message:0x007fca7a028338>,#<Message:0x007fca79a6bf58>
I would expect the Message attributes like:
ID,text
1,hello
2,world

Message.take(2) returns Array. You need ActiveRecord::Relation.
Try Message.limit(2)

Related

How do I export a filtered table to CSV?

controller code
def index
#courses = Course.all
respond_to do |format|
format.html
format.csv { send_data #courses.to_csv }
end
end
Link code
<%= link_to "Export Course", courses_path(format: :csv) %>
model code
def self.to_csv
CSV.generatezz do |csv|
csv << column_names
all.each do |product|
csv << product.attributes.values_at(*column_names)
end
end
end
With that code, I can properly export a csv file that contains every course in the database. I want to set it up where I can export only the information of one course. If possible i'd like to use a variable(like a url parameter) as I have other tables I want to iterate over with the same id that would let me get one course to the csv.
The model code is a class method, which annoyingly enough won't work for an instance of that class, so I can't, in the controller, go #courses = Course.find(params[:course_id].to_i) and then send_data #courses.to_csv, as it acts as if its an entirely new thing.
Any help on this would be great, thanks.
What if you made an instance method:
def to_csv
CSV.generatezz do |csv|
csv << column_names
csv << attributes.values_at(*column_names)
end
end
I dont know what column_names is here, maybe another method you made? Anyhow, you should be able to call that in your controller after you set the #course variable with #course = Course.find(params[:id])

export an object to csv file currently displaying data inline

I have #people variable contains data look exactly like:
What I have
[{"id"=>1, "name"=>"Tom", "age"=>"25"},
{"id"=>2, "name"=>"Marry", "age"=>"27"},
{"id"=>3, "name"=>"Jack", "age"=>"28"}]
and I am trying to convert the data to the CSV file, which might look like
What I am aiming to do
id | name | age
1 | Tom | 25
2 | Marry| 27
3 | Jack | 28
but my code generates a CSV file with displaying all of the data inline. For example:
What I get
{"id"=>1,"name"=>"Tom","age"=>25},{"id"=>2, "name"=>"Marry",
"age"=>"27"},{"id"=>3, "name"=>"Jack", "age"=>"28"}
What I did:
to_csv action look like:
def to_csv
CSV.generate(option) do |csv|
csv << column_names
values.each do |value|
csv << value.attributes.values_at(*column_names)
end
end
end
I added this respond_to block to one of my actions:
respond_to do |format|
format.html
format.csv {
send_data #people.to_csv,
filename: "export.csv",
type: 'text/csv; charset=utf-8'
}
I am getting data(e.g {"id"=>1,"name"=>"Tom","age"=>25 ...) from external so I pushed that data into #people variable to use. Any help would be very appreciated.
I think you need to write the function differently:
def to_csv(people)
CSV.generate do |csv|
return unless people.count > 0
csv << people[0].keys
people.each do |person|
csv << person.values
end
end
end
I suppose you could even do:
def to_csv(people)
CSV.generate do |csv|
return unless people.count > 0
csv << people[0].keys
csv << people.each.map{|item| item.values}
end
end
And then call it as a function:
respond_to do |format|
format.html
format.csv {
send_data to_csv(#people),
filename: "export.csv",
type: 'text/csv; charset=utf-8'
}
you Don't need to do like value.attributes.values_at(*column_names) just you need to do value.values which will give you the array of values that you want to store it in CSV.
for example
people = [{"id"=>1, "name"=>"Tom", "age"=>"25"},
{"id"=>2, "name"=>"Marry", "age"=>"27"},
{"id"=>3, "name"=>"Jack", "age"=>"28"}]
def to_csv
CSV.generate(headers: true) do |csv|
csv << column_names
people.each do |person|
csv << person.values
end
end
end
Here is how i do mine,
in my controller i added
respond_to do |format|
format.html
format.csv { send_data #people.to_csv }
end
then
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |project|
csv << people.attributes.values_at(*column_names)
end
end
end
then dont forget to require 'csv' in your config/application.rb
then you can link to your csv with something like <%= link_to "CSV", people_path(format: "csv") %>

Ruby on Rails - export user data to csv - button

Since I ended up using a csv method and not a json method I thought it might be a good Idea to change the question name and remove the part with the json if other people might have the same problem someday.
Update: I've tried using this as a way to export data.
In my controller I have the following:
def profile
#user = User.find(params[:id])
#user_posts = #user.posts.order('created_at DESC')
respond_to do |format|
format.html
format.csv { send_data #user.csv, filename: "userinfo-#{Date.today}.csv" }
end
end
In my view :
<p><%= link_to("Generate Report", user_path(#user, format: :csv), class: "btn btn-success",) %></p>
In my user.rb :
def csv
CSV.generate do |csv|
csv << column_names
all.each do |item|
csv << item.attributes.values_at(*column_names)
end
end
end
Update 2: Managed to fix it myself, I was using a wrong csv method in my Controller. Replacing it with the following :
def csv
CSV.generate do |csv|
csv << %w{ user_id user_username user_email }
csv << [ self.id, self.username, self.email]
end
end
works like a charm.
Best regards

Rails CSV export to server instead of download

I have a form which when submitted takes all the input and generates a csv. I am using CSV.open in my model so that the file is sent to the server. However, even with this, there is a separate CSV file with a random CSV code that is generated. It does not contain any form details, however, it would be ideal if no CSV is downloaded at all. I just want to CSV to get uploaded to the server.
Model:
def csv
attributes = %w{ first_name last_name }
CSV.open("#{Rails.root}/public/#{self.first_name}.csv", "wb") do |csv|
csv << attributes
csv << [ self.first_name, self.last_name ]
end
end
controller:
def method
if conditions
student = Student.find(params[:id])
respond_to do |format|
format.html {redirect_to students_path, :notice => "Success"}
format.csv { send_data student.csv }
end
else
redirect_to students_path, :notice => "Declined"
end
end
Please let me know whats wrong

Rails 4 download to CSV

I'm building a marketplace app so sellers can list items to sell. I'm trying to download a CSV by seller so sellers can download their own listings.
I'm following the code in this railscast. I got the railscasts code to work as-is. It downloads all the data from my model into a csv. But when I add a seller filter to the query, it doesn't apply the filter.
In listings_controller:
def index
#listings = Listing.not_expired.order("created_at DESC")
respond_to do |format|
format.html
format.csv { send_data #listings.to_csv }
end
end
def seller
#listings = Listing.where(user: current_user).order("created_at DESC")
respond_to do |format|
format.html
format.csv { send_data #listings.seller_csv }
end
end
in listing.rb:
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |listing|
csv << listing.attributes.values_at(*column_names)
end
end
end
def self.seller_csv
CSV.generate do |csv|
csv << column_names
where(user: current_user).each do |listing|
csv << listing.attributes.values_at(*column_names)
end
end
end
The to_csv methods works fine and downloads all listings. But the seller_csv method also downloads all listings. I need it to filter by current_user. What am I missing?
Make your function take a list of listings as parameter.
def self.to_csv(listings)
CSV.generate do |csv|
csv << column_names
listings.each do |listing|
csv << listing.attributes.values_at(*column_names)
end
end
end
Then you cane re-use the same function in the two scenarios
def index
#listings = Listing.not_expired.order("created_at DESC")
respond_to do |format|
format.html
format.csv { send_data Listing.to_csv(#listings) }
end
end
def seller
#listings = Listing.where(user: current_user).order("created_at DESC")
respond_to do |format|
format.html
format.csv { send_data Listing.to_csv(#listings) }
end
end
Your code didn't make really sense as you were fetching listings in your controller but never re-used those fetched objects and was re-calling DB in your model's static functions.

Resources