Rails基于Devise认证的相册多图上传场景下单张图片删除实现
单张图片删除功能实现全流程
一、现有代码的核心问题
- 语法层面错误:
current_user.albums.ActiveStorage::Blob.find(params[:id])不符合Ruby/Rails的调用规范,根本无法正常执行,访问该方法时会直接抛出语法类报错。 - 安全层面风险:如果绕过语法问题直接全局查询
ActiveStorage::Blob,全程没有校验图片和当前登录用户的归属关系,攻击者可以篡改请求参数删除任意用户的图片,存在越权操作的重大隐患。 - 体验层面缺陷:删除完成后固定重定向到
albums_path列表页,会强制打断用户在相册详情页的操作流,不符合常规交互逻辑。
二、修正后的控制器实现
调整delete_image_attachment方法的逻辑,补全权限校验、修正查询逻辑、优化跳转行为:
def delete_image_attachment # 仅查找当前登录用户名下的相册,完成第一层权限校验 @album = current_user.albums.find(params[:id]) # 仅在当前相册的图片集合内查找待删除的附件,完成第二层权限校验 @image = @album.images.find(params[:image_id]) # 同步删除图片的存储文件和数据库关联记录 @image.purge # 跳转回当前相册详情页,保留用户操作上下文 redirect_to @album, notice: "图片删除成功" end
三、路由正确配置方式
在现有resources :albums的嵌套路由块内新增图片删除的路由规则,不需要新增独立的控制器:
Rails.application.routes.draw do devise_for :users root to: "albums#index" resources :albums do resources :comments # 新增DELETE类型路由,绑定到Albums控制器的图片删除方法 delete "images/:image_id", to: "albums#delete_image_attachment", on: :member, as: :delete_image end end
配置完成后,Rails会自动生成名为delete_image_album的路径辅助方法,对应请求路径为/albums/:id/images/:image_id,请求方法为DELETE,和控制器的参数逻辑完全匹配。
四、Show页面删除链接编写
在相册详情页循环渲染单张图片时,直接调用生成的路由辅助方法拼接链接即可:
<% @album.images.each do |image| %> <div class="p-2"> <%= image_tag image, class: "w-full" %> <%# 补全链接的路径参数,保留原有的删除请求方法和二次确认逻辑 %> <%= link_to 'Remove', delete_image_album_path(@album, image), method: :delete, data: {confirm: "Are You Sure ?"} %> </div> <% end %>
链接参数说明
delete_image_album_path接收两个入参:第一个传入当前的@album对象,Rails会自动提取其id作为路由中:id参数的值;第二个传入循环到的单个图片附件对象,Rails会自动提取其id作为路由中:image_id参数的值。- 保留原有
method: :delete配置,和路由定义的请求类型保持一致;data-confirm配置的二次确认弹窗逻辑不需要额外修改。
内容的提问来源于stack exchange,提问作者Damon
相关产品推荐
相关产品推荐

