1

有没有更好的方法在 Ruby on Rails 中使用不同值在一个查询中更新更多记录?我解决了在 SQL 中使用 CASE 的问题,但是有任何 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.ini 文件。:) 你有什么建议?

4

1 回答 1

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
于 2013-09-15T10:42:15.940 回答