I am trying to export some data to CSV in Rails 4. I have two models: Excursions and Inscriptions. One excursion has many inscriptions and one inscription belongs to one excursion.
I have my nested routes defined this way:
resources :excursions do
resources :inscriptions
get 'exportcsv' => 'excursions#download'
end
So the behavior I am trying to achieve is: when I visit the route /excursions/1/exportcsv, a CSV will be downloaded to my computer and it will contain all the inscriptions with excursion_id = 1 in CSV format.
In my excursion model I have defined self.to_csv:
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
self.inscriptions.each do |inscription|
csv << inscription.attributes.values_at(*column_names)
end
end
end
And my excursion controller's method download:
def download
@excursion = Excursion.find(params[:id])
respond_to do |format|
format.html
format.csv { send_data @excursion.to_csv }
end
end
EDIT: When I go to a route like: /excursions/:id/exportcsv the server is throwing an ActiveRecord::RecordNotFound error. This error is easy to solve, but if I solve the RecordNotFound I get an ActionController::UnknownFormat in this line:
def download
@excursion = Excursion.find(params[:id])
respond_to do |format| ########THIS LINE
format.html
format.csv { send_data @excursion.to_csv }
end
end
What I am doing wrong? Maybe all this approach is not correct...
I would update the routes to the following:
resources :excursions do
get 'download', on: :member, constraints: { format: /(html|csv)/ }
resources :inscriptions
end
Also there is a bug in your model code. You are exporting inscriptions
but are using Excursion
column_names instead of Inscription
column_names. Following is the updated model code.
class Excursion < ActiveRecord::Base
def to_csv(options = {})
CSV.generate(options) do |csv|
inscription_column_names = Inscription.column_names
csv << inscription_column_names
self.inscriptions.each do |inscription|
csv << inscription.attributes.values_at(*inscription_column_names)
end
end
end
Now try to access http://localhost:3000/excursions/:id/download.csv
Replace :id
with an existing Excursion
records id. If you still encounter ActiveRecord::RecordNotFound
error, then the problem could be that you are trying to access an Excursion
that doesn't actually exist in the database.