55 votes

dans les rails, comment retourner des enregistrements dans un fichier csv

J'ai une simple table de base de données appelée "Entrées":

 class CreateEntries < ActiveRecord::Migration
  def self.up
    create_table :entries do |t|
      t.string :firstName
      t.string :lastName
      #etc.
      t.timestamps
    end
  end

  def self.down
    drop_table :entries
  end
end
 

Comment écrire un gestionnaire qui renvoie le contenu du tableau Entries sous forme de fichier CSV (idéalement de manière à ce qu'il s'ouvre automatiquement dans Excel)?

 class EntriesController < ApplicationController

  def getcsv
    @entries = Entry.find( :all )

    # ??? NOW WHAT ????

  end

end
 

89voto

Clinton R. Nixon Points 4283

FasterCSV est certainement le chemin à parcourir, mais si vous voulez les servir directement à partir de votre application Rails, vous aurez envie de mettre en place certains en-têtes de réponse, trop.

Je garde une méthode à mettre en place autour du nom de fichier et nécessaires en-têtes:

def render_csv(filename = nil)
  filename ||= params[:action]
  filename += '.csv'

  if request.env['HTTP_USER_AGENT'] =~ /msie/i
    headers['Pragma'] = 'public'
    headers["Content-type"] = "text/plain" 
    headers['Cache-Control'] = 'no-cache, must-revalidate, post-check=0, pre-check=0'
    headers['Content-Disposition'] = "attachment; filename=\"#{filename}\"" 
    headers['Expires'] = "0" 
  else
    headers["Content-Type"] ||= 'text/csv'
    headers["Content-Disposition"] = "attachment; filename=\"#{filename}\"" 
  end

  render :layout => false
end

L'aide qu'il est facile d'avoir quelque chose comme ceci dans mon controller:

respond_to do |wants|
  wants.csv do
    render_csv("users-#{Time.now.strftime("%Y%m%d")}")
  end
end

Et avoir un affichage qui ressemble à ceci: (generate_csv est de FasterCSV)

UserID,Email,Password,ActivationURL,Messages
<%= generate_csv do |csv|
  @users.each do |user|
    csv << [ user[:id], user[:email], user[:password], user[:url], user[:message] ]
  end
end %>

26voto

Eric Points 5994

J'ai accepté (et voté!) @ La réponse de Brian, pour m'avoir d'abord dirigé vers FasterCSV. Ensuite, lorsque j'ai cherché sur Google pour trouver la gemme, j'ai également trouvé un exemple assez complet sur cette page wiki . En les assemblant, je me suis installé sur le code suivant.

A propos, la commande pour installer la gemme est la suivante: sudo gem install plus csv (en minuscules)

 require 'fastercsv'

class EntriesController < ApplicationController

  def getcsv
      entries = Entry.find(:all)
      csv_string = FasterCSV.generate do |csv| 
            csv << ["first","last"]
            entries.each do |e|
              csv << [e.firstName,e.lastName]
            end
          end
          send_data csv_string, :type => "text/plain", 
           :filename=>"entries.csv",
           :disposition => 'attachment'

  end


end
 

25voto

rwc9u Points 532

Une autre façon de le faire sans l'aide de FasterCSV:

Besoin de ruby csv bibliothèque dans un initializer comme config/initializers/dépendances.rb

require "csv"

Comme certains l'arrière-plan, le code suivant est basé hors de Ryan Bate du Formulaire de Recherche Avancée qui crée une ressource de recherche. Dans mon cas, la méthode show de la ressource de recherche renvoie les résultats de recherche enregistrés. Il répond également au format csv, et utilise un gabarit de vue pour le format de sortie souhaité.

  def show
    @advertiser_search = AdvertiserSearch.find(params[:id])
    @advertisers = @advertiser_search.search(params[:page])
    respond_to do |format|
      format.html # show.html.erb
      format.csv  # show.csv.erb
    end
  end

Le spectacle.csv.erb fichier se présente comme suit:

<%- headers = ["Id", "Name", "Account Number", "Publisher", "Product Name", "Status"] -%>
<%= CSV.generate_line headers %>
<%- @advertiser_search.advertisers.each do |advertiser| -%>
<%- advertiser.subscriptions.each do |subscription| -%>
<%- row = [ advertiser.id,
            advertiser.name,
            advertiser.external_id,
            advertiser.publisher.name,
            publisher_product_name(subscription),
            subscription.state ] -%>
<%=   CSV.generate_line row %>
<%- end -%>
<%- end -%>

Sur la version html de la page de rapport, j'ai un lien pour exporter le rapport que l'utilisateur consulte. Ce qui suit est la link_to qui renvoie le csv version du rapport:

<%= link_to "Export Report", formatted_advertiser_search_path(@advertiser_search, :csv) %>

23voto

Brian Points 3889

Il existe un plugin appelé FasterCSV qui gère cela à merveille.

7voto

kch Points 25855

Jetez un coup d'œil à la gemme FasterCSV .

Si tout ce dont vous avez besoin est un support Excel, vous pouvez également envisager de générer directement un xls. (Voir Tableur :: Excel)

 gem install fastercsv
gem install spreadsheet-excel
 

Je trouve ces options bonnes pour ouvrir le fichier csv dans Windows Excel:

 FasterCSV.generate(:col_sep => ";", :row_sep => "\r\n") { |csv| ... }
 

En ce qui concerne la partie ActiveRecord, quelque chose comme ceci ferait:

 CSV_FIELDS = %w[ title created_at etc ]
FasterCSV.generate do |csv|
  Entry.all.map { |r| CSV_FIELDS.map { |m| r.send m }  }.each { |row| csv << row }
end
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X