我正在 Ruby on Rails 存盤庫中匯出到 csv 檔案功能,我幾乎完成了。但是,當我按下“全部匯出”按鈕時,undefined method `export' for nil:NilClass出現錯誤。日志顯示format.csv { send_data @foos.export, filename: "foos-#{Date.today}.csv" }出錯了。請問我錯過了什么?
這是模型
class Foo < ApplicationRecord
has_many :bars
def export
[id, name, foos.map(&:name).join(' ')]
end
end
這是控制器的一部分
def index
@foos = Foo.all
end
def export
all = Foo.all
attributes = %w{name}
CSV.generate(headers: true) do |csv|
csv << attributes
all.each do |foo|
csv << attributes.map{ |attr| foo.send(attr) }
end
respond_to do |format|
format.csv { send_data @foos.export, filename: "foos-#{Date.today}.csv" }
end
end
end
def name
"#{foo_id} #{name}"
end
這是視圖
<a href="/export.csv"><button class="btn btn-success">export all</button></a>
這是路線
Rails.application.routes.draw do
resources :foos
get :export, controller: :foos
root "foos#index"
end
這是 Rake (lib/tasks/export.rb)
namespace :export do
task foo: :environment do
file_name = 'exported_foo.csv'
csv_data = Foo.to_csv
File.write(file_name, csv_data)
end
end
uj5u.com熱心網友回復:
首先創建一個接收記錄集合并回傳 CSV 的服務物件,以便您可以單獨測驗 CSV 生成:
# app/services/foo_export_service.rb
# Just a Plain Old Ruby Object that converts a collection of foos into CSV
class FooExportService
# The initializer gives us a good place to setup our service
# @param [Enumerable] foo - an array or collection of records
def initialize(foos)
@headers = %w{name} # the attributes you want to use
@foos = foos
end
# performs the actual work
# @return [String]
def perform
CSV.generate do |csv|
@foos.each do |foo|
csv << foo.serializable_hash.slice(@headers).values
end
end
end
# A convenient factory method which makes stubbing the
# service easier
# @param [Enumerable] foos - an array or collection of records
# @return [String]
def self.perform(foos)
new(foos).perform
end
end
# example usage
FooExportService.perform(Foo.all)
并非 Rails 應用程式中的所有內容都需要嵌入模型、視圖或控制器中。他們已經有足夠的責任。如果您確實需要它,這也可以讓您在您的 rake 任務中重用代碼。
這只是對集合進行迭代,并使用 Rails 內置的序列化功能將模型實體轉換為可以序列化為 CSV 的哈希值。它還使用了Hash#slice對哈希鍵進行重新排序的事實。
在您的控制器中,您只需使用服務物件:
class FoosController
def export
@foos = Foo.all
respond_to do |format|
format.csv do
send_data FooExportService.perform(@foos),
filename: "foos-#{Date.today}.csv"
end
end
end
end
首先,您甚至真的不需要單獨的export操作。只需使用 MimeResponds 將 CSV 作為可用的回應格式添加到索引:
class FoosController
def index
# GET /foos
# GET /foos.csv
@foos = Foo.all
respond_to do |format|
format.html
format.csv do
send_data FooExportService.perform(@foos),
filename: "foos-#{Date.today}.csv"
end
end
end
end
<%= link_to("Export as CSV", foos_path(format: :csv)) %>
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/436020.html
標籤:轨道上的红宝石
