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

Rails多态关联下如何通过关联模型ID删除Favorite

实现多态收藏的类型+ID删除逻辑

1. 配置路由

首先在config/routes.rb中添加自定义删除路由,匹配你需要的/favorites/ata_public/2格式:

delete '/favorites/:favoritable_type/:favoritable_id', to: 'favorites#destroy', as: :favorite_by_type
  • :favoritable_type:接收收藏对象的类型(如ata_public)
  • :favoritable_id:接收收藏对象的ID
  • as: :favorite_by_type:生成路由辅助方法,方便视图调用

2. 完善FavoritesController的destroy方法

结合你的数据库结构(包含user_id、favoritable_type、favoritable_id字段),修改控制器代码,确保只删除当前用户的对应收藏:

class FavoritesController < ApplicationController
  before_action :set_favorite, only: [:destroy]

  def destroy
    @favorite.destroy
    respond_to do |format|
      format.html { redirect_to favorites_url, notice: '收藏已取消' }
      format.json { head :no_content }
    end
  end

  private

  def set_favorite
    # 将下划线格式的类型转成模型类名(如"ata_public" → "AtaPublic")
    favoritable_type = params[:favoritable_type].classify
    # 校验类型合法性,防止恶意参数
    unless Object.const_defined?(favoritable_type)
      redirect_to favorites_url, alert: '无效的收藏类型'
      return
    end
    # 定位当前用户的目标收藏
    @favorite = current_user.favorites.find_by(
      favoritable_type: favoritable_type,
      favoritable_id: params[:favoritable_id]
    )
    # 处理收藏不存在的情况
    unless @favorite
      redirect_to favorites_url, alert: '该收藏不存在'
    end
  end
end

3. 视图中的删除链接示例

用路由辅助方法生成符合要求的删除链接:

<%# 取消AtaPublic对象的收藏 %>
<%= link_to '取消收藏', favorite_by_type_path('ata_public', ata_public.id), 
      method: :delete, 
      data: { confirm: '确定要取消收藏吗?' } %>

<%# 取消AtaObject对象的收藏 %>
<%= link_to '取消收藏', favorite_by_type_path('ata_object', ata_object.id), 
      method: :delete, 
      data: { confirm: '确定要取消收藏吗?' } %>

关键注意点

  • 权限控制:通过current_user.favorites限定只操作当前用户的收藏,避免误删他人数据
  • 安全校验:用Object.const_defined?验证传入的类型是否对应真实存在的模型,防止注入攻击
  • 错误处理:对无效类型、不存在的收藏做跳转提示,提升用户体验

内容的提问来源于stack exchange,提问作者Roberto da Silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:48:25