ruevaughn
ruevaughn

Reputation: 1319

How to update existing records if conflict, Ruby on Rails

In my code I have a Category model which has many subcategories, and the Subcategory belongs to a Category.

Subcategory has a :position field to keep track of what position it should line up under the category. Here is my Model code for SubCategory.

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

As you can see it doesn't allow for duplicate positions. When it detects that the Subcategory position already exists, I want it to prompt the user to say something like "That position is already taken, but it can still be inserted. Would you like to continue?" Yes | No.

If Yes, Then I need it to add +1 to all the current Category subcategories :position (after the 'subcategory in question' position. So if Category 1 has subcategories 1, 2, and 3 when someone tries to add a new subcategory with position 2, I need to drop the current 2 and 3 to 3 and 4 and insert the new subcategory to position 2.

If No, Then I just want it to return to the edit screen.

I am not sure how to code this exactly, I'm assuming the check for :position conflict will be in the subcategories controller, if the save fails.

So my 2 questions are: Where is the best place to put the check for this code, and I need help/ideas writing the code.

Upvotes: 1

Views: 759

Answers (2)

Brandan
Brandan

Reputation: 14983

I suggest acts_as_list to manage the position. That handles everything you're talking about, except that you'd need to manually check for collisions in order to prompt the user:

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

Upvotes: 0

Tom L
Tom L

Reputation: 3409

Setting the uniqueness validation aside, this will re-index the positions:

# 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

Instead of validating uniqueness you could add a before_validation callback to Category that simply ensures that you have a sorted, contiguous set of positions in subcategories.

Upvotes: 0

Related Questions