Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Exporting Data to CSV in Ruby on Rails

February 10, 2014 By Austin Story 2 Comments

So in our application we have a list of clients that our users are tracking (called trackers). One of our clients needed the ability to quickly export this data. In ruby this is super easy. We just add a few lines to our controller and model. In our controller, we already have an instance of their active trackers (@trackers_enabled )and it just grabs the trackers that are enabled.

[ruby]
trackers_controller.rb

respond_to do |format|
format.html
format.csv { send_data @trackers_enabled.to_csv}
end
[/ruby]

This allows us to export the data by just appending .csv to the url, so to access this we just add a link in the view. In the model we just add.

tracker.rb
[ruby]
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |row|
csv << row.attributes.values_at(*column_names)
end
end
end
[/ruby]

This is a quick solution and can be found in about 20 places around the internet, but it adds some unnecessary fields like created_at, updated_at and user_id to the csv.

To limit that data we just have to do some investigation on the column_names and see what type of data it returns in IRB.

In irb
[ruby]
Tracker.column_names
=> ["id", "user_id", "address", "first_name", "last_name", "enabled", "created_at", "updated_at"]
[/ruby]

So now we know that column names is just an array of the columns. To grab just the ones we are interested in we edit tracker.to_csv to have the columns we want or we could edit column_names to just specify the columns we want. I opted with the first because it won’t have any unintended consequences.

tracker.rb

[ruby]
def self.to_csv(options = {})
CSV.generate(options) do |csv|
columns = %w(first_name last_name age address description)
csv << columns
all.each do |row|
csv << row.attributes.values_at(*columns)
end
end
end
[/ruby]

Then in the view code you can add something like this if you are using bootstrap.

[ruby]
<div class="container-fluid padded">
<%= link_to "Export #{@trackers_enabled.count} Trackers to CSV", params.merge(:format => :csv), :class => "btn btn-green" %>
</div>
[/ruby]

Filed Under: Programming, Ruby, Ruby on Rails

Comments

  1. Makgwela says

    May 28, 2016 at 12:08 am

    Thank you for the lesson.

    Let’s just say you want to control the exported colums by using checkboxes. Instead of specifying them, you want to choose exported columns by checkboxes so that you can have different report everytime you wish to.

    Reply
    • Austin Story says

      June 18, 2016 at 9:53 pm

      I would approach that in the following way.

      1. in your model, set a variable like ALLOWED_EXPORTABLE_COLUMNS. This can also be done in a config.yml file if you already have something like that in your system. That will be an array similar to [:created_at, :updated_at]

      2. in your view, iterate over this array and create a check_box for each of the allowed

      3. on_click for your submit button, set the query string on your URL using javascript based on the columns that are selected, i would just use a string here.

      4. in your controller, slice those values that came in with your ALLOWED_EXPORTABLE_COLUMNS.

      5. profit! (use the concept i had previously only accept the columns submitted in this way dynamically

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • AngularJS
  • Books
  • Devise
  • Elasticsearch
  • ES6
  • Information Security
  • Integrations
  • Javascript
  • Linux
  • Minitest
  • PhoneGap
  • Programming
  • React
  • Redux
  • Ruby
  • Ruby on Rails
  • Stripe
  • Testing
  • Theory
  • TypeScript
  • Uncategorized
  • Vue
  • Webpack