在我的rails应用程序中,我创建了一个列表,允许用户通过单击/拖放它们来重新排序记录。每次重新订购后,我都会运行更新操作并传递已移动项目的public class AjaxImage extends MNServlet {
private static URLCodec urlcodec = new URLCodec("UTF-8");
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
String id = request.getParameter(Plugin.PLUGIN_ID_VARIABLE);
if (isMultipart) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> multiparts = upload.parseRequest(request);
for (FileItem item : multiparts) {
if (!item.isFormField()) {
String road = "";
try {
String name = new File(item.getName()).getName();
String relativeWebPath = "/image";
String absoluteFilePath = request.getServletContext().getRealPath(relativeWebPath);
item.write(new File(absoluteFilePath, FilenameUtils.getName(item.getName())));
request.setCharacterEncoding("UTF-8");
String data = "";
try {
data =urlcodec.decode(request.getParameter("data"), "UTF-8");
} catch (DecoderException e) {
e.printStackTrace();
}
} catch (Exception e) {}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
和old_index
,并重新排序整个列表。只要我不以非常快的速度重新排序项目,该应用程序就可以正常运行。我的问题是如何改进设计,我必须考虑用户快速排序并准确反映这些变化?此外,我试图阻止用户点击&#34;保存&#34;按钮 - 但如果有必要,那么我可以实现它。
更新操作
new_index
我也使用以下gem: https://github.com/scttdavs/sortable-rails
答案 0 :(得分:0)
您的代码可以进行一些改进,但它们无法解决后端的root问题,无法跟上UI更新。
当您执行多个数据库请求时,这些请求需要将数据保持在一致状态,这应该在事务中完成:
if @list_item.present?
# update the modified item, and then update all items after that are affected
old_index = params[:old_rank].to_i
new_index = params[:sequence_rank].to_i
@list_item.transaction do
@list_item.update(sequence_rank: new_index)
if old_index < new_index
...
end
end
end
这段代码
.each_with_index do |item, index|
item.update(sequence_rank: item.sequence_rank - 1)
比它慢。这是因为each_with_index
必须从数据库中获取记录并将它们包装在ActiveRecord模型类中。然后item.update
为每条记录调用一个单独的SQL语句。一种改进方法是发出单个原始SQL更新语句,减少所有受影响记录的sequence_rank
。
sql = "UPDATE list_items SET sequence_rank = sequence_rank - 1 WHERE ..."
@list_item.connection.execute(sql)
递增sequence_rank
的查询可能与上面的内容合并。
解决根本问题,至少有两种解决方案。一种是禁用列表UI,直到更新ajax请求返回。这样您可以确保更新是串行的。但它有一些可用性影响。
另一种方法是在前端累积更新并按间隔或其他一些事件保存它们,同样,在ajax调用期间禁用相关的UI。这实现起来更复杂,但可能对可用性的影响较小。