12

I've been reading similar questions, but many of the answers are outdated or not clear enough for me.

I'd like to be able to just do something like (in a controller action):

respond_to do |format|
  format.html
  format.csv
end

I know I'd then need a view such as action.csv.erb


So my questions are:

1) What do I need to configure in rails to allow this to happen in general.

2) How should I setup the CSV view to display some basic fields from a model?

UPDATE:

So I've tried to go the route of comma, I installed and vendored the gem.

Then according to the read me, I threw this into my model (customized to my needs):

comma do

user_id 'User'
created_at 'Date'
name 'Name'
end

I then threw this in the control for the index action (according to the readme):

  format.csv { render :csv => MyModel.limited(50) }

Then when accessing the index (not in CSV format) I receive the following ActionController Exception error:

undefined method `comma' for

So then I googled that, and I read that I should put require 'comma' in my model.

After doing that, I refreshed (my local index page), and the error changed to:

no such file to load -- comma

So at this point I decided it must not be finding the comma files obviously. So I copied the files from the vendored gem folder of comma, from comma's lib folder, to the rails lib folder. I then refreshed the page and landed on this error:

uninitialized constant Error

Then I pretty much gave up.

The errors from the trace were:

/Users/elliot/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in load_missing_constant' /Users/elliot/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in const_missing' /Users/elliot/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in `const_missing'

Other notes, I have already installed FasterCSV

Hope thats enough info :)

Elliot
  • 13,580
  • 29
  • 82
  • 118

4 Answers4

11

I suggest taking a look at comma. It works very well and allows you to handle stuff at the model level, as opposed to the view level.

theIV
  • 25,434
  • 5
  • 54
  • 58
  • I've been trying this with no success. – Elliot Mar 18 '10 at 23:15
  • What didn't work out for you? If you are getting an error, could you update your original post with that error? – theIV Mar 19 '10 at 00:20
  • I can't seem to recreate your issue :/ I just started a new rails 2.3.5 project, installed comma as a gem, required it in my environment.rb file, unpacked the gem, created a dummy model with a call to comma and it works. Do you actually have a `limited` method on your model? If you try to just put the `.csv` format on the index and just pass it in every instance of your model, does it still not work? – theIV Mar 19 '10 at 19:48
  • Thanks for the continued effort, sometime yesterday I decided to give up on CSV for now and went a different route. Next time I come back to it I will certainly try this route (but from scratch)! – Elliot Mar 20 '10 at 12:35
6

Have a look at FasterCSV.

csv_string = FasterCSV.generate do |csv|

  cols = ["column one", "column two", "column three"]

  csv << cols

  @entries.each do |entry|                
    csv << [entry.column_one, entry.column_two, entry.column_three ]
  end

  filename = "data-#{Time.now.to_date.to_s}.csv"    

end

send_data(csv_string, :type => 'text/csv; charset=utf-8; header=present', :filename => filename)  
Toby Hede
  • 36,755
  • 28
  • 133
  • 162
4

This is terrible, but the CSV library (in 1.9, == FasterCSV) won't play nice with meta_where, so I did it this way:

@customers.collect {|c| lines.push ["#{c.lastname}","#{c.firstname}","#{c.id}","#{c.type}"}
lines = lines.collect {|line| line.join(',')}
csv_string = lines.join("\n")  
respond_to do |format|
  format.html
  format.csv { send_data(csv_string, :filename => "#{@plan.name.camelize}.csv", :type => "text/csv") }
end

It's ugly, but effective.

Jason Lewis
  • 1,314
  • 8
  • 13
  • 1
    I like this answer, simple and effective if you're just generating a very basic CSV (although I moved the logic to the model instead of having it in the controller). – Christian Mar 08 '13 at 13:48
  • Yeah, this was a quick and dirty hack for me, but if you're going to use it "for real" the model is a much better place for it. – Jason Lewis Mar 11 '13 at 19:33
  • Just on a side note, if you think semantically - a model is terrible place for this. A customer shouldn't have knowledge of how to render itself. It's just not logical, besides fat models are too prominent in rails. Why not make a PORO which accepts the model and allows this method instead? – Jono Feb 29 '16 at 23:43
0

Take a look at CSV Shaper.

https://github.com/paulspringett/csv_shaper

It has a nice DSL and works really well with Rails models.

paul
  • 307
  • 2
  • 4