crowdint_acts-as-taggable-on 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +35 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +5 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.rdoc +250 -0
  9. data/Rakefile +13 -0
  10. data/acts-as-taggable-on.gemspec +28 -0
  11. data/lib/acts-as-taggable-on.rb +59 -0
  12. data/lib/acts-as-taggable-on/version.rb +4 -0
  13. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +53 -0
  14. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +127 -0
  15. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +349 -0
  16. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  17. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +99 -0
  18. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +73 -0
  19. data/lib/acts_as_taggable_on/tag.rb +77 -0
  20. data/lib/acts_as_taggable_on/tag_list.rb +97 -0
  21. data/lib/acts_as_taggable_on/taggable.rb +102 -0
  22. data/lib/acts_as_taggable_on/tagger.rb +67 -0
  23. data/lib/acts_as_taggable_on/tagging.rb +34 -0
  24. data/lib/acts_as_taggable_on/tags_helper.rb +17 -0
  25. data/lib/acts_as_taggable_on/utils.rb +34 -0
  26. data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +39 -0
  27. data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +30 -0
  28. data/rails/init.rb +1 -0
  29. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +514 -0
  30. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +114 -0
  31. data/spec/acts_as_taggable_on/tag_list_spec.rb +93 -0
  32. data/spec/acts_as_taggable_on/tag_spec.rb +153 -0
  33. data/spec/acts_as_taggable_on/taggable_spec.rb +543 -0
  34. data/spec/acts_as_taggable_on/tagger_spec.rb +112 -0
  35. data/spec/acts_as_taggable_on/tagging_spec.rb +28 -0
  36. data/spec/acts_as_taggable_on/tags_helper_spec.rb +44 -0
  37. data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
  38. data/spec/bm.rb +52 -0
  39. data/spec/database.yml.sample +19 -0
  40. data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
  41. data/spec/models.rb +49 -0
  42. data/spec/schema.rb +61 -0
  43. data/spec/spec_helper.rb +83 -0
  44. data/uninstall.rb +1 -0
  45. metadata +240 -0
@@ -0,0 +1,112 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Tagger" do
4
+ before(:each) do
5
+ clean_database!
6
+ @user = TaggableUser.create
7
+ @taggable = TaggableModel.create(:name => "Bob Jones")
8
+ end
9
+
10
+ it "should have taggings" do
11
+ @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
12
+ @user.owned_taggings.size == 2
13
+ end
14
+
15
+ it "should have tags" do
16
+ @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
17
+ @user.owned_tags.size == 2
18
+ end
19
+
20
+ it "should scope objects returned by tagged_with by owners" do
21
+ @taggable2 = TaggableModel.create(:name => "Jim Jones")
22
+ @taggable3 = TaggableModel.create(:name => "Jane Doe")
23
+
24
+ @user2 = TaggableUser.new
25
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
26
+ @user2.tag(@taggable2, :with => 'ruby, scheme', :on => :tags)
27
+ @user2.tag(@taggable3, :with => 'ruby, scheme', :on => :tags)
28
+
29
+ TaggableModel.tagged_with(%w(ruby scheme), :owned_by => @user).count.should == 1
30
+ TaggableModel.tagged_with(%w(ruby scheme), :owned_by => @user2).count.should == 2
31
+
32
+ end
33
+
34
+ it "should not overlap tags from different taggers" do
35
+ @user2 = TaggableUser.new
36
+ lambda{
37
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
38
+ @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
39
+ }.should change(ActsAsTaggableOn::Tagging, :count).by(6)
40
+
41
+ [@user, @user2, @taggable].each(&:reload)
42
+
43
+ @user.owned_tags.map(&:name).sort.should == %w(ruby scheme).sort
44
+ @user2.owned_tags.map(&:name).sort.should == %w(java python lisp ruby).sort
45
+
46
+ @taggable.tags_from(@user).sort.should == %w(ruby scheme).sort
47
+ @taggable.tags_from(@user2).sort.should == %w(java lisp python ruby).sort
48
+
49
+ @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
50
+ @taggable.all_tags_on(:tags).size.should == 5
51
+ end
52
+
53
+ it "should not lose tags from different taggers" do
54
+ @user2 = TaggableUser.create
55
+ @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
56
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
57
+
58
+ lambda {
59
+ @user2.tag(@taggable, :with => 'java, python, lisp', :on => :tags)
60
+ }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
61
+
62
+ [@user, @user2, @taggable].each(&:reload)
63
+
64
+ @taggable.tags_from(@user).sort.should == %w(ruby scheme).sort
65
+ @taggable.tags_from(@user2).sort.should == %w(java python lisp).sort
66
+
67
+ @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
68
+ @taggable.all_tags_on(:tags).length.should == 5
69
+ end
70
+
71
+ it "should not lose tags" do
72
+ @user2 = TaggableUser.create
73
+
74
+ @user.tag(@taggable, :with => 'awesome', :on => :tags)
75
+ @user2.tag(@taggable, :with => 'awesome, epic', :on => :tags)
76
+
77
+ lambda {
78
+ @user2.tag(@taggable, :with => 'epic', :on => :tags)
79
+ }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
80
+
81
+ @taggable.reload
82
+ @taggable.all_tags_list.should include('awesome')
83
+ @taggable.all_tags_list.should include('epic')
84
+ end
85
+
86
+ it "should not lose tags" do
87
+ @taggable.update_attributes(:tag_list => 'ruby')
88
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
89
+
90
+ [@taggable, @user].each(&:reload)
91
+ @taggable.tag_list.should == %w(ruby)
92
+ @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
93
+
94
+ lambda {
95
+ @taggable.update_attributes(:tag_list => "")
96
+ }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
97
+
98
+ @taggable.tag_list.should == []
99
+ @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
100
+ end
101
+
102
+ it "is tagger" do
103
+ @user.is_tagger?.should(be_true)
104
+ end
105
+
106
+ it "should skip save if skip_save is passed as option" do
107
+ lambda {
108
+ @user.tag(@taggable, :with => 'epic', :on => :tags, :skip_save => true)
109
+ }.should_not change(ActsAsTaggableOn::Tagging, :count)
110
+
111
+ end
112
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ActsAsTaggableOn::Tagging do
4
+ before(:each) do
5
+ clean_database!
6
+ @tagging = ActsAsTaggableOn::Tagging.new
7
+ end
8
+
9
+ it "should not be valid with a invalid tag" do
10
+ @tagging.taggable = TaggableModel.create(:name => "Bob Jones")
11
+ @tagging.tag = ActsAsTaggableOn::Tag.new(:name => "")
12
+ @tagging.context = "tags"
13
+
14
+ @tagging.should_not be_valid
15
+
16
+ @tagging.errors[:tag_id].should == ["can't be blank"]
17
+ end
18
+
19
+ it "should not create duplicate taggings" do
20
+ @taggable = TaggableModel.create(:name => "Bob Jones")
21
+ @tag = ActsAsTaggableOn::Tag.create(:name => "awesome")
22
+
23
+ lambda {
24
+ 2.times { ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags') }
25
+ }.should change(ActsAsTaggableOn::Tagging, :count).by(1)
26
+ end
27
+
28
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ActsAsTaggableOn::TagsHelper do
4
+ before(:each) do
5
+ clean_database!
6
+
7
+ @bob = TaggableModel.create(:name => "Bob Jones", :language_list => "ruby, php")
8
+ @tom = TaggableModel.create(:name => "Tom Marley", :language_list => "ruby, java")
9
+ @eve = TaggableModel.create(:name => "Eve Nodd", :language_list => "ruby, c++")
10
+
11
+ @helper = class Helper
12
+ include ActsAsTaggableOn::TagsHelper
13
+ end.new
14
+ end
15
+
16
+ it "should yield the proper css classes" do
17
+ tags = { }
18
+
19
+ @helper.tag_cloud(TaggableModel.tag_counts_on(:languages), ["sucky", "awesome"]) do |tag, css_class|
20
+ tags[tag.name] = css_class
21
+ end
22
+
23
+ tags["ruby"].should == "awesome"
24
+ tags["java"].should == "sucky"
25
+ tags["c++"].should == "sucky"
26
+ tags["php"].should == "sucky"
27
+ end
28
+
29
+ it "should handle tags with zero counts (build for empty)" do
30
+ bob = ActsAsTaggableOn::Tag.create(:name => "php")
31
+ tom = ActsAsTaggableOn::Tag.create(:name => "java")
32
+ eve = ActsAsTaggableOn::Tag.create(:name => "c++")
33
+
34
+ tags = { }
35
+
36
+ @helper.tag_cloud(ActsAsTaggableOn::Tag.all, ["sucky", "awesome"]) do |tag, css_class|
37
+ tags[tag.name] = css_class
38
+ end
39
+
40
+ tags["java"].should == "sucky"
41
+ tags["c++"].should == "sucky"
42
+ tags["php"].should == "sucky"
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ActsAsTaggableOn::Utils do
4
+ describe "like_operator" do
5
+ before(:each) do
6
+ clean_database!
7
+ TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
8
+ @taggable = TaggableModel.new(:name => "Bob Jones")
9
+ end
10
+
11
+ it "should return 'ILIKE' when the adapter is PostgreSQL" do
12
+ TaggableModel.connection.stub(:adapter_name).and_return("PostgreSQL")
13
+ TaggableModel.send(:like_operator).should == "ILIKE"
14
+ end
15
+
16
+ it "should return 'LIKE' when the adapter is not PostgreSQL" do
17
+ TaggableModel.connection.stub(:adapter_name).and_return("MySQL")
18
+ TaggableModel.send(:like_operator).should == "LIKE"
19
+ end
20
+ end
21
+ end
data/spec/bm.rb ADDED
@@ -0,0 +1,52 @@
1
+ require 'active_record'
2
+ require 'action_view'
3
+ require File.expand_path('../../lib/acts-as-taggable-on', __FILE__)
4
+
5
+ if defined?(ActiveRecord::Acts::TaggableOn)
6
+ ActiveRecord::Base.send :include, ActiveRecord::Acts::TaggableOn
7
+ ActiveRecord::Base.send :include, ActiveRecord::Acts::Tagger
8
+ ActionView::Base.send :include, TagsHelper if defined?(ActionView::Base)
9
+ end
10
+
11
+ TEST_DATABASE_FILE = File.join(File.dirname(__FILE__), '..', 'test.sqlite3')
12
+ File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
13
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => TEST_DATABASE_FILE
14
+
15
+ ActiveRecord::Base.silence do
16
+ ActiveRecord::Migration.verbose = false
17
+ ActiveRecord::Schema.define :version => 0 do
18
+ create_table "taggings", :force => true do |t|
19
+ t.integer "tag_id", :limit => 11
20
+ t.integer "taggable_id", :limit => 11
21
+ t.string "taggable_type"
22
+ t.string "context"
23
+ t.datetime "created_at"
24
+ t.integer "tagger_id", :limit => 11
25
+ t.string "tagger_type"
26
+ end
27
+
28
+ add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
29
+ add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
30
+
31
+ create_table "tags", :force => true do |t|
32
+ t.string "name"
33
+ end
34
+
35
+ create_table :taggable_models, :force => true do |t|
36
+ t.column :name, :string
37
+ t.column :type, :string
38
+ t.column :cached_tag_list, :string
39
+ end
40
+ end
41
+
42
+ class TaggableModel < ActiveRecord::Base
43
+ acts_as_taggable
44
+ acts_as_taggable_on :languages
45
+ acts_as_taggable_on :skills
46
+ acts_as_taggable_on :needs, :offerings
47
+ end
48
+ end
49
+
50
+ puts Benchmark.measure {
51
+ 1000.times { TaggableModel.create :tag_list => "awesome, epic, neat" }
52
+ }
@@ -0,0 +1,19 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: acts_as_taggable_on.sqlite3
4
+
5
+ mysql:
6
+ adapter: mysql2
7
+ hostname: localhost
8
+ username: root
9
+ password:
10
+ database: acts_as_taggable_on
11
+ charset: utf8
12
+
13
+ postgresql:
14
+ adapter: postgresql
15
+ hostname: localhost
16
+ username: postgres
17
+ password:
18
+ database: acts_as_taggable_on
19
+ encoding: utf8
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ # Generators are not automatically loaded by Rails
4
+ require 'generators/acts_as_taggable_on/migration/migration_generator'
5
+
6
+ describe ActsAsTaggableOn::MigrationGenerator do
7
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
8
+ destination File.expand_path("../../../../../tmp", __FILE__)
9
+
10
+ before do
11
+ prepare_destination
12
+ Rails::Generators.options[:rails][:orm] = :active_record
13
+ end
14
+ describe 'no arguments' do
15
+ before { run_generator }
16
+
17
+ describe 'db/migrate/acts_as_taggable_on_migration.rb' do
18
+ subject { file('db/migrate/acts_as_taggable_on_migration.rb') }
19
+ it { should be_a_migration }
20
+ end
21
+ end
22
+ end
data/spec/models.rb ADDED
@@ -0,0 +1,49 @@
1
+ class TaggableModel < ActiveRecord::Base
2
+ acts_as_taggable
3
+ acts_as_taggable_on :languages
4
+ acts_as_taggable_on :skills
5
+ acts_as_taggable_on :needs, :offerings
6
+ has_many :untaggable_models
7
+ end
8
+
9
+ class CachedModel < ActiveRecord::Base
10
+ acts_as_taggable
11
+ end
12
+
13
+ class OtherCachedModel < ActiveRecord::Base
14
+ acts_as_taggable_on :languages, :statuses, :glasses
15
+ end
16
+
17
+ class OtherTaggableModel < ActiveRecord::Base
18
+ acts_as_taggable_on :tags, :languages
19
+ acts_as_taggable_on :needs, :offerings
20
+ end
21
+
22
+ class InheritingTaggableModel < TaggableModel
23
+ end
24
+
25
+ class AlteredInheritingTaggableModel < TaggableModel
26
+ acts_as_taggable_on :parts
27
+ end
28
+
29
+ class TaggableUser < ActiveRecord::Base
30
+ acts_as_tagger
31
+ end
32
+
33
+ class UntaggableModel < ActiveRecord::Base
34
+ belongs_to :taggable_model
35
+ end
36
+
37
+ class NonStandardIdTaggableModel < ActiveRecord::Base
38
+ set_primary_key "an_id"
39
+ acts_as_taggable
40
+ acts_as_taggable_on :languages
41
+ acts_as_taggable_on :skills
42
+ acts_as_taggable_on :needs, :offerings
43
+ has_many :untaggable_models
44
+ end
45
+
46
+ class OrderedTaggableModel < ActiveRecord::Base
47
+ acts_as_ordered_taggable
48
+ acts_as_ordered_taggable_on :colours
49
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,61 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+ create_table "taggings", :force => true do |t|
3
+ t.integer "tag_id", :limit => 11
4
+ t.integer "taggable_id", :limit => 11
5
+ t.string "taggable_type"
6
+ t.string "context"
7
+ t.datetime "created_at"
8
+ t.integer "tagger_id", :limit => 11
9
+ t.string "tagger_type"
10
+ end
11
+
12
+ add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
13
+ add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
14
+
15
+ create_table "tags", :force => true do |t|
16
+ t.string "name"
17
+ end
18
+
19
+ create_table :taggable_models, :force => true do |t|
20
+ t.column :name, :string
21
+ t.column :type, :string
22
+ end
23
+
24
+ create_table :non_standard_id_taggable_models, :primary_key => "an_id", :force => true do |t|
25
+ t.column :name, :string
26
+ t.column :type, :string
27
+ end
28
+
29
+ create_table :untaggable_models, :force => true do |t|
30
+ t.column :taggable_model_id, :integer
31
+ t.column :name, :string
32
+ end
33
+
34
+ create_table :cached_models, :force => true do |t|
35
+ t.column :name, :string
36
+ t.column :type, :string
37
+ t.column :cached_tag_list, :string
38
+ end
39
+
40
+ create_table :other_cached_models, :force => true do |t|
41
+ t.column :name, :string
42
+ t.column :type, :string
43
+ t.column :cached_language_list, :string
44
+ t.column :cached_status_list, :string
45
+ t.column :cached_glass_list, :string
46
+ end
47
+
48
+ create_table :taggable_users, :force => true do |t|
49
+ t.column :name, :string
50
+ end
51
+
52
+ create_table :other_taggable_models, :force => true do |t|
53
+ t.column :name, :string
54
+ t.column :type, :string
55
+ end
56
+
57
+ create_table :ordered_taggable_models, :force => true do |t|
58
+ t.column :name, :string
59
+ t.column :type, :string
60
+ end
61
+ end
@@ -0,0 +1,83 @@
1
+ $LOAD_PATH << "." unless $LOAD_PATH.include?(".")
2
+ require 'logger'
3
+
4
+ begin
5
+ require "rubygems"
6
+ require "bundler"
7
+
8
+ if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5")
9
+ raise RuntimeError, "Your bundler version is too old." +
10
+ "Run `gem install bundler` to upgrade."
11
+ end
12
+
13
+ # Set up load paths for all bundled gems
14
+ Bundler.setup
15
+ rescue Bundler::GemNotFound
16
+ raise RuntimeError, "Bundler couldn't find some gems." +
17
+ "Did you run \`bundlee install\`?"
18
+ end
19
+
20
+ Bundler.require
21
+ require File.expand_path('../../lib/acts-as-taggable-on', __FILE__)
22
+ require 'ammeter/init'
23
+
24
+ unless [].respond_to?(:freq)
25
+ class Array
26
+ def freq
27
+ k=Hash.new(0)
28
+ each {|e| k[e]+=1}
29
+ k
30
+ end
31
+ end
32
+ end
33
+
34
+ # set adapter to use, default is sqlite3
35
+ # to use an alternative adapter run => rake spec DB='postgresql'
36
+ db_name = ENV['DB'] || 'sqlite3'
37
+ database_yml = File.expand_path('../database.yml', __FILE__)
38
+
39
+ if File.exists?(database_yml)
40
+ active_record_configuration = YAML.load_file(database_yml)
41
+
42
+ ActiveRecord::Base.configurations = active_record_configuration
43
+ config = ActiveRecord::Base.configurations[db_name]
44
+
45
+ begin
46
+ ActiveRecord::Base.establish_connection(db_name)
47
+ ActiveRecord::Base.connection
48
+ rescue
49
+ case db_name
50
+ when /mysql/
51
+ ActiveRecord::Base.establish_connection(config.merge('database' => nil))
52
+ ActiveRecord::Base.connection.create_database(config['database'], {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
53
+ when 'postgresql'
54
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
55
+ ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8'))
56
+ end
57
+
58
+ ActiveRecord::Base.establish_connection(config)
59
+ end
60
+
61
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
62
+ ActiveRecord::Base.default_timezone = :utc
63
+
64
+ ActiveRecord::Base.silence do
65
+ ActiveRecord::Migration.verbose = false
66
+
67
+ load(File.dirname(__FILE__) + '/schema.rb')
68
+ load(File.dirname(__FILE__) + '/models.rb')
69
+ end
70
+
71
+ else
72
+ raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample"
73
+ end
74
+
75
+ def clean_database!
76
+ models = [ActsAsTaggableOn::Tag, ActsAsTaggableOn::Tagging, TaggableModel, OtherTaggableModel, InheritingTaggableModel,
77
+ AlteredInheritingTaggableModel, TaggableUser, UntaggableModel, OrderedTaggableModel]
78
+ models.each do |model|
79
+ ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
80
+ end
81
+ end
82
+
83
+ clean_database!