You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails从零实现CSV导入:课程-模块-任务层级数据导入求助

Rails CSV导入实现方案

需求说明

我是Rails及网站开发新手,若有基础问题敬请谅解。我的网站需上传特定格式的CSV文件,数据库结构为Course包含多个CourseModule(避免和Ruby内置Module关键字冲突),每个CourseModule包含多个Task。

CSV格式示例

Course_name #header
course1

Module_name #header
module1

Task_name,Task_description,Task_expected_result #header
mod1 task1 test,mod1 task2 test description,mod1 task1 test result
mod1 task2 test,mod1 task2 test description,mod1 task2 test result
mod1 task3 test,mod1 task3 test description,mod1 task3 test result

Module_name #header
module2

Task_name,Task_description,Task_expected_result
mod2 task1 test,mod2 task1 test description,mod1 task1 test result
mod2 task2 test,mod2 task2 test description,mod2 task2 test result

导入逻辑步骤

  • 读取Course_name直至空行,创建Course并获取course_id;
  • 读取Module_name直至空行,关联course_id创建CourseModule并获取module_id;
  • 读取Task相关字段,关联module_id创建Task直至空行;
  • 若未到文件末尾且出现新的Module_name,重复步骤2-3直至文件结束。

代码实现

1. 模型(Models)

app/models/course.rb

class Course < ApplicationRecord
  has_many :course_modules, dependent: :destroy
end

app/models/course_module.rb

# 用CourseModule代替Module,避免Ruby内置关键字冲突
class CourseModule < ApplicationRecord
  belongs_to :course
  has_many :tasks, dependent: :destroy
end

app/models/task.rb

class Task < ApplicationRecord
  belongs_to :course_module
end

2. 数据库迁移(Migrations)

运行以下命令生成迁移文件,执行rails db:migrate完成数据库创建:

rails generate model Course name:string
rails generate model CourseModule name:string course:references
rails generate model Task name:string description:text expected_result:text course_module:references

3. 控制器(Controller)

app/controllers/courses_controller.rb

class CoursesController < ApplicationController
  def new
    # 渲染上传表单页面
  end

  def import
    file = params[:csv_file]
    return redirect_to new_course_path, alert: "请选择CSV文件" unless file

    current_course = nil
    current_module = nil
    current_stage = :looking_for_course # 标记当前处理阶段:课程/模块/任务

    File.open(file.path, "r:utf-8") do |f|
      f.each_line do |line|
        line = line.strip
        next if line.empty? || line.start_with?("#") # 跳过空行和注释行

        case current_stage
        when :looking_for_course
          # 创建课程
          current_course = Course.create!(name: line)
          current_stage = :looking_for_module
        when :looking_for_module
          # 创建模块并关联所属课程
          current_module = current_course.course_modules.create!(name: line)
          current_stage = :processing_tasks
        when :processing_tasks
          # 若遇到新模块表头,切换阶段;否则处理任务数据
          if line == "Module_name"
            current_stage = :looking_for_module
          else
            task_attrs = line.split(",")
            Task.create!(
              name: task_attrs[0].strip,
              description: task_attrs[1].strip,
              expected_result: task_attrs[2].strip,
              course_module: current_module
            )
          end
        end
      end
    end

    redirect_to courses_path, notice: "CSV导入成功"
  rescue StandardError => e
    redirect_to new_course_path, alert: "导入失败:#{e.message}"
  end
end

4. 视图(Views)

app/views/courses/new.html.erb

<h1>导入CSV创建课程</h1>

<% if notice %>
  <p style="color: green;"><%= notice %></p>
<% end %>

<% if alert %>
  <p style="color: red;"><%= alert %></p>
<% end %>

<%= form_tag import_courses_path, multipart: true do %>
  <%= file_field_tag :csv_file, accept: ".csv" %>
  <%= submit_tag "上传并导入" %>
<% end %>

app/views/courses/index.html.erb(可选,用于展示已导入的课程数据)

<h1>课程列表</h1>

<% @courses.each do |course| %>
  <div style="margin: 15px 0; padding: 10px; border: 1px solid #ddd;">
    <h3><%= course.name %></h3>
    <% course.course_modules.each do |mod| %>
      <h4>模块:<%= mod.name %></h4>
      <ul>
        <% mod.tasks.each do |task| %>
          <li style="margin: 5px 0;">
            <strong><%= task.name %></strong><br>
            描述:<%= task.description %><br>
            预期结果:<%= task.expected_result %>
          </li>
        <% end %>
      </ul>
    <% end %>
  </div>
<% end %>

<%= link_to "导入新课程", new_course_path %>

5. 路由(Routes)

在config/routes.rb中添加路由配置:

Rails.application.routes.draw do
  resources :courses do
    collection do
      post :import
    end
  end
end

内容的提问来源于stack exchange,提问作者Rewi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:45:19