在 Rails 中,如何提交表单并请求 csv 格式的页面?

Rod*_*ick 7 ruby csv ruby-on-rails ruby-on-rails-5

我有解决方案的几个部分,但我无法将它们组合在一起。

我有一个包含两个文本字段(在 form_tag 中)的页面,我将在其中输入一个日期时间字符串,其中包含我想以 CSV 格式下载的记录的开始日期和结束日期。

我可以使用 submit_tag 并获取两个日期,但是我不知道如何让视图告诉控制器我想要一个 CSV,所以 . 我可以使用link_to,但是参数会被抛在后面。

当我试图弄清楚这些东西应该如何协同工作时,视图和控制器看起来有点不稳定。例如,我不会同时提供链接和按钮。为了简洁/隐私,我还根据需要删除/更改了内容。

show.html.erb:

<%= form_tag do %>    
  <br/><br/>
  <%= label_tag :start_date, "From:" %>
  <%= text_field_tag :start_date, nil, size: 40 %>
  <%= label_tag :end_date, "To:" %>
  <%= text_field_tag :end_date, nil, size: 40 %>
  <br/>

  <%= link_to "Export Report", report_path(:csv) %>

  <%= submit_tag("Generate .CSV", format: :csv) %><br/><br/>
<% end %>
Run Code Online (Sandbox Code Playgroud)

report_controller.rb:

require 'csv'

class ReportController < ApplicationController
  def show
    if params[:start_date]          
      @data = get_data(params[:start_date], params[:end_date])
      respond_to do |format|
        format.html
        format.csv
      end
    end
  end

  def build_csv_enumerator(header, data)
    Enumerator.new do |y|
      CSVBuilder.new(header, data, y)
    end
  end

  def download
    if params[:start_date]
      @data = get_data(params[:start_date], params[:end_date])
      respond_to do |format|
        format.html
        format.csv
      end
    end
    redirect_to action: "show"
  end

  private def csv_filename
    "report-#{Time.now.to_s}.csv"
  end
end

class CSVBuilder

  attr_accessor :output, :header, :data

  def initialize(header, data, output = "")
    @output = output
    @header = header
    @data = data
  end

  def build
    output << CSV.generate_line(header)
    data.each do |row|
      output << CSV.generate_line(row)
    end
    output
  end
end
Run Code Online (Sandbox Code Playgroud)

下载.csv.erb:

<%- headers = ["name", "email", "created_at"] -%>
<%= CSV.generate_line(headers) %>
<%- @data.each do |line| -%>
  <%- row = line.values_at(*headers) -%>
  <%= CSV.generate_line(row) %>
<%- end -%>
Run Code Online (Sandbox Code Playgroud)

Aet*_*rus 4

因为您要下载 CSV,所以请求应该是GET请求。

您的链接应该如下所示<a download href="/reports/1.csv?from=2017-01-01&to=2017-12-31">Download</a>。我建议你在浏览器上构建这个url(这意味着使用javascript,而不是rails)。

您的 Rails 应用程序必须理解扩展.csv。这可以配置在config/initializers/mime_types.rb

Mime::Type.register "text/csv", :csv
Run Code Online (Sandbox Code Playgroud)

现在您可以将 CSV 发送到浏览器

class ReportsController < ApplicationController
  def show
    respond_to do |format|
      # ...
      format.csv do
        @csv = ...
        send_data @csv.to_s  # what you send must be a string
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)