Как обновить существующие записи в случае конфликта, Ruby on Rails

В моем коде у меня есть модель категории, которая имеет много подкатегорий, а подкатегория принадлежит категории.

У подкатегории есть поле :position, чтобы отслеживать, на какой позиции она должна располагаться под категорией. Вот мой код модели для подкатегории.

class Subcategory < ActiveRecord::Base
  belongs_to :category
  has_many :products
  validates_uniqueness_of :position
  scope :position, order("position asc")
end

Как видите, он не допускает дублирования позиций. Когда он обнаруживает, что позиция подкатегории уже существует, я хочу, чтобы пользователь сказал что-то вроде «Эта позиция уже занята, но ее все еще можно вставить. Хотите продолжить?» Да | Нет.

Если да, то мне нужно добавить +1 ко всем текущим подкатегориям категории: позиция (после позиции «рассматриваемой подкатегории». Итак, если в категории 1 есть подкатегории 1, 2 и 3, когда кто-то пытается добавить новую подкатегорию с позиции 2, мне нужно сбросить текущие 2 и 3 на 3 и 4 и вставить новую подкатегорию в позицию 2.

Если нет, то я просто хочу, чтобы он вернулся на экран редактирования.

Я не уверен, как именно это закодировать, я предполагаю, что проверка на конфликт :position будет в контроллере подкатегорий, если сохранение не удастся.

Итак, у меня 2 вопроса: где лучше всего поставить чек для этого кода, и мне нужна помощь/идеи для написания кода.


person ruevaughn    schedule 13.02.2012    source источник


Ответы (2)


Если оставить в стороне проверку уникальности, это приведет к переиндексации позиций:

# build a new subcategory
subcategory = category.subcategories.build(:foo => :bar)

# some arbitrary, zero-based position desired by your user
position = 3

# insert the subcategory at the desired position
category.subcategories.insert(position, subcategory)

# use each with index to re-index all of your subcategories
category.subcategories.each_with_index do |sc, index|
   sc.position = index
end

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

person Tom L    schedule 13.02.2012
comment
Я не очень хорошо объяснил последний бит. Забудьте об обратном вызове. Категория может иметь пользовательскую проверку, которая гарантирует, что, если у нее есть подкатегории, эти подкатегории имеют непрерывный набор значений позиции. - person Tom L; 15.02.2012

Я предлагаю acts_as_list управлять позицией. Это обрабатывает все, о чем вы говорите, за исключением того, что вам нужно вручную проверять столкновения, чтобы запросить пользователя:

if Subcategory.exists?(:position => params[:position])  # or whatever
  # alert the user
end
person Brandan    schedule 14.02.2012