Должен ли act_as_list автоматически переупорядочивать элементы, когда ресурс обновляется с помощью update_attributes? - PullRequest
3 голосов
/ 14 октября 2011

Я использую плагин act_as_list с рельсами 3.1, и всякий раз, когда я добавляю или удаляю ресурс, существующие позиции упорядочиваются и обновляются в порядке. Однако при обновлении позиции ресурса с помощью update_attributes переупорядочение, по-видимому, не происходит, и у меня могут остаться ресурсы с дублированными позициями. Это правильное поведение act_as_list?

Я искал разъяснения, но документация по этому плагину действительно ограничена.

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

Спасибо

Ответы [ 2 ]

2 голосов
/ 14 октября 2011

В плагине нет ничего, что вызывалось бы при обновлении объекта.Вам нужно будет сделать это вручную, используя встроенные методы, которые предоставляет act_as_list.

Файл ruby ​​для этого плагина состоит всего из 300 строк, и за ним легко следить, он расскажет вам все, что нужно знать о acts_as_list... честно говоря, ничего особенного: https://github.com/swanandp/acts_as_list/blob/master/lib/acts_as_list/active_record/acts/list.rb

Чтобы сделать это вручную, просто возьмите все предметы с позицией выше, чем у текущего предмета, и увеличивайте каждый.Вот как я справляюсь с этим в своих приложениях (не используя act_as_list, но концепция есть).Это пример для заказа форумов:

forum.rb

PositionOptions = [["First Forum", "-1"]] + all.map{|forum| ["After #{forum.subject}", forum.position]}

attr_accessor :position_before
  before_save :set_position, :if => "position_before.present?"
    def set_position
      self.position = position_before.to_i + 1
    end

  after_save :do_positions, :if => "position_before.present?"
    def do_positions
      Forum.where('position >= ? AND id != ?', position, id).order('position, updated_at DESC').all.each_with_index do |forum, index|
        forum.update_attribute('position', position + index + 1)
      end
    end

просмотр

<% position_options = Forum::PositionOptions %>
<%= f.select :position_before, position_options.reject {|forum| @forum.position == forum[1]}, :selected => position_options[position_options.index {|p| p[1] == @forum.position} - 1][1] %>

Возможно, нет лучший способ сделать это, но это было лучшее, что я мог придумать.Вероятно, это будет слишком дорого, если вы планируете часто обновлять позиции или если будет размещено много объектов ... но это работает для небольших коллекций, таких как форумы.

0 голосов
/ 09 мая 2013

Я обработал это, переопределив записывающее устройство для атрибута has_many, чтобы сначала очистить список, например, в этом случае, когда Photo acts_as_list, я переопределил записывающее устройство в ссылающемся классе:

def photos_with_clear=(photos)
  self.photos_without_clear=[]
  self.photos_without_clear=photos
end
alias_method_chain :photos=, :clear

Это, очевидно, довольно неэффективнопотому что фотографии очищаются и воссоздаются всякий раз, когда установлена ​​коллекция фотографий, но она имеет преимущество работы с обоими update_attributes(:photos=>[<Photo 1>, <Photo 2>]) или update_attributes(:photo_ids=>[123, 456]) (по крайней мере, в рельсах 2.3.18).

...