title: How to save the order of a drag and drop item to the database in Rails?
body: <p>I am using <a href="https://github.com/McPants/jquery.shapeshift" rel="nofollow">Jquery Shapeshift</a> for drag and drop on some lists that i have.</p>
  
  <p>I have a javascript array containing the list_id and it's position. That array is sent to my controller each time i move a list. So all i need to do is take that data and save it to the position field in my database. Each list has a position field for its order.</p>
  
  <p>Below is the array that contains the list_id and it's position for each list. This is sent to my controller action called sortlists each time i drag a list into a different position.</p>
  
  <pre><code>Parameters: {"position"=&gt;"[[\"list_46\",0],[\"list_45\",1],
  [\"list_38\",2],[\"list_44\",3],[\"list_39\",4],[\"list_37\",5]]"}
  </code></pre>
  
  <p>So how can i take that information above and update the position field for each list.</p>
  
  <pre><code>def sortlists
    params[:position]
    render nothing: true
  end
  </code></pre>
  
  <p>Again everything things is already setup i just need to know how to use the contents in the array to update the lists.</p>
  
  <p>I have tried this and it does not work.</p>
  
  <pre><code>def sortlists
    params[:position].each_with_index do |id, index|
    List.where(id: id).update_all({position: index+1})
    end
  
    render nothing: true 
  end
  </code></pre>
  
  <p><br></p>
  
  <h2><strong>Edit (this is what i have right now)</strong></h2>
  
  <p><strong>View</strong></p>
  
  <pre><code>&lt;div class="container listwrap"&gt;
    &lt;% @lists.each do |list| %&gt;
      &lt;div class="list" data-item-id="&lt;%= list.id %&gt;"&gt;
  
         &lt;div class="list-title"&gt; &lt;%= list.title %&gt;&lt;/div&gt;
  
      &lt;/div&gt;
    &lt;% end %&gt; 
  &lt;/div&gt;   
  </code></pre>
  
  <p><strong>Javascript</strong></p>
  
  <pre><code>jQuery(function() {
    $('.listwrap').shapeshift();
    $('.listwrap').on('ss-rearranged', function(e) {
      order = [];
      $(this).children().each(function() {
        order.push([$(this).attr("data-item-id"), $(this).index() ]);
      });
      $.post('/boards/sortlists',
        {order: JSON.stringify(order)},
        function(data, status, jqXHR) {
        // This is what gets rendered from your rails controller + action
      });
    });
  });
  </code></pre>
  
  <p><strong>Controller</strong></p>
  
  <pre><code>def sortlists
    items_to_update = JSON::parse(params[:order]).map{|item| [item[0], {position: item[1]}]}
    items_hash_to_update = items_to_update.to_h
    List.update(items_hash_to_update.keys, items_hash_to_update.values)
    render nothing: true  
  end
  </code></pre>
  
  <p><strong>Rails Terminal each time a list is dragged</strong></p>
  
  <p>Each time i move list it runs the sortlists method in my controller. Now as you can see in the parameters i have the list_id and then the position those are correct. Then it updates everything but the positions end up wrong. They are not updated to what the parameters say they should be. It also appears to be running everything twice and i don't know why?</p>
  
  <pre><code>Parameters: {"order"=&gt;"[[\"48\",0],[\"49\",1]]"}
    Parameters: {"order"=&gt;"[[\"48\",0],[\"49\",1]]"}
    User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
    User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
    List Load (0.2ms)  SELECT  "lists".* FROM "lists" WHERE "lists"."id" = $1 LIMIT 1  [["id", 48]]
    List Load (0.2ms)  SELECT  "lists".* FROM "lists" WHERE "lists"."id" = $1 LIMIT 1  [["id", 48]]
     (0.2ms)  BEGIN
     (0.2ms)  BEGIN
    SQL (0.2ms)  UPDATE "lists" SET "position" = $1, "updated_at" = $2 WHERE "lists"."id" = $3  [["position", 1], ["updated_at", "2015-09-09 01:15:27.117822"], ["id", 48]]
    SQL (0.2ms)  UPDATE "lists" SET "position" = $1, "updated_at" = $2 WHERE "lists"."id" = $3  [["position", 1], ["updated_at", "2015-09-09 01:15:27.117822"], ["id", 48]]
     (0.2ms)  SELECT COUNT(*) FROM "lists" WHERE "lists"."board_id" = $1 AND (position = 1)  [["board_id", 11]]
     (0.2ms)  SELECT COUNT(*) FROM "lists" WHERE "lists"."board_id" = $1 AND (position = 1)  [["board_id", 11]]
    SQL (0.2ms)  UPDATE "lists" SET position = (position + 1) WHERE "lists"."board_id" = $1 AND (position &gt;= 1) AND (position &lt; 2 AND id != 48)  [["board_id", 11]]
    SQL (0.2ms)  UPDATE "lists" SET position = (position + 1) WHERE "lists"."board_id" = $1 AND (position &gt;= 1) AND (position &lt; 2 AND id != 48)  [["board_id", 11]]
     (13.9ms)  COMMIT
     (13.9ms)  COMMIT
    List Load (0.2ms)  SELECT  "lists".* FROM "lists" WHERE "lists"."id" = $1 LIMIT 1  [["id", 49]]
    List Load (0.2ms)  SELECT  "lists".* FROM "lists" WHERE "lists"."id" = $1 LIMIT 1  [["id", 49]]
     (0.1ms)  BEGIN
     (0.1ms)  BEGIN
    SQL (0.3ms)  UPDATE "lists" SET "position" = $1, "updated_at" = $2 WHERE "lists"."id" = $3  [["position", 1], ["updated_at", "2015-09-09 01:15:27.141404"], ["id", 49]]
    SQL (0.3ms)  UPDATE "lists" SET "position" = $1, "updated_at" = $2 WHERE "lists"."id" = $3  [["position", 1], ["updated_at", "2015-09-09 01:15:27.141404"], ["id", 49]]
     (0.3ms)  SELECT COUNT(*) FROM "lists" WHERE "lists"."board_id" = $1 AND (position = 1)  [["board_id", 11]]
     (0.3ms)  SELECT COUNT(*) FROM "lists" WHERE "lists"."board_id" = $1 AND (position = 1)  [["board_id", 11]]
    SQL (0.3ms)  UPDATE "lists" SET position = (position + 1) WHERE "lists"."board_id" = $1 AND (position &gt;= 1) AND (position &lt; 2 AND id != 49)  [["board_id", 11]]
    SQL (0.3ms)  UPDATE "lists" SET position = (position + 1) WHERE "lists"."board_id" = $1 AND (position &gt;= 1) AND (position &lt; 2 AND id != 49)  [["board_id", 11]]
     (9.0ms)  COMMIT
     (9.0ms)  COMMIT
  </code></pre>