You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在Rails 5中搭建LMS:课程与课时关联方案咨询

嘿,作为Rails新手能想到用关联来设计Course和Lesson,这点思路很对!下面一步步帮你搞定这两个模型的关联,还有前端创建课程时添加课时的实现方案:

第一步:创建带关联的模型

首先用Rails的生成器快速创建模型,Lesson需要关联到Course,所以生成Lesson模型时加上course:references,它会自动帮我们添加外键字段和基础关联代码:

# 生成Course模型(带标题和描述字段)
rails generate model Course title:string description:text

# 生成Lesson模型(关联Course,带标题、文本内容、视频链接字段)
rails generate model Lesson title:string content:text video_url:string course:references

然后执行迁移,把表结构同步到数据库:

rails db:migrate

接下来完善模型里的关联逻辑:
app/models/course.rb里添加:

class Course < ApplicationRecord
  # 一个Course有多个Lesson,删除Course时自动删除关联的Lesson
  has_many :lessons, dependent: :destroy
end

app/models/lesson.rb里(其实生成器已经帮你加了belongs_to :course,确认一下就行):

class Lesson < ApplicationRecord
  belongs_to :course
end
第二步:设置嵌套路由

因为Lesson是属于Course的子资源,用嵌套路由更符合RESTful设计,也能让前端更方便地关联课程和课时。修改config/routes.rb

Rails.application.routes.draw do
  # 嵌套路由:所有Lesson的操作都关联到对应的Course
  resources :courses do
    resources :lessons
  end
end

这样路由就会是/courses/:course_id/lessons这种形式,能明确知道哪个课时属于哪个课程。

第三步:调整Lesson控制器

因为用了嵌套路由,Lesson的CRUD操作需要先找到对应的Course,所以修改app/controllers/lessons_controller.rb

class LessonsController < ApplicationController
  before_action :set_course
  before_action :set_lesson, only: [:show, :edit, :update, :destroy]

  # GET /courses/:course_id/lessons
  def index
    @lessons = @course.lessons
  end

  # GET /courses/:course_id/lessons/1
  def show
  end

  # GET /courses/:course_id/lessons/new
  def new
    @lesson = @course.lessons.build
  end

  # GET /courses/:course_id/lessons/1/edit
  def edit
  end

  # POST /courses/:course_id/lessons
  def create
    @lesson = @course.lessons.build(lesson_params)

    if @lesson.save
      redirect_to @course, notice: '课时创建成功!'
    else
      render :new
    end
  end

  # PATCH/PUT /courses/:course_id/lessons/1
  def update
    if @lesson.update(lesson_params)
      redirect_to [@course, @lesson], notice: '课时更新成功!'
    else
      render :edit
    end
  end

  # DELETE /courses/:course_id/lessons/1
  def destroy
    @lesson.destroy
    redirect_to @course, notice: '课时已删除!'
  end

  private
    # 先找到对应的Course
    def set_course
      @course = Course.find(params[:course_id])
    end

    # 找到对应的Lesson
    def set_lesson
      @lesson = @course.lessons.find(params[:id])
    end

    # 强参数,只允许指定字段
    def lesson_params
      params.require(:lesson).permit(:title, :content, :video_url)
    end
end
第四步:前端实现课程关联课时

1. 先搞定Course的CRUD

用scaffold快速生成Course的创建、编辑页面:

rails generate scaffold Course title:string description:text

这样你就有了/courses/new页面来创建课程,创建后会跳转到课程详情页。

2. 在课程详情页添加课时表单

修改app/views/courses/show.html.erb,在课程信息下方添加课时列表和新增课时的表单:

<h1><%= @course.title %></h1>
<p><%= @course.description %></p>

<div class="lessons-section">
  <h2>本课程的课时</h2>
  <% if @course.lessons.empty? %>
    <p>还没有课时,赶紧添加第一个吧!</p>
  <% else %>
    <ul>
      <% @course.lessons.each do |lesson| %>
        <li>
          <%= link_to lesson.title, course_lesson_path(@course, lesson) %>
          <span class="actions">
            <%= link_to '编辑', edit_course_lesson_path(@course, lesson) %>
            <%= link_to '删除', course_lesson_path(@course, lesson), method: :delete, data: { confirm: '确定要删除这个课时吗?' } %>
          </span>
        </li>
      <% end %>
    </ul>
  <% end %>

  <h3>添加新课时</h3>
  <%= form_with(model: [@course, @course.lessons.build], local: true) do |form| %>
    <% if @lesson&.errors.any? %>
      <div class="alert alert-danger">
        <h4><%= pluralize(@lesson.errors.count, '错误') %> 无法创建课时:</h4>
        <ul>
          <% @lesson.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
        </ul>
      </div>
    <% end %>

    <div class="form-group">
      <%= form.label :title, '课时标题' %>
      <%= form.text_field :title, class: 'form-control' %>
    </div>

    <div class="form-group">
      <%= form.label :content, '文本内容' %>
      <%= form.text_area :content, class: 'form-control', rows: 5 %>
    </div>

    <div class="form-group">
      <%= form.label :video_url, '视频链接' %>
      <%= form.text_field :video_url, class: 'form-control' %>
    </div>

    <%= form.submit '创建课时', class: 'btn btn-primary' %>
  <% end %>
</div>

<%= link_to '编辑课程', edit_course_path(@course) %> |
<%= link_to '返回课程列表', courses_path %>
第五步:完善体验的小细节
  • dependent: :destroy点赞:这个选项会在删除课程时自动删除所有关联的课时,避免数据库里出现没有所属课程的“孤儿课时”。
  • 如果你想在创建课程时直接添加第一个课时,可以在Course的new页面加入嵌套表单,但对于新手来说,先分步骤实现课程创建后再添加课时会更简单。
  • 可以给Lesson的表单加一些前端验证,比如必填字段提示,提升用户体验。

这样一套下来,你就能实现课程和课时的关联,并且在前端完成课程创建、为课程添加课时的操作啦!

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

火山引擎 最新活动