2013-08-30 73 views
1

有没有更好的方法在Ruby on Rails中用不同的值更新一条查询中的更多记录?我在SQL中使用CASE解决了问题,但是有没有Active Record解决方案?使用Rails中的Active Record更新一条查询中的更多记录

基本上我保存一个新的排序顺序,当一个新的列表从jQuery ajax帖子返回时。

#List of product ids in sorted order. Get from jqueryui sortable plugin. 
#product_ids = [3,1,2,4,7,6,5] 

# Simple solution which generate a loads of queries. Working but slow. 
#product_ids.each_with_index do |id, index| 
# Product.where(id: id).update_all(sort_order: index+1) 
#end 

##CASE syntax example: 
##Product.where(id: product_ids).update_all("sort_order = CASE id WHEN 539 THEN 1 WHEN 540 THEN 2 WHEN 542 THEN 3 END") 

case_string = "sort_order = CASE id "  

product_ids.each_with_index do |id, index| 
    case_string += "WHEN #{id} THEN #{index+1} " 
end 

case_string += "END" 

Product.where(id: product_ids).update_all(case_string) 

此解决方案工作速度快,只有一个查询,但我创建了一个查询字符串像在php中。 :)你的建议是什么?

+0

不知您对表的大小,你真的想** **一个查询?我认为无论你选择哪一种阅读方式更容易,并且有多个查询,或者你有一个查询,它会变得更加混乱。根据这个查询完成的频率(以及如何设置索引),我认为多个查询应该没问题。 – Roger

+1

Rogier,谢谢你的评论。你是对的。我赞同你。如果我有20个元素的列表,有20个查询,它需要100-150ms,所以没什么大不了的。但是一个查询只需要2ms,我得到了相同的结果。当然,在这种情况下,可能并不是真的需要这样做,但知道使数据库速度更快而查询次数更少的一般概念会很好。 :) – Zoltan

+0

我说得对,如果您改变两种产品的顺序,您需要更改表中每种产品(即行)的排序顺序(或者至少在两种产品之间的每一行中) ,因此随着产品表的增长,行更新的数量也在增长?在这种情况下,为什么不考虑一个只包含以逗号分隔的经过排序的ID的字符串的新表?在展示产品前阅读它,在重新订购后更新它? – Mitch

回答

2

您应该查看acts_as_list gem。它可以满足您的所有需求,并在幕后使用1-3个查询。它与jQuery排序插件一起使用是一个完美的搭配。它依赖于直接在SQL中增加/减少位置(sort_order)字段。

如果您的UI/UX依靠用户手动保存订单(用户对事物进行分类并点击更新/保存),这对您而言不是一个好的解决方案。但是,我强烈不鼓励这种接口,除非有特定的原因(例如,您不能在新旧订单中的数据库中间存在中间状态,因为其他内容取决于该顺序)。

如果情况并非如此,那么在用户移动一个元素(并且acts_as_list将很好地帮助您完成该操作)之后,您可以通过所有方法进行异步更新。

退房:

https://github.com/swanandp/acts_as_list/blob/master/lib/acts_as_list/active_record/acts/list.rb#L324

# This has the effect of moving all the higher items down one. 
def increment_positions_on_higher_items 
    return unless in_list? 
    acts_as_list_class.unscoped.where(
    "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}" 
).update_all(
    "#{position_column} = (#{position_column} + 1)" 
) 
end 
+0

谢谢。看起来很有希望。我肯定会试一试。 – Zoltan

相关问题