Rails has_many :through关联下实现用户加入已有Curso的方法问询
实现方案如下
首先可以明确:这个创建报名关联的逻辑放在InscripcionesController中处理完全符合Rails REST设计规范,也不需要新增new视图、不需要填写表单,只需要三步即可实现需求:
1. 配置路由
在路由文件中给课程资源嵌套一个报名的POST路由,语义更清晰:
# config/routes.rb Rails.application.routes.draw do # 其他原有路由 resources :cursos do post 'inscribir', to: 'inscripciones#create', on: :member end end
配置完成后会生成/cursos/:id/inscribir格式的路由,对应InscripcionesController的create动作。
2. 编写控制器逻辑
不需要编写new动作,直接处理create请求即可,额外增加重复报名的校验避免报错:
# app/controllers/inscripciones_controller.rb class InscripcionesController < ApplicationController # 登录校验,用Devise的话直接用这个过滤器,其他登录方案替换为对应校验逻辑即可 before_action :authenticate_user! before_action :find_curso def create unless current_user.cursos.include?(@curso) current_user.cursos << @curso flash[:notice] = "成功加入课程" else flash[:alert] = "你已经加入过该课程" end # 完成操作后跳转回课程列表页 redirect_to cursos_path end private def find_curso @curso = Curso.find(params[:id]) end end
3. 课程列表页加入按钮
直接用Rails自带的button_to助手生成POST请求按钮,不需要手动写表单:
<!-- app/views/cursos/index.html.erb 遍历课程的位置插入 --> <% @cursos.each do |curso| %> <div class="curso-card"> <h4><%= curso.nombre %></h4> <!-- 其他课程展示信息 --> <% if current_user.cursos.include?(curso) %> <span>已加入</span> <% else %> <%= button_to "加入课程", inscribir_curso_path(curso), method: :post %> <% end %> </div> <% end %>
如果你不想额外调用InscripcionesController,也可以把create逻辑直接放到CursosController的自定义动作中,不过按职责拆分原则,放在关联资源对应的控制器里后期维护会更清晰。
内容的提问来源于stack exchange,提问作者jpgazmuri
相关产品推荐
相关产品推荐

