Skip to main content

Sortable Drag and Drop

Rails • Asked by Clay

Hi

I am hoping someone can assist. I have gone through the tutorial of Srttable Drag and Drop.
https://gorails.com/episodes/sortable-drag-and-drop

All is working but once the drop happens I am getting a NoMethodError
NoMethodError (undefined methodeach_with_index' for nil:NilClass):`

This is happening on the sort action in the controller (mine being admin/products)

def sort
    params[:product].each_with_index do |id, index|
        Product.where(id: id).update_all(position: index + 1)
    end

    head :ok
end

Anyone know what could be causing this ?


Hi Clay,

If you throw a byebug in your action before you start iterating, you'll get a console where you can test what the params are and see if the id's are even present in the params hash or that your key is actually :product.

Can you post your view where you have your sortable list and the js?


Hi Jacob

Thanks for a idea. Here is the byebug result.
[1070, 1079] in /Users/Clayton/.rvm/gems/ruby-2.5.1/gems/actionpack-5.2.0/lib/action_controller/metal/strong_parameters.rb
1070: include ActiveSupport::Rescuable
1071:
1072: # Returns a new ActionController::Parameters object that
1073: # has been instantiated with the request.parameters.
1074: def params
=> 1075: @_params ||= Parameters.new(request.parameters)
1076: end
1077:
1078: # Assigns the given +value+ to the +params+ hash. If +value+
1079: # is a Hash, this will create an ActionController::Parameters


admin/products controller

def sort
    params[:product].each_with_index do |id, index|
        Product.where(id: id).update_all(position: index + 1)
    end
    head :ok
end

products.js

document.addEventListener("turbolinks:load", function() {

    $("#products").sortable({
        update: function(e, ui) {
            Rails.ajax({
                url: $(this).data("url"),
                type: "PATCH",
                data: $(this).sortable('serialize'),
            });
        }
    });
});

Admin Products Index

<tbody id="products" data-url="<%= sort_admin_products_path %>">
   <%= render @products %>
 </tbody>

Admin Products - Product

<tr>
  <td><%= link_to product.product_code, admin_product_path(product), id: dom_id(product) %> - (<%= product.position %>)</td>
  <td><%= product.product_name.truncate(45) %></td>
  <td></td>
  <td><%= link_to 'Edit', edit_admin_product_path(product), class: 'btn btn-sm btn-warning' %></td>
  <td><%=button_to "Remove", admin_product_path(product), method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-sm btn-danger' %></td>
</tr>

Ahh, I think your problem is how you're identifying your sortable objects. I haven't tested this or even done the sorting on a table so this could be wrong, but you're putting the id: dom_id(product) on a <td> tag and I believe it should be on the <tr> tag.

As for the byebug result, you should do something like this:

def sort
    byebug  
    params[:product].each_with_index do |id, index|
        Product.where(id: id).update_all(position: index + 1)
    end

    head :ok
end

And then refresh the page. Now look at your terminal where you started your rails server at and you should now have a command prompt where you can type in params then hit enter and get the params for that request. https://github.com/deivid-rodriguez/byebug


Sorry, small correction to the byebug instructions...

You'll refresh your page and then try rearranging your rows. The first time you move a row into a new slot it should fire the ajax request which should now trigger the byebug instance in your console. Now you can type in params and see the params that were sent over in the request to see if you're getting anything at all related to your rearranged rows.


Hi thanks for the suggestions.
Here is the result of the params
"admin/products", "action"=>"sort"} permitted: false>

The Dom it is on the link_to tag within the td. Not sure if it should be moved out but here it is displaying correctly.


Displaying ok != working ok

Result of params shows that the ID's aren't being grabbed by the JS. So since all your code on the JS looks good, then the process of elimination is saying it's because you're defining your id on the <td> instead of <tr>

Did you move id: dom_id(product) to the <tr> tag?

Please do that and then test. I just modified one of my implementations and it does not work if I put the ID on the <td> tag but it works as expected when I move it to the <tr> tag.


Hi

Ok added as per your suggestion

https://stackoverflow.com/questions/51676832/sortable-drag-and-drop-rails-jquery
Thanks once again have a great one!

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.