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:
class Admin::ReportsController < AdminController
respond_to :csv
def trips
respond_with TripReport.new
end
end
Instances of TripReport have a to_csv method.
When I make a request to that action I get the following error:
ActionView::MissingTemplate (Missing template admin/reports/trips with {:formats=>[:csv], :handlers=>[:erb, :builder, :rjs, :rhtml, :rxml], :locale=>[:en, :en]} in view paths
So it looks like the controller is looking for a template file to render. How can I get around this?
I’d rather the csv format responded in a similar way to json, so it calls to_csv on the object and just renders the output, is this possible?
I’ve been struggling with the exact same problem. I might have found a solution.
I found some clues while reading the Renderers.add source code for :json and :xml (link is for Rails 3.0.10 code, 3.1 might have some changes already):
https://github.com/rails/rails/blob/v3.0.10/actionpack/lib/action_controller/metal/renderers.rb
First, add a simple
as_csvmethod to your model definition:This can be anything, just make sure to return a hash with key/value pairs. A Hash works better than an Array, as with keys you’re able to add a header row to the CSV output later on. The idea for
as_csvcomes from Rails’as_jsonmethod, which return a Ruby object that is used byto_jsonto generate the actual JSON (text) output.With the
as_csvmethod in place, put the following code in a file inconfig/initializersinside your app (name itcsv_renderer.rb, for example):And finally, add CSV support to your controller code:
The initializer code is largely based on the :json and :xml behaviour from the Rails source code (see link above).
Currently, the
optionshash passed to the block doesn’t get passed to theto_csvcall, as CSV is quite picky on which options it allows to be sent. Rails adds some default options by itself (like :template and some others), which gives you an error when passing them toto_csv. You can change the default CSV rendering behaviour by adding your own preferred CSV options to the initializer, of course.Hope this helps!