Rails gem acts_as_list: как обрабатывать изменение порядка элементов списка при уничтожении элемента списка?

#ruby-on-rails #ruby #activerecord #ruby-on-rails-5 #acts-as-list

#ruby-on-rails #ruby #activerecord #ruby-on-rails-5 #действует как список

Вопрос:

Я использую acts_as_list v0.9.17 таким образом:

 class ListItem < ActiveRecord::Base
  acts_as_list scope: [:column1_id, :column2_id], :add_new_at => :bottom
end
  

Когда создается новый (ограниченный) @list_item объект, скажем, тот, где column1_id есть 1 , column2_id есть 11 и column3_id есть 37 , база данных выглядит следующим образом, как и ожидалось:

 id  | position | column1_id | column2_id | column3_id
--- | -------- | ---------- | ---------- | ----------
750 | 1        | 1          | 11         | 89
751 | 2        | 1          | 11         | 56
752 | 3        | 1          | 11         | 105
753 | 4        | 1          | 11         | 25
754 | 5        | 1          | 11         | 37
  

Однако, когда @list_item уничтожается, скажем, тот, где column1_id есть 1 , column2_id есть 11 и column3_id есть 56 (идентификатор записи 751 ), тогда база данных выглядит следующим образом:

 id  | position | column1_id | column2_id | column3_id
--- | -------- | ---------- | ---------- | ----------
750 | 1        | 1          | 11         | 89
752 | 3        | 1          | 11         | 105
753 | 4        | 1          | 11         | 25
754 | 5        | 1          | 11         | 37
  

Это означает, что существует пробел для position 2 .

Как предотвратить или отрегулировать разрыв? То есть, как обрабатывать переупорядочивание элементов списка при уничтожении элемента списка?


Примечание: Я знаю, что есть методы, которые меняют положение и переупорядочивают список, но я не знаю, использовать ли их и как решить проблему (возможно, каким-то образом remove_from_list ).

Ответ №1:

Как вы говорите, вам нужно использовать предоставленный вами метод, и вы можете сделать это либо в своем контроллере, либо в самой модели. Если вы из тех парней, которым нравятся обратные вызовы, то:

 class ListItem < ActiveRecord::Base
  acts_as_list scope: [:column1_id, :column2_id], :add_new_at => :bottom
  before_destroy { |record| record.remove_from_list }

  ....
end
  

Некоторым людям не нравится обрабатывать подобную логику в качестве обратного вызова, поэтому вы также можете добавить ее прямо в свой контроллер:

 class ListItemsController < Wherever
  ....
  ....

  def destroy
    @list_item.remove_from_list
    @list_item.delete

    ....
  end
end
  

Лично я бы добавил его в модель, но они оба делают одно и то же.

Если вам нужно попытаться исправить список, в котором отсутствует запись, скажем, у вас есть LineItems с идентификатором и позицией 0-4 и 6-9, отсутствует позиция 5. Вы можете сделать грязное исправление в консоли с помощью:

 LineItem.where('position >= ?', 5).each { |line_item| line_item.update_attributes(position: line_item.position - 1) }
  

Это позволит найти все элементы строки с позицией выше 4 и уменьшить каждую из них на единицу, оставив вам правильно упорядоченный список от 0 до 8.

Комментарии:

1. Для вас добавлен обратный вызов destroy: github.com/swanandp/acts_as_list/blob / … поэтому нет необходимости делать это вручную. За github.com/swanandp/acts_as_list/issues/347 Я думаю, что OP что-то неправильно настроил, но нам нужно больше информации.

2. Я ошибся в отображении данных столбца, и я обновил вопрос. В настоящее время я решаю проблему, используя before_destroy { |record| record.remove_from_list } обратный вызов внутри модели, но, поскольку ActsAsList сам имеет его, как указал @Brendon Muir, вероятно, мне следует его использовать. Возможно, я что-то неправильно настроил. Дайте мне знать, если вам нужна дополнительная информация.

3. ОБНОВЛЕНИЕ — Я (тонко) неправильно настроил :scope параметр. Теперь все работает без использования before_destroy обратного вызова. В любом случае спасибо.

4. Спасибо, что нашли время для обновления, поскольку я собирался потратить еще немного времени на это 🙂

5. @Backo, вы должны создать ответ, который показывает ваше решение проблемы, и принять это как ответ, если этот ответ не является правильным решением.