From c814fc16a315bf77e675f75038a6bd1f934a0234 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 23 Oct 2013 12:58:11 -0400 Subject: [PATCH] Database structure to support sub categories --- app/models/category.rb | 23 +++++++++++---- ...09_add_parent_category_id_to_categories.rb | 6 ++++ spec/models/category_spec.rb | 29 ++++++++++++++++++- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20131023163509_add_parent_category_id_to_categories.rb diff --git a/app/models/category.rb b/app/models/category.rb index 9b39dd6598e..b0f322ca644 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -7,14 +7,14 @@ class Category < ActiveRecord::Base belongs_to :topic, dependent: :destroy if rails4? belongs_to :topic_only_relative_url, - -> { select "id, title, slug" }, - class_name: "Topic", - foreign_key: "topic_id" + -> { select "id, title, slug" }, + class_name: "Topic", + foreign_key: "topic_id" else belongs_to :topic_only_relative_url, - select: "id, title, slug", - class_name: "Topic", - foreign_key: "topic_id" + select: "id, title, slug", + class_name: "Topic", + foreign_key: "topic_id" end belongs_to :user @@ -33,6 +33,7 @@ class Category < ActiveRecord::Base validates :user_id, presence: true validates :name, presence: true, uniqueness: true, length: { in: 1..50 } validate :uncategorized_validator + validate :parent_category_validator before_validation :ensure_slug after_save :invalidate_site_cache @@ -43,6 +44,7 @@ class Category < ActiveRecord::Base after_destroy :publish_categories_list has_one :category_search_data + belongs_to :parent_category, class_name: 'Category' scope :latest, ->{ order('topic_count desc') } @@ -188,6 +190,15 @@ SQL errors.add(:slug, I18n.t(:is_reserved)) if slug == SiteSetting.uncategorized_name end + def parent_category_validator + if parent_category_id + errors.add(:parent_category_id, "You can't link a category to itself") if parent_category_id == id + + grandfather_id = Category.where(id: parent_category_id).pluck(:parent_category_id).first + errors.add(:parent_category_id, "You can't have more than one level of subcategory") if grandfather_id + end + end + def group_names=(names) # this line bothers me, destroying in AR can not seem to be queued, thinking of extending it category_groups.destroy_all unless new_record? diff --git a/db/migrate/20131023163509_add_parent_category_id_to_categories.rb b/db/migrate/20131023163509_add_parent_category_id_to_categories.rb new file mode 100644 index 00000000000..f4b86f50414 --- /dev/null +++ b/db/migrate/20131023163509_add_parent_category_id_to_categories.rb @@ -0,0 +1,6 @@ +class AddParentCategoryIdToCategories < ActiveRecord::Migration + def change + add_column :categories, :parent_category_id, :integer + end +end + diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index f78d17a3d87..a58eb835722 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -18,7 +18,7 @@ describe Category do it { should have_many :topics } it { should have_many :category_featured_topics } it { should have_many :featured_topics } - + it { should belong_to :parent_category} describe "resolve_permissions" do it "can determine read_restricted" do @@ -314,4 +314,31 @@ describe Category do end end + + + describe "parent categories" do + let(:user) { Fabricate(:user) } + let(:parent_category) { Fabricate(:category, user: user) } + + it "can be associated with a parent category" do + sub_category = Fabricate.build(:category, parent_category_id: parent_category.id, user: user) + sub_category.should be_valid + sub_category.parent_category.should == parent_category + end + + it "cannot associate a category with itself" do + category = Fabricate(:category, user: user) + category.parent_category_id = category.id + category.should_not be_valid + end + + it "cannot have a category two levels deep" do + sub_category = Fabricate(:category, parent_category_id: parent_category.id, user: user) + nested_sub_category = Fabricate.build(:category, parent_category_id: sub_category.id, user: user) + nested_sub_category.should_not be_valid + + end + + end + end