Reputation: 1319
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
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
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