我有一个具有 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/