使用活动存储对图像进行排序
Sorting Images using Active Storage
我正在尝试使用 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
更新更好的方法
鉴于 MyModel.images returns 一个 ActiveStorageAttachment 模型数组,我刚刚通过创建迁移以将位置列添加到 active_storage_attachments
table 来完成测试
然后使用此字段对图像进行排序效果很好
rails g migration add_order_by_to_active_storage_attachments position:integer
显然不要忘记 运行 迁移,您可能希望在 运行 之前编辑迁移以更新现有记录上的职位字段。
现在您可以将位置字段设置为您想要的任何值,然后您可以使用
my_model.images.order(:position)
如果我扩展这个答案对你有帮助,请在评论中提问
为了更清楚起见,更新一下,需要对图像数组进行排序,对吗?为了实现这一点,在视图中重新组织图像后,当表单回发到控制器时,需要设置您刚刚在迁移中创建的位置字段。
因此,在相关的控制器操作、更新和创建中,您可以循环遍历 @post.images
设置每个图像的位置并将图像保存回数据库。这将确保当您使用 @post.images.order(:position)
查看图像时,它们会以正确的顺序显示。
这就是我最终为了让它在实际应用程序中工作而做的事情。 "simple" 功能中的所有内容令人惊叹。
Gemfile
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
class.
对任何内容进行排序
$(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
class 添加到包含的 div 将使可排序的元素脱离下一组项目。
<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
这些是相关路线。在这种情况下,我们使用的是管理命名空间。因此,如果您在没有它的情况下使用它,请确保您的 routes/paths 不包括管理部分。
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
我正在尝试使用 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
更新更好的方法
鉴于 MyModel.images returns 一个 ActiveStorageAttachment 模型数组,我刚刚通过创建迁移以将位置列添加到 active_storage_attachments
table 来完成测试
然后使用此字段对图像进行排序效果很好
rails g migration add_order_by_to_active_storage_attachments position:integer
显然不要忘记 运行 迁移,您可能希望在 运行 之前编辑迁移以更新现有记录上的职位字段。
现在您可以将位置字段设置为您想要的任何值,然后您可以使用
my_model.images.order(:position)
如果我扩展这个答案对你有帮助,请在评论中提问
为了更清楚起见,更新一下,需要对图像数组进行排序,对吗?为了实现这一点,在视图中重新组织图像后,当表单回发到控制器时,需要设置您刚刚在迁移中创建的位置字段。
因此,在相关的控制器操作、更新和创建中,您可以循环遍历 @post.images
设置每个图像的位置并将图像保存回数据库。这将确保当您使用 @post.images.order(:position)
查看图像时,它们会以正确的顺序显示。
这就是我最终为了让它在实际应用程序中工作而做的事情。 "simple" 功能中的所有内容令人惊叹。
Gemfile
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
class.
$(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
class 添加到包含的 div 将使可排序的元素脱离下一组项目。
<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
这些是相关路线。在这种情况下,我们使用的是管理命名空间。因此,如果您在没有它的情况下使用它,请确保您的 routes/paths 不包括管理部分。
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