ruby-on-rails - Rails 将多个表导出到 csv
问题描述
嗨,我有一个简单的 rails 应用程序,它有两个模型 Equipment_Types 和 Tasks
每种设备类型都有许多任务。当我导出到 csv 文件时,我想导出设备类型的名称、任务名称和相关的时间表。基本上设备类型/show.html.erb 上显示的所有内容
<p id="notice"><%= notice %></p>
<div class="row">
<table class="table table-bordered">
<thead>
<tr>
<th class="align-middle" rowspan="2">Equipment</th>
<th class="align-middle" rowspan="2">Task</th>
<th class="text-center" colspan="4">Frequency</th>
</tr>
<tr>
<th class="text-center">M</th>
<th class="text-center">Q</th>
<th class="text-center">B</th>
<th class="text-center">A</th>
</tr>
</thead>
<tbody>
<tr>
<% if @taskcount > 3 %>
<td class="text-center bottomtotop" rowspan="0"><%= link_to @equipment_type.name, edit_equipment_type_path(@equipment_type) %></td>
<% else %>
<td class="text-center" rowspan="0"><%= link_to @equipment_type.name, edit_equipment_type_path(@equipment_type) %></td>
<% end %>
</tr>
<% @equip_tasks.each do |task| %>
<tr>
<td><%= link_to task.name, task %></td>
<td class="text-center"><%= if task.monthly then 'x' else ' ' end %></td>
<td class="text-center"><%= if task.quarterly then 'x' else ' ' end %></td>
<td class="text-center"><%= if task.sixmonthly then 'x' else ' ' end %></td>
<td class="text-center"><%= if task.annually then 'x' else ' ' end %></td>
</tr>
<% end %>
<div class="collapse" id="collapsenewline">
</div>
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm">
<%= link_to 'Add Task', new_task_path(@equipment_type), class: 'btn btn-dark' %>
</div>
<div class="col-sm">
<%= link_to 'Back', equipment_types_path, class: 'btn btn-dark' %>
</div>
<div class="col-sm">
<button class="btn btn-dark" type="button" data-toggle="collapse" data-target="#collapsedownload" aria-expanded="false" aria-controls="collapseExample">
Download
</button>
</div>
</div>
<div class="row">
<div class="col-sm">
</div>
<div class="col-sm">
</div>
<div class="col-sm">
<div class="collapse" id="collapsedownload">
<div class="card card-body">
<h3>Download File</h3>
<%= link_to "csv", equipment_types_path(format: "csv"), class: 'btn btn-dark' %>
<br>
<%= link_to "pdf", equipment_types_path(format: "pdf"), class: 'btn btn-dark' %>
<br>
<%= link_to "word", equipment_types_path(format: "word"), class: 'btn btn-dark' %>
</div>
</div>
</div>
</div>
device_type 型号
class EquipmentType < ApplicationRecord
has_many :tasks
accepts_nested_attributes_for :tasks
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
EquipmentType.create! row.to_hash
end
end
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |equipmenttype|
csv << equipmenttype.attributes.values_at(*column_names)
end
end
end
end
设备类型控制器
class EquipmentTypesController < ApplicationController
before_action :set_equipment_type, only: [:show, :edit, :update, :destroy]
before_action :set_task, only: [:show]
# GET /equipment_types
# GET /equipment_types.json
def index
@equipment_types = EquipmentType.all
respond_to do |format|
format.html
format.csv { send_data @equipment_types.to_csv }
end
end
# GET /equipment_types/1
# GET /equipment_types/1.json
def show
@equipment_type = EquipmentType.find_by(id: params[:id])
@tasks = Task.all
@equip_tasks = @equipment_type.tasks.all
@taskcount = @equip_tasks.count
respond_to do |format|
format.html
format.csv { send_data text: @equip_tasks.to_csv }
end
end
# GET /equipment_types/new
def new
@equipment_type = EquipmentType.new
end
# GET /equipment_types/1/edit
def edit
end
# POST /equipment_types
# POST /equipment_types.json
def create
@equipment_type = EquipmentType.new(equipment_type_params)
respond_to do |format|
if @equipment_type.save
format.html { redirect_to @equipment_type, notice: 'Equipment type was successfully created.' }
format.json { render :show, status: :created, location: @equipment_type }
else
format.html { render :new }
format.json { render json: @equipment_type.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /equipment_types/1
# PATCH/PUT /equipment_types/1.json
def update
respond_to do |format|
if @equipment_type.update(equipment_type_params)
format.html { redirect_to @equipment_type, notice: 'Equipment type was successfully updated.' }
format.json { render :show, status: :ok, location: @equipment_type }
else
format.html { render :edit }
format.json { render json: @equipment_type.errors, status: :unprocessable_entity }
end
end
end
def import
EquipmentType.import(params[:file])
redirect_to equipment_type_path, notice: "Equipment Type Added Successfully"
end
# DELETE /equipment_types/1
# DELETE /equipment_types/1.json
def destroy
@equipment_type.destroy
respond_to do |format|
format.html { redirect_to equipment_types_url, notice: 'Equipment type was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_equipment_type
@equipment_type = EquipmentType.find(params[:id])
end
def set_task
@task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def equipment_type_params
params.require(:equipment_type).permit(:name, task: [])
end
end
任务模型
class Task < ApplicationRecord
belongs_to :equipment_type
end
任务控制器
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
@task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
@task = Task.new(task_params)
respond_to do |format|
if @task.save
format.html { redirect_to @task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: @task }
else
format.html { render :new }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to @task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: @task }
else
format.html { render :edit }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
@task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:name, :monthly, :quarterly, :sixmonthly, :annually, :equipment_type_id)
end
end
解决方案
这应该让你开始:
您只需要将属性附加到数组即可。
代替,
csv << equipmenttype.attributes.values_at(*column_names)
放入这个(或类似的)(注意:这是资源密集型的,所以你需要减少它,特别是如果你有很多任务)
def csv_attributes
{
tasks: self.tasks.all.map(&:attributes).map(&:values),
id: self.id
}
end
接着
csv << equipmenttype.csv_attributes
推荐阅读
- html - 打印 Perl CSS 和 HTML
- mysql - Oracle DBlink 创建以从 MySql 获取数据
- shell - 通过powershell将打印机添加到打印服务器
- html - html文件输入只选择一个文件
- hangfire - 一次性使用hangfire
- c# - C# 将两个字符串列表与一个模式相交
- python-3.x - 如何在 Python 中匹配日期和时间
- android - 使用 jitpack 构建的库中的错误:无法解析 ':app@debug/compileClasspath' 的依赖关系
- xcode - 如何在 appStore 连接中更新我的应用信息?
- java - resultset.next() 仅显示第一行的输出