RoR:使用 Dropzone.js 和 jQuery 可排序
RoR: using Dropzone.js with jQuery sortable
我在我的 rails 应用程序中结合了 Dropzone Js 和回形针,我还设法将 jquery 的排序应用到它。
我的 objective 是:
- 能够将每张图片的位置保存到数据库中
上传成功
- 当我更改(排序)图像的顺序时更新数据库中每个图像的位置。
我的上传模型有 :image 和 :position
我的路线有集合 {post "sort"}
我的控制器代码:
class UploadsController < ApplicationController
def new
@upload = Upload.new
end
def upload_list
@uploads = Upload.all.select(:id, :image_file_name, :image_file_size).order("position")
respond_to do |format|
format.json {render json: @uploads.to_json(methods: [:path])}
end
end
def create
@upload = Upload.create(upload_params)
@upload.position = params[:upload][:position]
if @upload.save
render json: { message: "success", fileID: @upload.id }, :status => 200
else
render json: { error: @upload.errors.full_messages.join(',')}, :status => 400
end
end
def sort
//params[:upload] gives undefined method for nil error
Upload.all.each_with_index do |id, index|
Upload.where(id: id).update_all({position: index+1})
end
render nothing: true
end
def destroy
@upload = Upload.find(params[:id])
if @upload.destroy
render json: { message: "File deleted from server" }
else
render json: { message: @upload.errors.full_messages.join(',') }
end
end
private
def upload_params
params.require(:upload).permit(:image, :position)
end
end
upload.rb:
class Upload < ActiveRecord::Base
has_attached_file :image, :styles => { :medium => "300x300>",:thumb => "100x100>" }
validates_attachment :image,
:presence => true,
:content_type => { :content_type => /\Aimage\/.*\Z/ },
:size => { :less_than => 1.megabyte }
def path
image.url
end
def as_json(options = { })
h = super(options)
h["name"] = h.delete "image_file_name"
h["size"] = h.delete "image_file_size"
h
end
end
new.html.erb:
<h1>Uploads#new</h1>
<%= form_for(@upload, html: { multipart: true, class: "dropzone"}) do |f| %>
<div class="fallback">
<%= f.file_field :image %>
<%= f.submit "Upload" %>
</div>
<% end %>
最后 uploads.js:
$(document).ready(function(){
Dropzone.autoDiscover = false;
$("#new_upload").dropzone({
maxFilesize: 1,
paramName: "upload[image]",
addRemoveLinks: true,
dictRemoveFile: "Delete",
//to show existing images from db
init: function() {
var thisDropZone = this;
$.getJSON('upload_list', function(data) {
$.each(data, function(index, val) {
var mockFile = { name: val.name, size: val.size };
thisDropZone.emit("addedfile", mockFile);
thisDropZone.emit("thumbnail", mockFile, val.path);
$(mockFile.previewTemplate).find('.dz-remove').attr('id', val.id);
// adding id attribute for serialize
$(".dz-preview:last-child").attr('id', "image_" + val.id);
});
});
},
success: function(file, response){
$(file.previewTemplate).find('.dz-remove').attr('id', response.fileID);
$(file.previewElement).addClass("dz-success");
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
},
removedfile: function(file){
var id = $(file.previewTemplate).find('.dz-remove').attr('id');
file.previewElement.remove();
$.ajax({
type: 'DELETE',
url: '/uploads/' + id,
success: function(data){
console.log(data.message);
}
});
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
}
});
//this function is for sorting + updating positions of old images loaded by the init function.
$(function() {
$(".dropzone").sortable({
items:'.dz-preview',
cursor: 'move',
opacity: 0.5,
containment: '.dropzone',
distance: 20,
update: function(event, ui) {
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
}
});
$(".dropzone").disableSelection();
});
});
我知道我有很多清理工作要做,但我想先让它开始工作。
我知道我需要在 dropzone 的每个图像的 .dz-preview 中有一个以“_”开头的 id 才能进行序列化。然而,成功函数中的 ajax post 在不应用任何 id 属性的情况下工作正常,所以当我上传 3 张图像时,在数据库中位置分别为 1、2 和 3,removedfile 函数也有效,如果我删除第二张图片,由于控制器中的排序方法,image1 获得位置“1”并且 image3 获得位置属性更新为 2。
我尝试在 init 函数中添加一行以将 id 属性附加到 .dz-preview 并刷新页面,以便我测试 init 函数并再次尝试排序,但它是一样的,我得到的是:
Started POST "/uploads/sort" for 127.0.0.1 at 2015-01-12 12:47:39 +0200
Processing by UploadsController#sort as */*
Parameters: {"image"=>["318", "320", "319"]}
Upload Load (2.7ms) SELECT "uploads".* FROM "uploads"
SQL (5.4ms) UPDATE "uploads" SET "position" = 1 WHERE "uploads"."id" = 318
SQL (14.7ms) UPDATE "uploads" SET "position" = 2 WHERE "uploads"."id" = 319
SQL (1.8ms) UPDATE "uploads" SET "position" = 3 WHERE "uploads"."id" = 320
Rendered text template (0.1ms)
Completed 200 OK in 54ms (Views: 2.0ms | ActiveRecord: 29.6ms)
注意参数的顺序,因此图像“318”应该占据位置 1,“320”应该占据位置 2,“319”应该占据位置 3...但是如图所示,更新忽略了新顺序...
知道我遗漏了什么吗?是sort方法还是.sortable函数?
谢谢
使用以下代码更新您的排序操作。
def sort
images = Upload.where(id: params[:image])
images.each do |image|
if position = params[:image].index(image.id.to_s)
image.update_attribute(:position, position + 1) unless image.position == position
end
end
render nothing: true
end
我在我的 rails 应用程序中结合了 Dropzone Js 和回形针,我还设法将 jquery 的排序应用到它。
我的 objective 是:
- 能够将每张图片的位置保存到数据库中 上传成功
- 当我更改(排序)图像的顺序时更新数据库中每个图像的位置。
我的上传模型有 :image 和 :position 我的路线有集合 {post "sort"}
我的控制器代码:
class UploadsController < ApplicationController
def new
@upload = Upload.new
end
def upload_list
@uploads = Upload.all.select(:id, :image_file_name, :image_file_size).order("position")
respond_to do |format|
format.json {render json: @uploads.to_json(methods: [:path])}
end
end
def create
@upload = Upload.create(upload_params)
@upload.position = params[:upload][:position]
if @upload.save
render json: { message: "success", fileID: @upload.id }, :status => 200
else
render json: { error: @upload.errors.full_messages.join(',')}, :status => 400
end
end
def sort
//params[:upload] gives undefined method for nil error
Upload.all.each_with_index do |id, index|
Upload.where(id: id).update_all({position: index+1})
end
render nothing: true
end
def destroy
@upload = Upload.find(params[:id])
if @upload.destroy
render json: { message: "File deleted from server" }
else
render json: { message: @upload.errors.full_messages.join(',') }
end
end
private
def upload_params
params.require(:upload).permit(:image, :position)
end
end
upload.rb:
class Upload < ActiveRecord::Base
has_attached_file :image, :styles => { :medium => "300x300>",:thumb => "100x100>" }
validates_attachment :image,
:presence => true,
:content_type => { :content_type => /\Aimage\/.*\Z/ },
:size => { :less_than => 1.megabyte }
def path
image.url
end
def as_json(options = { })
h = super(options)
h["name"] = h.delete "image_file_name"
h["size"] = h.delete "image_file_size"
h
end
end
new.html.erb:
<h1>Uploads#new</h1>
<%= form_for(@upload, html: { multipart: true, class: "dropzone"}) do |f| %>
<div class="fallback">
<%= f.file_field :image %>
<%= f.submit "Upload" %>
</div>
<% end %>
最后 uploads.js:
$(document).ready(function(){
Dropzone.autoDiscover = false;
$("#new_upload").dropzone({
maxFilesize: 1,
paramName: "upload[image]",
addRemoveLinks: true,
dictRemoveFile: "Delete",
//to show existing images from db
init: function() {
var thisDropZone = this;
$.getJSON('upload_list', function(data) {
$.each(data, function(index, val) {
var mockFile = { name: val.name, size: val.size };
thisDropZone.emit("addedfile", mockFile);
thisDropZone.emit("thumbnail", mockFile, val.path);
$(mockFile.previewTemplate).find('.dz-remove').attr('id', val.id);
// adding id attribute for serialize
$(".dz-preview:last-child").attr('id', "image_" + val.id);
});
});
},
success: function(file, response){
$(file.previewTemplate).find('.dz-remove').attr('id', response.fileID);
$(file.previewElement).addClass("dz-success");
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
},
removedfile: function(file){
var id = $(file.previewTemplate).find('.dz-remove').attr('id');
file.previewElement.remove();
$.ajax({
type: 'DELETE',
url: '/uploads/' + id,
success: function(data){
console.log(data.message);
}
});
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
}
});
//this function is for sorting + updating positions of old images loaded by the init function.
$(function() {
$(".dropzone").sortable({
items:'.dz-preview',
cursor: 'move',
opacity: 0.5,
containment: '.dropzone',
distance: 20,
update: function(event, ui) {
var order = $('.dropzone').sortable('serialize');
$.ajax({
type: 'POST',
url: '/uploads/sort',
data: order,
success: function(data){
console.log(data);
}
});
}
});
$(".dropzone").disableSelection();
});
});
我知道我有很多清理工作要做,但我想先让它开始工作。
我知道我需要在 dropzone 的每个图像的 .dz-preview 中有一个以“_”开头的 id 才能进行序列化。然而,成功函数中的 ajax post 在不应用任何 id 属性的情况下工作正常,所以当我上传 3 张图像时,在数据库中位置分别为 1、2 和 3,removedfile 函数也有效,如果我删除第二张图片,由于控制器中的排序方法,image1 获得位置“1”并且 image3 获得位置属性更新为 2。
我尝试在 init 函数中添加一行以将 id 属性附加到 .dz-preview 并刷新页面,以便我测试 init 函数并再次尝试排序,但它是一样的,我得到的是:
Started POST "/uploads/sort" for 127.0.0.1 at 2015-01-12 12:47:39 +0200
Processing by UploadsController#sort as */*
Parameters: {"image"=>["318", "320", "319"]}
Upload Load (2.7ms) SELECT "uploads".* FROM "uploads"
SQL (5.4ms) UPDATE "uploads" SET "position" = 1 WHERE "uploads"."id" = 318
SQL (14.7ms) UPDATE "uploads" SET "position" = 2 WHERE "uploads"."id" = 319
SQL (1.8ms) UPDATE "uploads" SET "position" = 3 WHERE "uploads"."id" = 320
Rendered text template (0.1ms)
Completed 200 OK in 54ms (Views: 2.0ms | ActiveRecord: 29.6ms)
注意参数的顺序,因此图像“318”应该占据位置 1,“320”应该占据位置 2,“319”应该占据位置 3...但是如图所示,更新忽略了新顺序...
知道我遗漏了什么吗?是sort方法还是.sortable函数?
谢谢
使用以下代码更新您的排序操作。
def sort
images = Upload.where(id: params[:image])
images.each do |image|
if position = params[:image].index(image.id.to_s)
image.update_attribute(:position, position + 1) unless image.position == position
end
end
render nothing: true
end