1

Ruby on Railsで異なる値を持つ1つのクエリでより多くのレコードを更新するより良い方法はありますか? 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)

このソリューションは高速で 1 つのクエリのみで動作しますが、php のようにクエリ文字列を作成します。:) あなたの提案は何ですか?

4

1 に答える 1

2

act_as_list gem を確認してください。必要なことはすべて実行し、バックグラウンドで 1 ~ 3 個のクエリを使用します。jquery ソート可能プラグインで使用するのに最適です。これは、SQL で直接位置 (sort_order) フィールドをインクリメント/デクリメントすることに依存しています。

UI/UX がユーザーが手動で注文を保存することに依存している場合 (ユーザーが注文を整理してから、更新/保存をクリックします)、これは良い解決策ではありません。ただし、特定の理由がない限り、この種のインターフェイスを強くお勧めしません (たとえば、古い順序と新しい順序の間の中間状態をデータベースに保持することはできません。他の何かがその順序に依存するためです)。

そうでない場合は、ユーザーが 1 つの要素を移動した後に必ず非同期更新を実行してください (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 に答える