Rails: Exportando dados para planilhas

Permitir que administradores de sistemas de dados exportem dados para planilhas permite que eles os manipulem, tornem-nos bonitos, gerem relatórios e os repassem à sua própria maneira, sem que o desenvolvedor tenha que usar toda essa funcionalidade para o aplicativo. Pronto para usar Rails pode fazer dump em XML e JSON, mas isso não é tão amigável. O despejo em CSV está mais perto, mas é muito fácil ter problemas com o encerramento de campo e cotação de valor, além disso, você não tem chance de estilizar a saída. Um pouco pode ir longe.

Digite a gema axlsx . Ele permite que você crie planilhas em Rails de forma rápida e fácil, exportando para o formato .xlsx que pode ser lido pelo Excel, OpenOffice e Google Docs. Cobertura sólida. Quando você combina isso com a gema axlsx-rails, você pode gerar planilhas tão facilmente quanto gera HTML com um modelo ERB.

No momento em que este livro foi escrito, você deseja a versão 2.1.0.pre do axlsx, então adicione-o ao seu Gemfile:

# Export data to spreadsheets
gem
'axlsx', '2.1.0.pre'
gem
'axlsx_rails'

Em seguida, crie um arquivo de visualização exatamente como faria para HTML. Aqui está um index.xlsx.axlsxmodelo de visualização genérico para descartar os atributos de um registro:

# app/views/base_controller/index.xlsx.axlsx

# Hook into the xlsx package provided by the axlsx-rails gem
wb
= xlsx_package.workbook

# Create a style we can use for record headers
styles
= xlsx_package.workbook.styles
header_style
= styles.add_style bg_color: "00",
fg_color
: "FF",
bold
: true,
alignment
: { horizontal: :center }

# Get a list of associations. We want to export the association value rather than ID
# e.x. Get Post#user rather than Post#user_id
assocs
= resource_class.reflect_on_all_associations(:belongs_to).map{|a| [a.foreign_key.to_sym, a.name]}.to_h

# Create a worksheet. Name it after the resource we're exporting
wb
.add_worksheet(name: @resource.model_name.plural.titleize) do |sheet|
# Get list of attributes to export
attrs
= policy(@resources.first).permitted_export_attributes

# Add a header row using the header style we defined
sheet
.add_row attrs.map { |n| @resources.first.class.human_attribute_name(n) }, style: header_style

# Add each row to our sheet
@resources.each do |row|
sheet
.add_row attrs.map { |a| row.send(assocs[a] || a) }
end
end

Uma coisa digna de nota é a policy(@resource_value.first).permitted_export_attributeslinha. Isso nos permite definir um método nas políticas do Pundit que retorna uma lista de campos permitidos para exportação. Em application_policy.rbum pode adicionar algo como:

# app/policies/application_policy.rb

def permitted_export_attributes
# don't export friendly_id slug, or legacy data mapping fields.
record
.class.attribute_names.map(&:to_sym) - %i(slug legacy_id data_source)
end

Uma última coisa que eu achei útil foi para definir o Content-Dispositionque attachmente definir meu próprio nome do arquivo de exportação. Isso dispara o download do arquivo (em vez de o usuário clicar com o botão direito do mouse, salvar como) e nos permite definir um nome de arquivo adequado.

# app/controllers/people_controller.rb

def index
respond_to
do |format|
format
.html
format
.xlsx { set_attachment_name "sites #{Time.now.utc.strftime('%Y%M%d%H%M%S')}.xlsx" }
end
end
# app/controllers/base_controller.rb

protected

def set_attachment_name(name)
escaped
= URI.encode(name)
response
.headers['Content-Disposition'] = "attachment; filename*=UTF-8''#{escaped}"
end

E aqui vamos nós! sites 20172419062423.xlsx

Captura de tela 19/02/2017 em 13.25.05.png