Rails 7 帮助干燥图像附件?

Rails 7 help DRYing out image attachments?

请耐心等待,我是发帖的新手,Rails 如果我措辞不当,非常抱歉!

我正在开发一个具有许多相似模型的 Rails 应用程序。每个视图都有一个 _form.html.haml 部分,内容不同但包含类似的组件,例如提交、删除等按钮。每个模型 has_many_attached 张照片,并且在表单中可以添加或删除照片。用于删除照片的 haml 看起来像这样,其中变量被替换为 _form.html.haml 中的任何视图:

.gallery#form
  - @VARIABLE.photo.each_with_index do |image, index|
    .overlay-container
      .img-square{ :style => "background-image: url(#{rails_blob_url(photo(@VARIABLE, index))})", :alt => "Photo of #{image}" }
      = link_to("Delete", delete_image_attachment_VARIABLE_url(image), method: :delete, class: 'button delete overlay')

要对每张照片进行删除,每个控制器中都有以下代码:

  def delete_image_attachment
    @photo = ActiveStorage::Attachment.find(params[:id])
    @photo.purge
    redirect_back fallback_location: @VARIABLE
    flash[:success] = 'Photo was successfully deleted.'
  end

并且 routes.rb 每个模型都有这段代码:

  resources :VARIABLE do
    member do
      delete :delete_image_attachment
    end
  end

但是,我需要在大约十几个模型上执行此操作。我的目标是将画廊带入新的部分,因为无论其他内容如何,​​它都会在每个 _form 中使用。但是,删除功能(尽管每个控制器都相同)与每个模型的 controller/routes.rb 绑定。

一定有某种方法可以将此功能干燥到几个文件中,而不是为每个模型复制粘贴,但我的 Google 搜索没有找到任何结果。因此,非常感谢任何指导或更好的 Rails 约定!

如果我对结构的理解正确,听起来你会想要做如下的事情:

创建一个 top-level 控制器来处理删除图像

  • 这可以被任何页面使用。
  • 这需要以下查询参数:
    • id 要删除的照片 ID。
    • redirect 操作完成后将用户重定向到哪里。

路线

现在只有 1 个路由来处理上面的控制器。

创建可重复使用的部分

用于使用重定向 url 渲染图像集合,允许您为部分设置以下状态:

  • photos 要渲染的图像集合。
  • redirect_url 这作为查询参数传递给集中删除图像控制器。

想法和模拟示例

这应该能够让您的实现变干。目前我看到的唯一将视图与删除结合在一起的是重定向 URL。通过将其抽象出来并将其本质上移动到部分参数将允许 re-use 和灵活性。

您已经通过 @VARIABLE 确定了您的耦合,这里是我期望它最终看起来如何的快速模拟:

部分模板

.gallery#form
  - @photos.each_with_index do |image, index|
    .overlay-container
      .img-square{ :style => "background-image: url(#{rails_blob_url(photo(@VARIABLE, index))})", :alt => "Photo of #{image}" }
      = link_to("Delete", delete_image_attachment_url(image, redirect: @redirect_url), method: :delete, class: 'button delete overlay')

需要:photosredirect_url 因此,请确保在消费控制器上设置 @photos@redirect_url

要在模板中访问实例属性的示例

@photos = GET_PHOTOS_HERE
@redirect_url = 'some-redirect-path'
render partial: 'photos_partial'

带有模板局部参数的示例

photos = GET_PHOTOS_HERE
render partial: 'photos_partial', locals: { photos: photos, redirect: 'some-redirect-path' }`

注意:您可能需要更改访问模板中局部变量的方式。

https://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables

控制器

  def delete_image_attachment
    @photo = ActiveStorage::Attachment.find(params[:id])
    @photo.purge
    redirect_back fallback_location: params[:redirect]
    flash[:success] = 'Photo was successfully deleted.'
  end

路线

这里只有删除任何图片附件的单一路径,指向上面的单一控制器。

delete 'resources/image_attachment/:id', to: 'resources#delete_image_attachment'

注意:将“资源”替换为您的控制器名称或您想要的scoping/naming。

PS:我已经有一段时间没做过了Rails所以我不能完全确定准确性或你的环境。