From 5451b3b986d042c303e35db730682cbfcf09ab18 Mon Sep 17 00:00:00 2001 From: AntonioTerceiro Date: Sat, 21 Jun 2008 02:35:22 +0000 Subject: [PATCH] ActionItem466: changing article categorization --- app/models/article.rb | 30 +++++++++++++++++++++++++++++- app/models/article_categorization.rb | 16 ++++++++++++++++ db/migrate/043_add_virtual_flag_to_categorizations.rb | 11 +++++++++++ db/schema.rb | 4 +++- test/functional/cms_controller_test.rb | 2 +- test/unit/article_categorization_test.rb | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/unit/article_test.rb | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 db/migrate/043_add_virtual_flag_to_categorizations.rb diff --git a/app/models/article.rb b/app/models/article.rb index b4d1bef..2e6b199 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -12,7 +12,35 @@ class Article < ActiveRecord::Base has_many :comments, :dependent => :destroy - has_and_belongs_to_many :categories + has_many :article_categorizations, :conditions => { :virtual => false } + has_many :categories, :through => :article_categorizations + + def pending_categorizations + @pending_categorizations ||= [] + end + + def add_category(c) + if self.id + ArticleCategorization.create!(:category => c, :article => self) + else + pending_categorizations << c + end + end + + def category_ids=(ids) + ArticleCategorization.remove_all_for(self) + ids.each do |item| + add_category(Category.find(item)) + end + end + + after_create :create_pending_categorizations + def create_pending_categorizations + pending_categorizations.each do |item| + ArticleCategorization.create!(:category => item, :article => self) + end + pending_categorizations.clear + end acts_as_taggable N_('Tag list') diff --git a/app/models/article_categorization.rb b/app/models/article_categorization.rb index 8a7f517..6fcbfd2 100644 --- a/app/models/article_categorization.rb +++ b/app/models/article_categorization.rb @@ -2,4 +2,20 @@ class ArticleCategorization < ActiveRecord::Base set_table_name :articles_categories belongs_to :article belongs_to :category + + after_create :associate_with_entire_hierarchy + def associate_with_entire_hierarchy + return if virtual + + c = category.parent + while !c.nil? && !self.class.find(:first, :conditions => {:article_id => article, :category_id => c}) + self.class.create!(:article => article, :category => c, :virtual => true) + c = c.parent + end + end + + def self.remove_all_for(article) + self.delete_all(:article_id => article.id) + end + end diff --git a/db/migrate/043_add_virtual_flag_to_categorizations.rb b/db/migrate/043_add_virtual_flag_to_categorizations.rb new file mode 100644 index 0000000..9835e22 --- /dev/null +++ b/db/migrate/043_add_virtual_flag_to_categorizations.rb @@ -0,0 +1,11 @@ +class AddVirtualFlagToCategorizations < ActiveRecord::Migration + def self.up + add_column :articles_categories, :virtual, :boolean, :default => false + add_column :categories_profiles, :virtual, :boolean, :default => false + end + + def self.down + remove_column :articles_categories, :virtual + remove_column :categories_profiles, :virtual + end +end diff --git a/db/schema.rb b/db/schema.rb index de9e0b3..2f5e80a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 42) do +ActiveRecord::Schema.define(:version => 43) do create_table "article_versions", :force => true do |t| t.integer "article_id" @@ -68,6 +68,7 @@ ActiveRecord::Schema.define(:version => 42) do create_table "articles_categories", :id => false, :force => true do |t| t.integer "article_id" t.integer "category_id" + t.boolean "virtual", :default => false end add_index "articles_categories", ["category_id"], :name => "index_articles_categories_on_category_id" @@ -104,6 +105,7 @@ ActiveRecord::Schema.define(:version => 42) do create_table "categories_profiles", :id => false, :force => true do |t| t.integer "profile_id" t.integer "category_id" + t.boolean "virtual", :default => false end create_table "comments", :force => true do |t| diff --git a/test/functional/cms_controller_test.rb b/test/functional/cms_controller_test.rb index 1fd358a..f3e3355 100644 --- a/test/functional/cms_controller_test.rb +++ b/test/functional/cms_controller_test.rb @@ -281,7 +281,7 @@ class CmsControllerTest < Test::Unit::TestCase # post is in c1 and c3 post :new, :type => TextileArticle.name, :profile => profile.identifier, :article => { :name => 'adding-categories-test', :category_ids => [ c1.id, c3.id] } - saved = TextileArticle.find_by_name('adding-categories-test') + saved = profile.articles.find_by_name('adding-categories-test') assert_includes saved.categories, c1 assert_not_includes saved.categories, c2 assert_includes saved.categories, c3 diff --git a/test/unit/article_categorization_test.rb b/test/unit/article_categorization_test.rb index 1695d41..0367e65 100644 --- a/test/unit/article_categorization_test.rb +++ b/test/unit/article_categorization_test.rb @@ -17,4 +17,48 @@ class ArticleCategorizationTest < Test::Unit::TestCase assert_equal category, ArticleCategorization.new(:category => category).category end + should 'create instances for the entire hierarchy' do + c1 = Category.create!(:name => 'c1', :environment => Environment.default) + c2 = c1.children.create!(:name => 'c2', :environment => Environment.default) + + p = create_user('testuser').person + a = p.articles.create!(:name => 'test') + + assert_difference ArticleCategorization, :count, 2 do + ArticleCategorization.create!(:category => c2, :article => a) + end + + assert_equal 2, ArticleCategorization.find_all_by_article_id(a.id).size + end + + should 'not duplicate entry for category that is parent of two others' do + c1 = Category.create!(:name => 'c1', :environment => Environment.default) + c2 = c1.children.create!(:name => 'c2', :environment => Environment.default) + c3 = c1.children.create!(:name => 'c3', :environment => Environment.default) + + p = create_user('testuser').person + a = p.articles.create!(:name => 'test') + + assert_difference ArticleCategorization, :count, 3 do + ac = ArticleCategorization.create!(:category => c2, :article => a) + ac = ArticleCategorization.create!(:category => c3, :article => a) + end + end + + should 'remove all instances for a given article' do + c1 = Category.create!(:name => 'c1', :environment => Environment.default) + c2 = c1.children.create!(:name => 'c2', :environment => Environment.default) + c3 = c1.children.create!(:name => 'c3', :environment => Environment.default) + + p = create_user('testuser').person + a = p.articles.create!(:name => 'test') + + ac = ArticleCategorization.create!(:category => c2, :article => a) + ac = ArticleCategorization.create!(:category => c3, :article => a) + + assert_difference ArticleCategorization, :count, -3 do + ArticleCategorization.remove_all_for(a) + end + end + end diff --git a/test/unit/article_test.rb b/test/unit/article_test.rb index f5481b7..35f2c50 100644 --- a/test/unit/article_test.rb +++ b/test/unit/article_test.rb @@ -183,6 +183,8 @@ class ArticleTest < Test::Unit::TestCase article.categories << c1 article.categories << c2 end + + assert_equivalent [c1,c2], article.categories(true) end should 'remove comments when removing article' do @@ -324,4 +326,48 @@ class ArticleTest < Test::Unit::TestCase end + should 'categorize in the entire category hierarchy' do + c1 = Category.create!(:environment => Environment.default, :name => 'c1') + c2 = c1.children.create!(:environment => Environment.default, :name => 'c2') + c3 = c2.children.create!(:environment => Environment.default, :name => 'c3') + + owner = create_user('testuser').person + art = owner.articles.create!(:name => 'ytest') + + art.add_category(c3) + + assert_equal [c3], art.categories(true) + assert_equal [art], c2.articles(true) + + assert_includes c3.articles(true), art + assert_includes c2.articles(true), art + assert_includes c1.articles(true), art + end + + should 'redefine the entire category set at once' do + c1 = Category.create!(:environment => Environment.default, :name => 'c1') + c2 = c1.children.create!(:environment => Environment.default, :name => 'c2') + c3 = c2.children.create!(:environment => Environment.default, :name => 'c3') + c4 = c1.children.create!(:environment => Environment.default, :name => 'c4') + owner = create_user('testuser').person + art = owner.articles.create!(:name => 'ytest') + + art.add_category(c4) + + art.category_ids = [c2,c3].map(&:id) + + assert_equivalent [c2, c3], art.categories(true) + end + + should 'be able to create an article already with categories' do + c1 = Category.create!(:environment => Environment.default, :name => 'c1') + c2 = Category.create!(:environment => Environment.default, :name => 'c2') + + p = create_user('testinguser').person + a = p.articles.create!(:name => 'test', :category_ids => [c1.id, c2.id]) + + assert_equivalent [c1, c2], a.categories(true) + + end + end -- libgit2 0.21.2