Data portability is an extremely important feature for any software-as-a-service company. At Mobile Commons, we strongly believe that our customers’ data is their data and work hard to make sure that information is portable. Whether they want to run their own analytics or share data between different software applications, customers can easily export any Mobile Commons data to CSV.
Because this is such a common requirement, we developed a Rails plugin to automatically make any collection of items in our application (text messages, phone calls, donations, profiles, etc.) exportable in CSV format.
The main features are:
- Transform an array of exportable records into a whole CSV file. (By default, FasterCSV transforms arrays into a singleCSV row.)
- Export a whole table by calling
.to_csvon the ActiveRecord subclass. - By default, export all of an ActiveRecord’s columns except for created_at and updated_at.
- Allow simple customization of exportable columns by overriding the
export_columnsmethod in your ActiveRecord class. - Allow multiple CSV formats by conditionally branching inside the
export_columnsmethod depending on the format parameter. - Override the names of the columns that get exported (default is the database column names)
- Allow complete customization of the export by overriding the
to_rowmethod.
The simplest use-case is just calling to_csv on an ActiveRecord model. This will export the contents of entire table to CSV format
1 |
Address.to_csv |
Pastie #340751 linked directly from Pastie.
The more common scenario is calling it on a collection of ActiveRecord Models:
1 |
Address.find(:all, :conditions=>{:city=>'New York'}).to_csv
|
Pastie #340753 linked directly from Pastie.
You can customize which columns are included in the CSV by defining an export_columns function in your model class. The default is every columns except created_at and updated_at:
1 2 3 4 5 |
class Address < ActiveRecord::Base
def export_columns(format = nil)
%w[city state postal_code]
end
end
|
Pastie #340730 linked directly from Pastie.
You can also define multiple output formats for a single model. Just modify your export_columns function to take a format parameter and return different values depending on its value.
1 2 3 4 5 6 7 8 9 10 11 12 |
class Address < ActiveRecord::Base
def export_columns(format = nil)
case format
when :local
%w[street1 street2 city state postal_code]
else
%w[city state postal_code]
end
end
end
|
Pastie #340733 linked directly from Pastie.
You can override any of the column names. This is useful if you use any technical terms and want to “translate” them before exporting for customers (e.g. a column named ‘guid’ might be exported as “Unique ID”).
1 |
Address.to_csv(:columns => [:city, :state, {:guid => :unique_id}])
|
Pastie #340734 linked directly from Pastie.
The code is quite small. You can simply save it as a file called exportable.rb in the lib folder of your Rails project or install it as a Rails Plugin from GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
require "fastercsv"
class ActiveRecord::Base
def self.to_csv(*args)
find(:all).to_csv(*args)
end
def export_columns(format = nil)
self.class.content_columns.map(&:name) - ['created_at', 'updated_at']
end
def to_row(format = nil)
export_columns(format).map { |c| self.send(c) }
end
end
class Array
def to_csv(options = {})
if first.respond_to?(:to_row)
if options[:columns]
cols = []
headers = []
options[:columns].each do | column |
if column.is_a?(Hash)
column.each do | key, value|
cols << value
headers << key
end
else
cols << column
headers << column
end
end
else
headers = cols = first.export_columns(options[:format])
end
csv = FasterCSV.new("", options.block(:format, :columns))
csv << headers
each do |row|
csv << cols.map do |col|
row.send(col)
end
end
csv.string
else
FasterCSV.generate_line(self, options.block(:format,:columns))
end
end
end
|
Pastie #340750 linked directly from Pastie.
Credit to Bryan Helmcamp and East Media, who wrote the original version for Mobile Commons.