【问题标题】:Sorting Images using Active Storage使用 Active Storage 对图像进行排序
【发布时间】:2018-12-03 02:14:33
【问题描述】:

我正在尝试使用 Active Storage 来管理图像。我让多个上传工作正常,但我想使用acts_as_list 位置和jQuery 可排序来使用ajax 管理他们的订单,比如the video on this site。在普通模型中,我会运行迁移以向模型添加位置。但看起来我无法访问 Blob 或 Attachement 模型。我将如何解决这个问题?还是我必须重新使用 Carrierwave?任何帮助将不胜感激。

为了澄清,让我添加代码。

show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @post.title %>
</p>

<p>
  <strong>Content:</strong>
  <%= @post.content %>
</p>

<% if @post.images.attached? %>
<p>
  <strong>Images:</strong>
  <br>
  <div id="images" class="list-group" data-url="<%= sort_posts_path %>">
  <% @post.images.order(:position).each do |image| %>
    <%= link_to image_tag image.variant(resize: "200x200"), class: "list-group-item", id: dom_id(image) %>
  <% end %>
  </div>
</p>
<% end %>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>

posts.js

document.addEventListener("turbolinks:load", function() {

  $("#images").sortable({
    update: function(e, ui) {
      /* Update active storage database entry for each POST image. */
      /* This is the RAILS AJAX from the tutorial */
      Rails.ajax({
        url: $(this).data("url"),
        type: "PATCH",
        data: $(this).sortable('serialize'),
    }
  });

});

routes.rb

Rails.application.routes.draw do
  resources :posts do
    collection do
      patch :sort
    end
  end
end

posts_controller.rb

def sort
  params[:image].each_with_index do |id, index|
    Post.image.where(id: id).update_all(position: index + 1)
  end

  head :ok
end

【问题讨论】:

    标签: ruby-on-rails rails-activestorage


    【解决方案1】:

    这就是我最终所做的,以使其在实际应用程序中发挥作用。这个“简单”功能中的所有内容都令人惊叹。

    宝石文件

    gem 'jquery-rails'
    gem 'jquery-ui-rails'
    gem 'acts_as_list'
    

    position 添加到Active Storage 的迁移

    class AddPositionToActiveStorageAttachments < ActiveRecord::Migration[5.2]
      def change
        add_column :active_storage_attachments, :position, :integer, default: 0
      end
    end
    

    sorting.js

    这允许我们使用sort-me 类对任何内容进行排序。

    $(function() {
    
      $(".sort-me").sortable({
        update: function(e, ui){
          ui.placeholder.height(ui.item.height());
          Rails.ajax({
            url: $(this).data("url"),
            type: "PATCH",
            data: $(this).sortable('serialize')
          });
        }
      }).disableSelection();
    
    });
    

    edit.html.erb

    这是页面上相关代码的sn-p。将sort-me 类添加到包含的 div 将使可排序元素脱离 NEXT 项集。

    <div id="product-attachments" class="sort-me" data-url="<%= sort_attachments_admin_products_path %>">
      <% @product.images.order(:position).each do |attachment| %>
        <div id="<%= dom_id(attachment) %>" class="ui-state-default image-box">
          <%= image_tag attachment.variant(combine_options: {auto_orient: true, thumbnail: '200x200^', gravity: 'center', extent: '200x200' }) %>
          <%= link_to "Delete", delete_image_admin_products_path(@product.id, attachment.id), method: :delete, class: "btn btn-xs", data: {confirm: "Are you sure?"} %>
        </div>
      <% end %>
    </div>
    

    routes.rb

    这些是相关的路线。在这种情况下,使用的是管理命名空间。因此,如果您在没有它的情况下使用它,请确保您的路线/路径不包含管理部分。

    namespace 'admin' do
      resources :products do
        collection do
          patch '/products/sort/:id', action: :sort_attachments, as: 'sort_attachments'
          delete '/products/:id/images/:image_id', action: 'delete_image', as: 'delete_image'
        end
      end
    end
    

    products_controller.rb

    排序删除路由的相应控制器操作。

    def sort_attachments
      params[:attachment].each_with_index do |id, index|
        ActiveStorage::Attachment.where(id: id).update_all(position: index + 1)
      end
    
      head :ok
    end
    
    def delete_image
      ActiveStorage::Attachment.where(id: params[:image_id])[0].purge
      redirect_to edit_admin_product_path(params[:id]), notice: 'Image was successfully deleted.'
    end
    

    【讨论】:

      【解决方案2】:

      更新一个更好的方法 鉴于 MyModel.images 返回一个 ActiveStorageAttachment 模型数组,我刚刚通过创建迁移以向 active_storage_attachments 表添加位置列进行了测试 然后使用此字段对图像进行排序即可完美工作

      rails g migration add_order_by_to_active_storage_attachments position:integer
      

      显然不要忘记运行迁移,您可能希望在运行之前编辑迁移以更新现有记录上的位置字段。

      现在您可以将位置字段设置为您想要的任何值,然后您就可以使用 my_model.images.order(:position)

      如果我扩展此答案对您有帮助,请在 cmets 中询问

      为了更清楚,更新是需要排序的图像数组吗?为了实现这一点,您刚刚在迁移中创建的位置字段需要在视图中重新组织图像后将表单发送回控制器时设置。

      因此,在相关的控制器动作中,更新和创建,您可以循环通过@post.images 设置每个图像的位置并将图像保存回数据库。这将确保当您使用@post.images.order(:position) 查看图像时,它们会以正确的顺序显示。

      【讨论】:

      • 所以,为了测试这一点,我正在使用 Post 模型。我得到了要排序的图像,但是在观看视频并在控制器中添加 SORT 操作时,该示例显示了如何对帖子进行排序,而不是对帖子的图像进行排序,因此它们不会持续存在。它显示 Post.where(id: id).update_all(position: index + 1) 但这将对 POST 本身进行排序,而不是对图像进行排序。应该是 Post.image 之类的吗?
      • 因此您将位置列添加到 active_storage_attachments 表中。然后在您的视图中或您需要显示图像的任何位置@post.images.order(:position)。当您通过image.position = 1 等对它们进行排序时,您需要保存每个图像的位置...
      • @Tony 我已经更新了我的答案,但我不确定你的知识水平,所以我不确定我所说的是否足以让你上路,所以请感受免费寻求更多帮助
      • 我添加了代码以进行澄清。在本教程中,POSTS 是按位置排序的内容。在此示例中,需要对帖子的活动存储图像进行排序。我可以很好地拖入 UI,但是当我刷新页面时,它会立即回到原始位置。我查看了控制台,hte 位置没有更新。进行更新的 JS 不起作用。我希望这能澄清发生了什么。
      • @TonyS。所以职位没有得到更新。要么未调用排序函数,要么参数不正确。
      猜你喜欢
      • 1970-01-01
      • 2013-07-05
      • 2013-08-25
      • 2023-04-09
      • 2018-11-16
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 2021-04-15
      相关资源
      最近更新 更多