使用Active Storage对图像进行排序

时间:2018-12-03 02:14:34

标签: ruby-on-rails rails-activestorage

我正在尝试使用Active Storage管理映像。我可以进行多个上传,但是我想使用可排序的jQuery的acts_as_list位置来使用ajax来管理其顺序,例如在the video on this site中。在普通模型中,我将运行迁移以向模型添加位置。但似乎我无法访问Blob或Attachment模型。我该如何解决?还是我必须重新使用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

2 个答案:

答案 0 :(得分:2)

这就是我最终要在实际应用程序中完成所有工作的结果。进入此“简单”功能的所有操作都令人惊讶。

宝石文件

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

这是页面上相关代码的片段。将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

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

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

答案 1 :(得分:0)

更新更好的方法 鉴于MyModel.images返回了ActiveStorageAttachment模型的数组,我刚刚通过创建将位置列添加到active_storage_attachments表的迁移进行了测试 然后使用该字段对图像进行排序

rails g migration add_order_by_to_active_storage_attachments position:integer

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

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

如果这对您有所帮助,请在评论中提问

UPDATE为了更清晰起见,需要对图像数组进行正确排序吗?为了实现这一点,在视图中重新组织图像后将表单发布回控制器时,需要设置您刚刚在迁移中创建的position字段。

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