I'm using the ancestry gem in order to create subcategories. After that when I create an item (item model) I use the following group select in order to associate the item with the subcategories it belongs to. The group select has the categories and subcategories grouped together.
<%= form.input :category, collection: @categories, as: :grouped_select, group_method: :children, label: false, include_blank: true %>
@categories = Category.where(ancestry: nil).order('name ASC')
Also I'm using the the cocoon gem in order to create and thus associate many subcategories to an item.
Now I would like to add a customvalidate
method inside a model which will allow the user to only add subcategories that belong to the same main category, or otherwise return an error:
errors.add(:category, "you can only choose subcategories from he same category")
I'm kind of stuck on how to create this validate
method. Maybe first I should find the subcategories that are being added:
subcategory = Category.find(category)
And then find the category that the subcategory belongs to with this:
subcategory.root.name
But after that I have now idea what to do.
How can I create this validate
method in order to allow the user to only add subcategories that belong to the same main category, or otherwise return an error?
Thank you in advance. Help would be very much appreciated on this one.
If I understand, all Categories assigned to an Item must be subcategories of the same Category. And I assume they have to be subcategories.
Write a custom validation method in Item which verifies all the subcategories have parents, and all the subcategories are the same.
class Item < ApplicationRecord
has_many categories
validate :categories_have_the_same_parent
private def categories_have_the_same_parent
if categories.any? { |cat| !cat.ancestry_id }
errors.add(
:categories,
:not_a_subcategory,
"All categories must be sub-categories"
)
end
if categories.each_cons(2).any? { |a,b| a.ancestry_id != b.ancestry_id }
errors.add(
:categories,
:different_ancestors,
"All categories must have the same parent."
}
end
end
end
The diagnostics on this can be improved to include the offending categories.
Then, in the form, populate the Item with the form information and check the Item's validation as normal.
class ItemController < ApplicationController
def create
@item = Item.create!(...params...)
...creation succeeded...
rescue ActiveRecord::RecordInvalid => e
...creation failed...
end
end