简体   繁体   English

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

[英]In Rails, how can I submit a form and request a csv formatted page?

I have a few parts of the solution, but I'm having trouble bringing them together.我有解决方案的几个部分,但我无法将它们组合在一起。

I have a page with two text fields (in a form_tag) in which I'll enter a datetime string with the start and end dates of the records I want to download in CSV form.我有一个包含两个文本字段(在 form_tag 中)的页面,我将在其中输入一个日期时间字符串,其中包含我想以 CSV 格式下载的记录的开始日期和结束日期。

I can use a submit_tag and get the two dates, but then I don't know how to get the view to tell the controller that I want a CSV, so .我可以使用 submit_tag 并获取两个日期,但是我不知道如何让视图告诉控制器我想要一个 CSV,所以 . I can use a link_to, but then the params get left behind.我可以使用link_to,但是参数会被抛在后面。

The view and controller look a little wonky as I'm trying to figure out how this stuff should work together.当我试图弄清楚这些东西应该如何协同工作时,视图和控制器看起来有点不稳定。 I won't ship both a link and a button, for example.例如,我不会同时提供链接和按钮。 I also removed/changed things as needed for brevity/privacy.为了简洁/隐私,我还根据需要删除/更改了内容。

show.html.erb: 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 %>

report_controller.rb: 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

download.csv.erb:下载.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 -%>

Because you want to download a CSV, the request should be a GET request.因为要下载 CSV,所以请求应该是GET请求。

Your link should look like <a download href="/reports/1.csv?from=2017-01-01&to=2017-12-31">Download</a> .您的链接应类似于<a download href="/reports/1.csv?from=2017-01-01&to=2017-12-31">Download</a> I suggest you build this url on browsers (which means using javascript, not rails).我建议你在浏览器上构建这个 url(这意味着使用 javascript,而不是 Rails)。

Your rails application must understand the extension .csv .您的 rails 应用程序必须理解扩展名.csv This can be configured in config/initializers/mime_types.rb这可以在config/initializers/mime_types.rbconfig/initializers/mime_types.rb

Mime::Type.register "text/csv", :csv

Now you can send CSV to the browser现在您可以将 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

Links are self-contained;链接是独立的; submit buttons (typically) submit forms (with all their non- disabled , name -having values) to the action URL of the form (unless you're doing submission through JavaScript, in which case you can do whatever you want, obviously).提交按钮(通常)将表单(带有所有非disabled 、具有name值)提交到表单的操作 URL(除非您通过 JavaScript 提交,在这种情况下,您可以做任何您想做的事情,显然)。

Thus, you don't specify the URL on submit_tag , you specify it on form_tag :因此,您没有在submit_tag上指定 URL,而是在form_tag上指定它:

Starts a form tag that points the action to a url configured with url_for_options just like ActionController::Base#url_for .启动一个表单标签,将动作指向一个用url_for_options配置的 url,就像ActionController::Base#url_for

As one of the answers mentioned, you need to specify the format on the form_tag .作为提到的答案之一,您需要在form_tag上指定format It can get tricky as the format needs to be set in the url_options , not in the other form_tag options.它可能会变得棘手,因为需要在url_options设置format ,而不是在其他form_tag选项中。 For example:例如:

<%= form_tag({controller: 'my_controller', method: 'my_method', format: 'csv'}, method: "get") do %>
  ...fields
  <%= submit_tag 'Submit' %>
<% end %>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM