ruby-on-rails - rails 3 : How to respond_with csv without having a template file?

标签 ruby-on-rails csv

我有一个具有 to_csv 的对象方法,我想将它传递给 respond_with从我的 Controller 渲染 csv。我的代码如下所示:

class Admin::ReportsController < AdminController

  respond_to :csv

  def trips
    respond_with TripReport.new
  end
end

TripReport 的实例有一个 to_csv 方法。

当我对该操作提出请求时,我收到以下错误:
ActionView::MissingTemplate (Missing template admin/reports/trips with {:formats=>[:csv], :handlers=>[:erb, :builder, :rjs, :rhtml, :rxml], :locale=>[:en, :en]} in view paths

所以看起来 Controller 正在寻找要渲染的模板文件。我怎样才能解决这个问题?

我宁愿 csv 格式以类似于 json 的方式响应,所以它调用 to_csv在对象上并只渲染输出,这可能吗?

最佳答案

我一直在努力解决完全相同的问题。我可能已经找到了解决方案。

我在阅读 :json 和 :xml 的 Renderers.add 源代码时发现了一些线索(链接适用于 Rails 3.0.10 代码,3.1 可能已经有一些更改):
https://github.com/rails/rails/blob/v3.0.10/actionpack/lib/action_controller/metal/renderers.rb

首先,添加一个简单的as_csv模型定义的方法:

class Modelname < ActiveRecord::Base
  # ...
  def as_csv
    attributes
  end
end

这可以是任何东西,只要确保返回带有键/值对的散列即可。 Hash 比 Array 更有效,因为您可以稍后将标题行添加到 CSV 输出中。 as_csv 的想法来自 Rails 的 as_json方法,返回 to_json 使用的 Ruby 对象生成实际的 JSON(文本)输出。

as_csv方法到位,将以下代码放入config/initializers的文件中在您的应用程序内部(例如,将其命名为 csv_renderer.rb):
require 'csv' # adds a .to_csv method to Array instances

class Array 
  alias old_to_csv to_csv #keep reference to original to_csv method

  def to_csv(options = Hash.new)
    # override only if first element actually has as_csv method
    return old_to_csv(options) unless self.first.respond_to? :as_csv
    # use keys from first row as header columns
    out = first.as_csv.keys.to_csv(options)
    self.each { |r| out << r.as_csv.values.to_csv(options) }
    out
  end
end

ActionController::Renderers.add :csv do |csv, options|
  csv = csv.respond_to?(:to_csv) ? csv.to_csv() : csv
  self.content_type ||= Mime::CSV
  self.response_body = csv
end

最后,将 CSV 支持添加到您的 Controller 代码中:
class ModelnamesController < ApplicationController
  respond_to :html, :json, :csv

  def index
    @modelnames = Modelname.all
    respond_with(@modelnames)
  end

  # ...

end

初始化代码主要基于 Rails 源代码中的 :json 和 :xml 行为(参见上面的链接)。

目前,options传递给 block 的哈希不会传递给 to_csv调用,因为 CSV 对允许发送哪些选项非常挑剔。 Rails 自己添加了一些默认选项(例如 :template 和其他一些选项),当您将它们传递给 to_csv 时会出现错误。 .当然,您可以通过将自己喜欢的 CSV 选项添加到初始化程序来更改默认的 CSV 呈现行为。

希望这可以帮助!

关于ruby-on-rails - rails 3 : How to respond_with csv without having a template file?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5182344/

相关文章:

java - 如何读取 Java 中包含多行单元格的 .csv 文件?

csv - 我如何知道从CSV文件读取的数据的总长度?

python - 遍历 for 循环并将检索到的数据保存在每个循环的唯一 csv 文件中 | Python

ruby-on-rails - 仅允许视频嵌入代码 (Rails)

ruby-on-rails - Flash 消息中的 active_scaffold 错误(没有将符号隐式转换为整数)

ruby-on-rails - 由随机词组成的 Heroku 应用程序 url

ruby-on-rails - Phusion Passenger 在使用 rvm 升级 Ruby 和 Rails 后抛出错误

python - 不懂Python的csv.reader对象

php - 将数据透视表模板从 csv(Excel) 移动到 MySQL

ruby-on-rails - Ruby 未定义方法 `[]' 为 nil :NilClass (NoMethodError) error