Я боролся с точно такой же проблемой. Я мог бы найти решение.
Я нашел некоторые подсказки, читая исходный код Renderers.add для: json и: xml (ссылка на код 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
Это может быть что угодно, просто обязательно верните хеш с парами ключ / значение. Хэш работает лучше, чем массив, так как с ключами вы можете добавить строку заголовка к выходу CSV позже. Идея as_csv
основана на методе Rails as_json
, который возвращает объект Ruby, который используется to_json
для генерации фактического вывода в формате 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 в код вашего контроллера:
class ModelnamesController < ApplicationController
respond_to :html, :json, :csv
def index
@modelnames = Modelname.all
respond_with(@modelnames)
end
# ...
end
Код инициализатора в значительной степени основан на поведении: json и: xml из исходного кода Rails (см. Ссылку выше).
В настоящее время хэш options
, переданный в блок, не передается в вызов to_csv
, так как CSV довольно требователен к тому, какие опции он позволяет отправлять. Rails добавляет некоторые опции по умолчанию (например, template и некоторые другие), что выдает ошибку при передаче их в to_csv
. Конечно, вы можете изменить поведение рендеринга CSV по умолчанию, добавив свои предпочтительные параметры CSV в инициализатор.
Надеюсь, это поможет!