ruby-on-rails - rails import csv
en rieles, cómo devolver registros como un archivo csv (10)
Acepté (¡y voté!) La respuesta de @ Brian, por primera vez me indicó FasterCSV. Luego, cuando busqué en Google para encontrar la gema, también encontré un ejemplo bastante completo en esta página wiki . Poniéndolos juntos, me decidí por el siguiente código.
Por cierto, el comando para instalar la gema es: sudo gem install fastercsv (todo en minúsculas)
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
Tengo una tabla de base de datos simple llamada "Entradas":
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
¿Cómo escribo un controlador que devolverá los contenidos de la tabla de entradas como un archivo CSV (idealmente de forma que se abra automáticamente en Excel)?
class EntriesController < ApplicationController
def getcsv
@entries = Entry.find( :all )
# ??? NOW WHAT ????
end
end
Debe configurar el encabezado Content-Type en su respuesta, luego envíe los datos. Content_Type: application / vnd.ms-excel debería hacer el truco.
Es posible que también desee configurar el encabezado Content-Disposition para que se vea como un documento de Excel, y el navegador elija un nombre de archivo predeterminado razonable; eso es algo como Content-Disposition: attachment; filename = "# {suggested_name} .xls"
Sugiero usar la gema ruby fastercsv para generar su CSV, pero también hay una csv incorporada. El código de ejemplo de fastercsv (de la documentación de la gema) se ve así:
csv_string = FasterCSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
Echa un vistazo a la gema CSV Shaper.
https://github.com/paulspringett/csv_shaper
Tiene un buen DSL y funciona muy bien con los modelos de Rails. También maneja los encabezados de respuesta y permite la personalización del nombre de archivo.
Echa un vistazo a la gema de FasterCSV .
Si todo lo que necesita es soporte de excel, también puede buscar generar un xls directamente. (Ver hoja de cálculo :: Excel)
gem install fastercsv
gem install spreadsheet-excel
Encuentro estas opciones buenas para abrir el archivo csv en Windows Excel:
FasterCSV.generate(:col_sep => ";", :row_sep => "/r/n") { |csv| ... }
En cuanto a la parte ActiveRecord, algo como esto sería:
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
El siguiente enfoque funcionó bien para mi caso y hace que el navegador abra la aplicación apropiada para el tipo CSV después de la descarga.
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
Hay un complemento llamado FasterCSV que maneja esto maravillosamente.
Otra forma de hacerlo sin usar FasterCSV:
Requerir la biblioteca csv de ruby en un archivo de inicializador como config / initializers / dependencies.rb
require "csv"
Como antecedentes, el siguiente código se basa en el formulario de búsqueda avanzada de Ryan Bate que crea un recurso de búsqueda. En mi caso, el método show del recurso de búsqueda devolverá los resultados de una búsqueda previamente guardada. También responde a csv y usa una plantilla de vista para formatear el resultado deseado.
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
El archivo show.csv.erb tiene el siguiente aspecto:
<%- 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 -%>
En la versión html de la página del informe, tengo un enlace para exportar el informe que el usuario está viendo. El siguiente es el link_to que devuelve la versión csv del informe:
<%= link_to "Export Report", formatted_advertiser_search_path(@advertiser_search, :csv) %>
Si simplemente desea obtener la base de datos csv desde la consola, puede hacerlo en unas pocas líneas
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(""))}
prueba una buena joya para generar CSV desde Rails https://github.com/crafterm/comma
FasterCSV es definitivamente el camino a seguir, pero si desea servirlo directamente desde su aplicación Rails, también querrá configurar algunos encabezados de respuesta.
Guardo un método para configurar el nombre de archivo y los encabezados necesarios:
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
Usar eso hace que sea fácil tener algo como esto en mi controlador:
respond_to do |wants|
wants.csv do
render_csv("users-#{Time.now.strftime("%Y%m%d")}")
end
end
Y tenga una vista que se vea así: ( generate_csv
es 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 %>