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
相关产品推荐
相关产品推荐

