IT박스

레일에서 레코드를 csv 파일로 반환하는 방법

itboxs 2021. 1. 5. 07:52
반응형

레일에서 레코드를 csv 파일로 반환하는 방법


"Entries"라는 간단한 데이터베이스 테이블이 있습니다.

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_csvFasterCSV에서 가져옴)

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

나는 FasterCSV를 처음으로 지적하기 위해 @Brian의 대답을 수락했습니다 (그리고 투표했습니다!). 그런 다음 젬을 찾기 위해 검색했을 때이 위키 페이지 에서 상당히 완벽한 예제를 찾았습니다 . 그것들을 모아서 다음 코드를 정했습니다.

그런데 gem을 설치하는 명령은 다음과 같습니다. sudo gem install 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를 사용하지 않고이를 수행하는 또 다른 방법 :

config / initializers / dependencies.rb와 같은 이니셜 라이저 파일에 루비의 csv 라이브러리가 필요합니다.

require "csv"

일부 배경으로 다음 코드는 검색 리소스를 만드는 Ryan Bate의 고급 검색 양식기반으로 합니다. 필자의 경우 검색 리소스의 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

The show.csv.erb file looks like the following:

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

On the html version of the report page I have a link to export the report that the user is viewing. The following is the link_to that returns the csv version of the report:

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

Take a look into the FasterCSV gem.

If all you need is excel support, you might also look into generating a xls directly. (See Spreadsheet::Excel)

gem install fastercsv
gem install spreadsheet-excel

I find these options good for opening the csv file in Windows Excel:

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

As for the ActiveRecord part, something like this would do:

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

You need to set the Content-Type header in your response, then send the data. Content_Type: application/vnd.ms-excel should do the trick.

You may also want to set the Content-Disposition header so that it looks like an Excel document, and the browser picks a reasonable default file name; that's something like Content-Disposition: attachment; filename="#{suggested_name}.xls"

I suggest using the fastercsv ruby gem to generate your CSV, but there's also a builtin csv. The fastercsv sample code (from the gem's documentation) looks like this:

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

The following approached worked well for my case and causes the browser to open the appropriate application for the CSV type after downloading.

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

try a nice gem to generate CSV from Rails https://github.com/crafterm/comma


Take a look at the CSV Shaper gem.

https://github.com/paulspringett/csv_shaper

It has a nice DSL and works really well with Rails models. It also handles the response headers and allows filename customisation.


If you're simply wanting to get the csv database yourself from the console you can do so in a few lines

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(""))}

ReferenceURL : https://stackoverflow.com/questions/94502/in-rails-how-to-return-records-as-a-csv-file

반응형