in Schienen, wie die Datensätze als CSV-Datei zurück
-
01-07-2019 - |
Frage
Ich habe eine einfache Datenbanktabelle namens „Einträge“:
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
Wie schreibe ich einen Handler, der den Inhalt der Einträge Tabelle als CSV-Datei zurück (idealerweise in einer Weise, dass es öffnet sich automatisch in Excel)?
class EntriesController < ApplicationController
def getcsv
@entries = Entry.find( :all )
# ??? NOW WHAT ????
end
end
Lösung
Es ist ein Plugin FasterCSV genannt, die diese wunderbar behandelt.
Andere Tipps
FasterCSV ist definitiv der Weg zu gehen, aber wenn Sie wollen, dass es direkt dienen von Ihrer Rails-Anwendung, sollten Sie einige Response-Header auch einzurichten.
Ich halte eine Methode, um die Dateinamen und die notwendigen Header einzurichten:
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
Mit dass macht es einfach, so etwas in meinem Controller haben:
respond_to do |wants|
wants.csv do
render_csv("users-#{Time.now.strftime("%Y%m%d")}")
end
end
Und einen Blick haben, die wie folgt aussieht: (generate_csv
ist aus 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 %>
akzeptiert I (und stimmte up!) @ Brian Antwort, für mich zum ersten Mal auf FasterCSV zeigen. Dann, wenn ich den Edelstein finden googeln fand ich auch ein ziemlich vollständiges Beispiel unter dieser Wiki-Seite . sie zusammen setzen, ließ ich mich auf den folgenden Code.
By the way, der Befehl den Edelstein zu installieren ist: sudo gem install fastercsv (Alles in Kleinbuchstaben)
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
Eine andere Möglichkeit, dies zu tun, ohne FasterCSV mit:
Erfordern Rubys csv-Bibliothek in einer Initialisierer-Datei wie config / initializers / dependencies.rb
require "csv"
Wie einige Hintergrundinformationen wird der folgende Code basiert weg von Ryan Bate Advanced Search Form , dass eine Ressourcensuche erstellt . In meinem Fall wird die Show-Methode der Suche Ressource zurückgeben, die Ergebnisse einer zuvor gespeicherten Suche. Es reagiert auch auf CSV, und verwendet eine Ansichtsvorlage die gewünschte Ausgabe zu formatieren.
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
Die show.csv.erb Datei sieht wie folgt aus:
<%- 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 -%>
Auf der HTML-Version der Berichts Seite ich einen Link, um den Bericht zu exportieren, dass der Benutzer gerade überprüft. Im Folgenden ist der link_to, die die CSV-Version des Berichts zurückgibt:
<%= link_to "Export Report", formatted_advertiser_search_path(@advertiser_search, :csv) %>
Werfen Sie einen Blick in die FasterCSV gem.
Wenn alles, was Sie Unterstützung auszeichnen müssen, können Sie auch in aussehen eine xls direkt zu erzeugen. (Siehe Tabellenkalkulations :: Excel)
gem install fastercsv
gem install spreadsheet-excel
Ich finde diese Optionen gut für die CSV-Datei in Windows Excel öffnen:
FasterCSV.generate(:col_sep => ";", :row_sep => "\r\n") { |csv| ... }
Wie für den Active Teil, so etwas wie dies tun würde:
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
Sie müssen die Content-Type-Header in Ihrer Antwort setzen, dann die Daten senden. Content_Type. Application / vnd.ms-excel sollte es tun
Sie können auch die Content-Disposition-Header zu setzen, so dass es wie ein Excel-Dokument aussieht, und der Browser nimmt einen angemessenen Standard-Dateinamen; das ist so etwas wie Content-Disposition: attachment; filename = "# {} suggested_name .xls"
Ich schlage vor, die fastercsv Ruby Gem mit Ihrem CSV zu erzeugen, aber es gibt auch einen eingebauten csv. Der fastercsv Beispielcode (aus der Dokumentation des gem) sieht wie folgt aus:
csv_string = FasterCSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
Die folgenden genähert haben gut funktioniert für meinen Fall und bewirkt, dass der Browser die entsprechende Anwendung für den CSV-Typen zu öffnen nach dem Download.
def index
respond_to do |format|
format.csv { return index_csv }
end
end
def index_csv
send_data(
method_that_returns_csv_data(...),
:type => 'text/csv',
:filename => 'export.csv',
:disposition => 'attachment'
)
end
versuchen, ein schönes Juwel CSV zu erzeugen, aus Schienen https://github.com/crafterm/comma
Werfen Sie einen Blick auf die CSV-Shaper gem.
https://github.com/paulspringett/csv_shaper
Es hat eine schöne DSL und funktioniert wirklich gut mit Rails-Modellen. Es behandelt auch die Response-Header und erlaubt Dateinamen individuell gestaltet werden.
Wenn Sie einfach nur wollen, sind die CSV-Datenbank, um sich selbst von der Konsole können Sie dies in ein paar Zeilen
tags = [Model.column_names]
rows = tags + Model.all.map(&:attributes).map(&:to_a).map { |m| m.inject([]) { |data, pair| data << pair.last } }
File.open("ss.csv", "w") {|f| f.write(rows.inject([]) { |csv, row| csv << CSV.generate_line(row) }.join(""))}