в rails, как возвращать записи в виде csv-файла

StackOverflow https://stackoverflow.com/questions/94502

  •  01-07-2019
  •  | 
  •  

Вопрос

У меня есть простая таблица базы данных под названием "Записи".:

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

Как мне написать обработчик, который вернет содержимое таблицы записей в виде CSV-файла (в идеале таким образом, чтобы он автоматически открывался в Excel)?

class EntriesController < ApplicationController

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

    # ??? NOW WHAT ????

  end

end
Это было полезно?

Решение

Существует плагин под названием FasterCSV, который прекрасно справляется с этим.

Другие советы

FasterCSV это определенно правильный путь, но если вы хотите обслуживать его непосредственно из своего приложения Rails, вам также потребуется настроить некоторые заголовки ответов.

У меня есть метод для настройки имени файла и необходимых заголовков:

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

Использование этого позволяет легко установить что-то подобное в моем контроллере:

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

И иметь вид, который выглядит примерно так:(generate_csv это от 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 %>

Я принял (и проголосовал за!) Ответ @Brian за то, что он первым указал мне на FasterCSV.Затем, когда я погуглил, чтобы найти драгоценный камень, я также нашел довольно полный пример по адресу эта вики-страница.Собрав их вместе, я остановился на следующем коде.

Кстати, команда для установки драгоценного камня такова:sudo gem устанавливает fastercsv (все в нижнем регистре)

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

Другой способ сделать это без использования FasterCSV:

Требуется CSV-библиотека ruby в файле инициализатора, таком как config/initializers/dependencies.rb

require "csv"

В качестве некоторой предпосылки следующий код основан на Расширенная форма поиска Райана Бейта это создает поисковый ресурс.В моем случае метод show поискового ресурса вернет результаты ранее сохраненного поиска.Он также реагирует на csv и использует шаблон представления для форматирования желаемых выходных данных.

  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

Файл show.csv.erb выглядит следующим образом:

<%- 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 -%>

На html-версии страницы отчета у меня есть ссылка для экспорта отчета, который просматривает пользователь.Ниже приведена ссылка_to, которая возвращает csv-версию отчета:

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

Взгляните на FasterCSV драгоценный камень.

Если все, что вам нужно, - это поддержка Excel, вы также можете рассмотреть возможность создания xls напрямую.(Смотрите таблицу::Excel)

gem install fastercsv
gem install spreadsheet-excel

Я нахожу эти параметры хорошими для открытия CSV-файла в Windows Excel:

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

Что касается части ActiveRecord, то для этого подойдет что-то вроде этого:

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

Вам нужно установить заголовок Content-Type в своем ответе, а затем отправить данные.Content_Type (Тип содержимого):приложение / vnd.ms-excel должно сделать свое дело.

Вы также можете захотеть настроить заголовок Content-Disposition таким образом, чтобы он выглядел как документ Excel, а браузер выбирал приемлемое имя файла по умолчанию;это что-то вроде Содержания-Диспозиции:привязанность;filename="#{предлагаемое имя_имя}.xls"

Я предлагаю использовать ruby gem fastercsv для генерации вашего CSV-файла, но есть также встроенный CSV-файл.Пример кода fastercsv (из документации gem) выглядит следующим образом:

csv_string = FasterCSV.generate do |csv|
  csv << ["row", "of", "CSV", "data"]
  csv << ["another", "row"]
# ...
end

Следующий подход хорошо сработал в моем случае и заставляет браузер открывать соответствующее приложение для типа CSV после загрузки.

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

попробуйте хороший gem для генерации CSV из Rails https://github.com/crafterm/comma

Взгляните на драгоценный камень CSV Shaper.

https://github.com/paulspringett/csv_shaper

Он имеет хороший DSL и действительно хорошо работает с моделями Rails.Он также обрабатывает заголовки ответов и позволяет настраивать имя файла.

Если вы просто хотите получить базу данных csv самостоятельно с консоли, вы можете сделать это в нескольких строках

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(""))}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top