Skip to content

Instantly share code, notes, and snippets.

@jeffreyiacono
Created August 2, 2011 22:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffreyiacono/1121381 to your computer and use it in GitHub Desktop.
Save jeffreyiacono/1121381 to your computer and use it in GitHub Desktop.
Simple Exporter
require 'csv'
# Class that takes a set of records from a Rails app and returns CSV'd goodness
# Record's must implement class method #csv_exportable_headers and instance method #csv_exportable_attributes
# Note: This probably should be moved to a module where the headers / attributes are defined
class Exporter
module CSV
def self.export(records)
# TODO: dropout if records is blank
klass = records.model_name.constantize
raise "#{klass} must implement csv_exportable_headers" unless klass.respond_to? :csv_exportable_headers
raise "#{klass} must implement csv_exportable_attributes" unless klass.method_defined? :csv_exportable_attributes
::CSV.generate do |csv|
# headers
csv << klass.csv_exportable_headers
# values
records.each do |record|
csv << record.csv_exportable_attributes
end
end
end
end
end
### TESTS ###
require 'spec_helper'
class Item
def attribute_a
'Attribute A value'
end
def attribute_b
'Attribute B value'
end
end
describe Exporter do
context 'csv' do
describe 'self.export' do
it 'should raise an error if passed record model does not implement #csv_exportable_headers' do
lambda { Exporter::CSV.export(Item.new) }.should raise_error, 'Item must implement csv_exportable_headers'
end
it 'should raise an error if passed records does not implement #csv_exportable_attributes' do
Item.instance_eval { def csv_exportable_headers; end }
lambda { Exporter::CSV.export(Item.new) }.should raise_error, 'Item must implement csv_exportable_attributes'
end
it 'should help me' do
Item.instance_eval { def csv_exportable_headers; ["Attribute A", "Attribute B"]; end }
Item.class_eval { def csv_exportable_attributes; [:attribute_a, :attribute_b]; end }
# As this is a rails app, Exporter expects an ActiveRecord::Relation
# which responds to #model_name. Give it what it wants.
fake_active_record_relation = [Item.new]
fake_active_record_relation.stub(:model_name => 'Item')
Exporter::CSV.export(fake_active_record_relation).should == "Attribute A,Attribute B\nattribute_a,attribute_b\n"
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment