diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index c1446481308..3fb80f71aef 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -138,6 +138,7 @@ class CategoriesController < ApplicationController :logo_url, :background_url, :allow_badges, + :slug, :permissions => [*p.try(:keys)]) end end diff --git a/app/models/category.rb b/app/models/category.rb index 846f5b36b15..0680ca96a05 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -32,7 +32,9 @@ class Category < ActiveRecord::Base length: { in: 1..50 } validate :parent_category_validator - before_validation :ensure_slug + # before_validation :ensure_slug + # before_save :ensure_slug + validate :ensure_slug before_save :apply_permissions before_save :downcase_email before_save :downcase_name @@ -196,18 +198,23 @@ SQL end + def duplicate_slug? + Category.where(slug: self.slug, parent_category_id: parent_category_id).where.not(id: id).any? + end + def ensure_slug if name.present? self.name.strip! - self.slug = Slug.for(name) - return if self.slug.blank? - - # If a category with that slug already exists, set the slug to nil so the category can be found - # another way. - category = Category.where(slug: self.slug, parent_category_id: parent_category_id) - category = category.where("id != ?", id) if id.present? - self.slug = '' if category.exists? + if slug.present? + # custom slug + errors.add(:slug, "is already in use") if duplicate_slug? + else + # auto slug + self.slug = Slug.for(name) + return if self.slug.blank? + self.slug = '' if duplicate_slug? + end end end diff --git a/spec/controllers/categories_controller_spec.rb b/spec/controllers/categories_controller_spec.rb index 08b731d6df0..9131980c1b6 100644 --- a/spec/controllers/categories_controller_spec.rb +++ b/spec/controllers/categories_controller_spec.rb @@ -43,13 +43,12 @@ describe CategoriesController do end end - describe "success" do it "works" do readonly = CategoryGroup.permission_types[:readonly] create_post = CategoryGroup.permission_types[:create_post] - xhr :post, :create, name: "hello", color: "ff0", text_color: "fff", + xhr :post, :create, name: "hello", color: "ff0", text_color: "fff", slug: "hello-cat", auto_close_hours: 72, permissions: { "everyone" => readonly, @@ -62,6 +61,7 @@ describe CategoriesController do [Group[:everyone].id, readonly],[Group[:staff].id,create_post] ] category.name.should == "hello" + category.slug.should == "hello-cat" category.color.should == "ff0" category.auto_close_hours.should == 72 end @@ -180,7 +180,7 @@ describe CategoriesController do readonly = CategoryGroup.permission_types[:readonly] create_post = CategoryGroup.permission_types[:create_post] - xhr :put, :update, id: @category.id, name: "hello", color: "ff0", text_color: "fff", + xhr :put, :update, id: @category.id, name: "hello", color: "ff0", text_color: "fff", slug: "hello-category", auto_close_hours: 72, permissions: { "everyone" => readonly, @@ -193,6 +193,7 @@ describe CategoriesController do [Group[:everyone].id, readonly],[Group[:staff].id,create_post] ] @category.name.should == "hello" + @category.slug.should == "hello-category" @category.color.should == "ff0" @category.auto_close_hours.should == 72 end diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index 6defee8fee6..9e3cf3d0fd0 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -192,6 +192,20 @@ describe Category do end end + describe 'custom slug can be provided' do + it 'has the custom value' do + c = Fabricate(:category, name: "Cats", slug: "cats-category") + c.slug.should eq("cats-category") + end + + it 'fails if custom slug is duplicate with existing' do + c1 = Fabricate(:category, name: "Cats", slug: "cats") + c2 = Fabricate.build(:category, name: "More Cats", slug: "cats") + c2.should_not be_valid + c2.errors[:slug].should be_present + end + end + describe 'description_text' do it 'correctly generates text description as needed' do c = Category.new @@ -284,6 +298,16 @@ describe Category do end end + describe "update" do + it "should enforce uniqueness of slug" do + Fabricate(:category, slug: "the-slug") + c2 = Fabricate(:category, slug: "different-slug") + c2.slug = "the-slug" + c2.should_not be_valid + c2.errors[:slug].should be_present + end + end + describe 'destroy' do before do @category = Fabricate(:category)