Recently I had learned how to write a csv file in my rails app using the fasterCSV gem. In Rails3, CSV is now part of the standard library, so things are a little different. I also did a few trickier things this time around, so I’m updating my notes.

In Gemfile, add:

require 'csv'

As before, create config/download_csv.yml

development:
    all: /Users/me/Desktop/all.csv
    current: /Users/me/Desktop/current.csv
    previous: /Users/me/Desktop/previous.csv
    
production:
    all: /tmp/all.csv
    current: /tmp/current.csv
    previous: /tmp/previous.csv

In the model, add a method to make the csv file.

def self.download_charges(project_id, timeframe)
    csv_settings = YAML.load_file("#{Rails.root.to_s}/config/
download_csv.yml")[Rails.env]
    filename = csv_settings[timeframe]
    if (timeframe == 'current')
      @entries = Entry.billable.current_month.where(:project_id => 
project_id).newest_first
    end
    if (timeframe == 'previous')
      @entries = Entry.billable.previous_month.where(:project_id => 
project_id).newest_first
    end
    if (timeframe == 'all')
      @entries = Entry.billable.where(:project_id => 
project_id).newest_first
    end
    CSV.open("#{filename}",'w') do |csv|
      csv << ["Report Generated On #{Time.now.to_s(:fulldate)}"]
      csv << ["Account",
"#{@entries.first.project.account}",
"#{@entries.first.project.subaccount}"]
      csv << ["#{@entries.first.project.name}"]
      csv << ["Total Charges", "#{@entries.sum(:cost)}"]
      csv << [""]
      csv << ['Date','Staff Member', 'Hours', 'Charge', 'Note']
      @entries.each do |entry|
        csv << ["#{entry.start_date.to_s(:fulldate)}",
"#{entry.user.fullname}","#{entry.hours}", 
"#{entry.cost}", "#{entry.note}"]
      end
    end
  end

In the controller, make a method to call.

def download_charges
    csv_settings = YAML.load_file("#{Rails.root.to_s}/config/
download_csv.yml")[Rails.env]
    filename = csv_settings["#{params[:timeframe]}"]
    Entry.download_charges(params[:project_id],
 params[:timeframe])
    send_file "#{filename}", :type => 'text/csv'
  end

and add it to the filter_resource access line.

filter_resource_access :additional_collection => 
[[:download_charges, :index], :index]

To my routes file, add:

resources :entries do
    collection do
      get 'download_charges', :as => :download_charges
    end
  end

Lastly, in my view, add the required links. Here they’re a little trickier because I want the same method to work for different time frames.

<% unless params[:project_id].nil? %>
	


  
    <%= link_to 'Download All Charges', :controller => :entries, 
    :action => :download_charges, :project_id => @entries.first.project_id, 
    timeframe => 'all' %>
  
  			
  
  
    <%= link_to 'Download Current Month Charges', 
    :controller => :entries, :action => :download_charges,
     :project_id => @entries.first.project_id, 
    :timeframe => 'current'%>
  
  			
  
  
    <%= link_to 'Download Previous Month Charges',
     :controller => :entries, :action => :download_charges, 
    :project_id => @entries.first.project_id, :timeframe => 
    'previous'%>
  
  		

	<% end %>