I have an object that has a to_csv method and I want to pass it to respond_with to render csv from my controller. My code looks like this:
This is an old question but here's an updated method for the custom Renderer for newer versions of Rails (currently using 3.2.11 and Ruby 1.9.3) taken from the ActionController::Renderers documentation: http://api.rubyonrails.org/classes/ActionController/Renderers.html#method-c-add
As florish said, create an initializer but add this code:
ActionController::Renderers.add :csv do |obj, options|
filename = options[:filename] || 'data'
str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
send_data str, :type => Mime::CSV,
:disposition => "attachment; filename=#{filename}.csv"
end
And use it as such:
def show
@csvable = Csvable.find(params[:id])
respond_to do |format|
format.html
format.csv { render :csv => @csvable, :filename => @csvable.name }
end
end
I take no credit for the code above, it's straight from the documentation, but this worked for me in Rails 3.2.11 so pointing it out for people coming across this thread for the first time.
In my project I'm not using a to_csv method, I'm actually building the CSV manually first. So here's what mine looks like:
def show
items = Item.where(something: true)
csv_string = CSV.generate do |csv|
# header row
csv << %w(id name)
# add a row for each item
items.each do |item|
csv << [item.id, item.name]
end
end
respond_to do |format|
format.csv { render :csv => csv_string, :filename => "myfile.csv" }
end
end
You should obvious move the CSV creation code to some other class or model but putting it here inline just to illustrate.