itmammoth / rails_sortable

Easy drag & drop sorting with persisting the arranged order for rails
MIT License
143 stars 37 forks source link

undefined method `[]' for nil:NilClass in sortable_controller.rb, line 27 #52

Closed bughuntsman closed 4 years ago

bughuntsman commented 4 years ago

I'm getting the next error while I try to sort a list.

NoMethodError at /sortable/reorder

undefined method `[]' for nil:NilClass

rails_sortable (1.3.2) app/controllers/sortable_controller.rb, line 27

   22     end
   23   
   24   private
   25   
   26     def find_model(token)
>  27       klass, id = VERIFIER.verify(token).match(/class=(.+),id=(.+)/)[1..2]
   28       klass.constantize.find(id)
   29     end
   30   end

I'm using '1.3.2' version.

Thank you in advance!

itmammoth commented 4 years ago

Hi, Can I have a look at your view(.erb/.haml/.slim etc)?

bughuntsman commented 4 years ago
.col-sm-12{ class: 'sortable' }
  = f.fields_for :hotel_photos, @photos, include_id: false do |hotel_photo|
    .col-sm-4{style: 'height: 150px; margin-bottom: 30px;', id: hotel_photo.object.sortable_id, class: 'nested-fields' + (hotel_photo.object.new_record? ? ' disable-sort' : '') }
      = render 'hotel_photo_fields', f: hotel_photo

"hotel_photo_fields" - file

.col-sm-6
  = f.hidden_field :id, value: f.object&.id
  = image_tag f.object.image.url(:thumb) if f.object.image?
  = f.file_field :image, class: "form-control hotel-photo filestyle", "data-input" => "false", required: false, accept: "image/png,image/jpeg"
.col-sm-6.text-center
  = link_to_remove_association t('views.hotels.new_reservation.form.fields.client.delete'), f, class: "btn btn-danger btn-xs btn-remove-image"
  .form-group
    = f.input :tag, collection: ["N/A", "Fachada"] + @hotel.room_types.active.map(&:name)

- if f.object.dimensions != [1440,960]
  .col-xs-12
    .text-danger Invalid size
bughuntsman commented 4 years ago

I duplicated SortableController in my app and I noticed that token is taking apparently a wrong format and it is repeating many times.

params['rails_sortable']

["BAhJIhpjbGFzcz1Ib3RlbFBob3RvLGlkPTIGOgZFVA==--fcdf4ea8066c1e156e6dda10bf2d032985604301",
 "BAhJIhpjbGFzcz1Ib3RlbFBob3RvLGlkPTMGOgZFVA==--52494848711f91ee09e7db8d6eaabb90c72591b2",
 "BAhJIhpjbGFzcz1Ib3RlbFBob3RvLGlkPTQGOgZFVA==--32eabb4f660b15504af21397d93e6003cb89cf32",
 "BAhJIhpjbGFzcz1Ib3RlbFBob3RvLGlkPTEGOgZFVA==--d394ed4f41b3907ca71e13645f51982598652537",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2",
 "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2"]
itmammoth commented 4 years ago

I guess the duplicated params - "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2" - are for new records because they have got no their ids untill persisted.

How does it go with using the item option in jquery?

// example
$('.sortrable').railsSortable({
    items: ':not(.disable-sort)'
});

https://api.jqueryui.com/sortable/#option-items

bughuntsman commented 4 years ago

You right! the problem is because of new records, but using item option did not work in this case, do you have another suggestion for handling ids for new records? I really thank for your help!

itmammoth commented 4 years ago

I think that should work... Please see the small example. https://codepen.io/itmammoth/pen/JjdYVVP

The problem is that toArray methods returns ids including for new records.

bughuntsman commented 4 years ago

Well, I only added a line for skipping token from new records and everything is working again. Anyway, really thanks for your help!!!

  TOKEN_OF_NEW_RECORDS = "BAhJIhljbGFzcz1Ib3RlbFBob3RvLGlkPQY6BkVU--8cfc743f8c2bc6b2263a98545282dd989f7c8ca2"

   def reorder
    ActiveRecord::Base.transaction do
      params['rails_sortable'].each_with_index do |token, new_sort|
        next if token == TOKEN_OF_NEW_RECORDS
        model = find_model(token)
        current_sort = model.read_attribute(model.class.sort_attribute)
        model.update_sort!(new_sort) if current_sort != new_sort
      end
    end

    head :ok
  end