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

Laravel中为课程关联多视频:迁移、控制器及模型实现方法咨询

实现课程与多视频的关联管理(Ruby on Rails 示例)

这是典型的一对多关联场景,一门课程对应多个视频课时,下面从Model、Migration、Controller三个层面给出具体实现方案:

1. Model 层定义

通过has_many和belongs_to建立课程与视频的关联:

# app/models/course.rb
class Course < ApplicationRecord
  # 删除课程时自动删除关联的视频,避免孤儿数据
  has_many :videos, dependent: :destroy
end
# app/models/video.rb
class Video < ApplicationRecord
  # 视频必须属于某一门课程
  belongs_to :course
end

2. Migration 数据库表设计

首先创建课程表,再创建包含外键的视频表:

课程表迁移

执行生成命令:

rails generate migration CreateCourses title:string description:text

生成的迁移文件内容如下(可直接运行rails db:migrate):

# db/migrate/[timestamp]_create_courses.rb
class CreateCourses < ActiveRecord::Migration[7.0]
  def change
    create_table :courses do |t|
      t.string :title # 课程标题
      t.text :description # 课程描述

      t.timestamps
    end
  end
end

视频表迁移

执行生成命令(自动包含外键关联):

rails generate migration CreateVideos title:string url:string duration:integer position:integer course:references

生成的迁移文件可补充索引优化:

# db/migrate/[timestamp]_create_videos.rb
class CreateVideos < ActiveRecord::Migration[7.0]
  def change
    create_table :videos do |t|
      t.string :title # 课时标题
      t.string :url # 视频存储路径/第三方播放链接
      t.integer :duration # 视频时长(单位:秒)
      t.integer :position # 课时排序位置,用于控制播放顺序
      t.references :course, null: false, foreign_key: true # 关联课程的外键

      t.timestamps
    end
    # 确保同一课程下的课时位置不重复,同时优化查询性能
    add_index :videos, [:course_id, :position], unique: true
  end
end

运行迁移:

rails db:migrate

3. Controller 与路由配置

通过嵌套路由组织课程与视频的关系,让逻辑更清晰:

路由配置

# config/routes.rb
Rails.application.routes.draw do
  resources :courses do
    # 只保留需要的视频操作动作
    resources :videos, only: [:index, :new, :create, :edit, :update, :destroy]
  end
end

视频控制器实现

# app/controllers/videos_controller.rb
class VideosController < ApplicationController
  # 提前加载当前课程
  before_action :set_course
  # 提前加载当前操作的视频
  before_action :set_video, only: [:edit, :update, :destroy]

  # 查看课程下的所有课时(按排序位置升序)
  def index
    @videos = @course.videos.order(position: :asc)
  end

  # 新建课时页面
  def new
    @video = @course.videos.new
  end

  # 创建课时
  def create
    @video = @course.videos.new(video_params)
    if @video.save
      redirect_to course_videos_path(@course), notice: '课时添加成功'
    else
      render :new
    end
  end

  # 编辑课时页面
  def edit
  end

  # 更新课时信息
  def update
    if @video.update(video_params)
      redirect_to course_videos_path(@course), notice: '课时更新成功'
    else
      render :edit
    end
  end

  # 删除课时
  def destroy
    @video.destroy
    redirect_to course_videos_path(@course), notice: '课时删除成功'
  end

  private

  def set_course
    @course = Course.find(params[:course_id])
  end

  def set_video
    @video = @course.videos.find(params[:id])
  end

  # 强参数,只允许指定字段提交
  def video_params
    params.require(:video).permit(:title, :url, :duration, :position)
  end
end

额外建议

  • 可以给position字段添加默认值(比如设置为当前课程下视频数量+1),简化排序逻辑
  • 如果需要更复杂的课时排序(如拖拽调整),可以使用acts_as_list这类gem来简化实现
  • 视频文件建议存储到云存储服务,数据库只存储文件链接

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 11:17:06