tagged 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.swp
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |g|
9
+ g.name = 'tagged'
10
+ g.summary = %(Simple ORM agnostic tagging.)
11
+ g.description = %(Simple ORM agnostic tagging.)
12
+ g.email = 'matt@toastyapps.com'
13
+ g.homepage = 'http://github.com/toastyapps/tagged'
14
+ g.authors = %w(toastyapps)
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts 'Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com'
19
+ end
20
+
21
+ Rake::TestTask.new do |t|
22
+ t.libs = %w(test)
23
+ t.pattern = 'test/**/*_test.rb'
24
+ end
25
+
26
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,11 @@
1
+ class VestalVersionsMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate'
5
+ end
6
+ end
7
+
8
+ def file_name
9
+ 'create_tagged'
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ class CreateTagged < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :taggings do |t|
4
+ t.belongs_to :tagged, :polymorphic => true
5
+ t.belongs_to :tag
6
+ t.datetime :created_at
7
+ end
8
+
9
+ create_table :tags do |t|
10
+ t.string :name
11
+ end
12
+
13
+ add_index :tags, :name
14
+ add_index :taggings, :tag_id
15
+ add_index :taggings, [:taggable_id, :taggable_type]
16
+
17
+ end
18
+
19
+ def self.down
20
+ drop_table :taggings
21
+ drop_table :tags
22
+ end
23
+ end
data/lib/tagged.rb ADDED
@@ -0,0 +1,57 @@
1
+ module Tagged
2
+
3
+ module Extension
4
+ def self.included(base)
5
+ base.class_eval do
6
+ def self.tagged
7
+ include Tagged::Base
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ module Base
14
+
15
+ def self.included(model)
16
+ model.class_eval do
17
+ def self.delimiter
18
+ @@delimiter ||= ','
19
+ end
20
+
21
+ def self.delimiter=(value)
22
+ @@delimiter = value
23
+ end
24
+ end
25
+ end
26
+
27
+ def delimiter
28
+ self.class.delimiter
29
+ end
30
+
31
+ def tag_list
32
+ self._tag_list
33
+ end
34
+
35
+ def tag_list=(list)
36
+ self._tag_list = Tagged::TagList.new(list.split(delimiter).map(&:strip))
37
+ end
38
+
39
+ def tag(list)
40
+ list.split(delimiter).map {|tag| self._tag_list << tag.strip }
41
+ end
42
+
43
+ def untag(items)
44
+ items.split(delimiter).map{|tag| self._tag_list.delete(tag.strip)}
45
+ end
46
+
47
+ def _tag_list
48
+ @tag_list ||= Tagged::TagList.new([], delimiter)
49
+ end
50
+ end
51
+ end
52
+
53
+ require 'tagged/tag'
54
+ require 'tagged/tag_list'
55
+ require 'tagged/adapters/abstract_adapter'
56
+
57
+
@@ -0,0 +1,4 @@
1
+ module Tagged
2
+ class AbstractAdapter
3
+ end
4
+ end
@@ -0,0 +1,35 @@
1
+ require 'tagged'
2
+
3
+ module Tagged
4
+
5
+ module ActiveRecordExtension
6
+ def self.included(base)
7
+ base.class_eval do
8
+ @@tagged_adapter = ActiveRecordAdapter.new
9
+ extend ClassMethods
10
+ include Tagged::Base
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def tagged
16
+ self.class_eval do
17
+ has_many :taggings, :as => :tagged, :dependent => :destroy
18
+ has_many :tags, :through => :taggings
19
+ after_save :save_tags
20
+ end
21
+ end
22
+ end
23
+
24
+ def save_tags
25
+ tag_list.each do |tag_name|
26
+ tags << ::Tag.find_or_initialize_by_name(tag_name)
27
+ end
28
+ end
29
+ end
30
+ class ActiveRecordAdapter < AbstractAdapter
31
+
32
+ end
33
+ end
34
+
35
+ ActiveRecord::Base.send(:include, Tagged::ActiveRecordExtension)
@@ -0,0 +1,32 @@
1
+ require 'tagged'
2
+
3
+ module Tagged
4
+
5
+ module MongoMapperExtension
6
+ def self.included(base)
7
+ base.class_eval do
8
+ @@tagged_adapter = MongoMapperAdapter.new
9
+ include Tagged::Base
10
+ end
11
+ end
12
+ end
13
+ class MongoMapperAdapter < AbstractAdapter
14
+
15
+ end
16
+ end
17
+
18
+ module MongoMapper
19
+ module Document
20
+ module ClassMethods
21
+ def tagged
22
+ include Tagged::MongoMapperExtension
23
+ key :tags, Array
24
+ before_save :save_tags
25
+ end
26
+ end
27
+
28
+ def save_tags
29
+ self.tags = self.tag_list
30
+ end
31
+ end
32
+ end
data/lib/tagged/tag.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Tagged
2
+ class Tag
3
+ attr_accessor :name, :kind
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ module Tagged
2
+ class TagList < Array
3
+ attr_accessor :tags, :delimiter
4
+ def initialize(*list)
5
+ self.delimiter = ','
6
+ if list[0].is_a?(Array)
7
+ self.delimiter = list[1]
8
+ list = list[0]
9
+ end
10
+ list = list.is_a?(Array) ? list : list.split(self.delimiter).collect(&:strip).reject(&:blank)
11
+ super(list)
12
+ end
13
+
14
+ def +(list)
15
+ Tagged::TagList.new(self.to_a + list, self.delimiter)
16
+ end
17
+
18
+ def to_s(delimiter = nil)
19
+ join(delimiter || self.delimiter)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+ module Tagged
2
+ class Tagging
3
+ end
4
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'tagged'
@@ -0,0 +1,55 @@
1
+ require 'test_helper'
2
+ require 'active_record'
3
+ require 'tagged/adapters/active_record_adapter'
4
+ require 'schema'
5
+
6
+
7
+ class ActiveRecordTest < Test::Unit::TestCase
8
+ context "A Tagged ActiveRecord class" do
9
+ should "respond to tagged class methods" do
10
+ [:delimiter, :delimiter=].each do |method|
11
+ assert Post.respond_to?(method)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "A Tagged ActiveRecord instance" do
17
+ setup do
18
+ @post = Post.new
19
+ end
20
+
21
+ should "respond to tagged instance methods" do
22
+ [:tag, :tag_list, :untag].each do |method|
23
+ assert @post.respond_to?(method)
24
+ end
25
+ end
26
+
27
+ should "respond to taggings" do
28
+ assert @post.respond_to?(:taggings)
29
+ end
30
+
31
+ should "have no tags to begin with" do
32
+ assert_equal [], @post.tag_list
33
+ end
34
+
35
+ should "be able to add a tag" do
36
+ @post.tag('foo')
37
+ assert_equal ['foo'], @post.tag_list
38
+ end
39
+
40
+ should "be able to remove a tag" do
41
+ @post.tag('foo')
42
+ @post.untag('foo')
43
+ assert_equal [], @post.tag_list
44
+ end
45
+
46
+ should "be able to save tags" do
47
+ @post.tag('foo,bar')
48
+ @post.save
49
+ assert_equal 2, Tag.count
50
+ assert_equal 2, Tagging.count
51
+ end
52
+
53
+ end
54
+ end
55
+
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class Bar
4
+ include Tagged::Base
5
+ end
6
+
7
+ class TaggingTest < Test::Unit::TestCase
8
+ context "A tagged instance with a custom delimiter" do
9
+ setup do
10
+ Bar.delimiter = '|'
11
+ @bar = Bar.new
12
+ @bar.tag('hoge|fuga|piyo')
13
+ end
14
+
15
+ should "respond with the correct tags" do
16
+ assert_equal ['hoge', 'fuga', 'piyo'], @bar.tag_list
17
+ end
18
+
19
+ should "be able to represent the tags as a string" do
20
+ assert_equal "hoge|fuga|piyo", @bar.tag_list.to_s
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ MongoMapper.connection = Mongo::Connection.new('127.0.0.1')
2
+ MongoMapper.database = "testing_tagged"
3
+
4
+ class Article
5
+ include MongoMapper::Document
6
+ key :title, String
7
+ tagged
8
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+ require 'mongo_mapper'
3
+ require 'tagged/adapters/mongo_mapper_adapter'
4
+ require 'mongo_mapper_schema'
5
+
6
+
7
+ class MongoMapperTest < Test::Unit::TestCase
8
+ context "A Tagged MongoMapper class" do
9
+ should "respond to tagged class methods" do
10
+ [:delimiter, :delimiter=].each do |method|
11
+ assert Article.respond_to?(method)
12
+ end
13
+ end
14
+ end
15
+
16
+ context "A Tagged MongoMapper instance" do
17
+ setup do
18
+ @article = Article.new
19
+ end
20
+
21
+ should "respond to tagged instance methods" do
22
+ [:tag, :tag_list, :untag].each do |method|
23
+ assert @article.respond_to?(method)
24
+ end
25
+ end
26
+
27
+ should "have no tags to begin with" do
28
+ assert_equal [], @article.tag_list
29
+ end
30
+
31
+ should "be able to add a tag" do
32
+ @article.tag('foo')
33
+ assert_equal ['foo'], @article.tag_list
34
+ end
35
+
36
+ should "be able to remove a tag" do
37
+ @article.tag('foo')
38
+ @article.untag('foo')
39
+ assert_equal [], @article.tag_list
40
+ end
41
+
42
+ should "be able to save tags" do
43
+ @article.tag('foo,bar')
44
+ @article.save
45
+ @find_article = Article.find(@article.id)
46
+ assert_equal ['foo', 'bar'], @find_article.tags
47
+ end
48
+
49
+ end
50
+ end
51
+
data/test/schema.rb ADDED
@@ -0,0 +1,38 @@
1
+ ActiveRecord::Base.configurations = {'sqlite3' => {:adapter => 'sqlite3', :database => ':memory:'}}
2
+ ActiveRecord::Base.establish_connection('sqlite3')
3
+ ActiveRecord::Base.logger = Logger.new(STDERR)
4
+ ActiveRecord::Base.logger.level = Logger::WARN
5
+
6
+ class CreateSchema < ActiveRecord::Migration
7
+ def self.up
8
+ create_table :taggings do |t|
9
+ t.belongs_to :tagged, :polymorphic => true
10
+ t.belongs_to :tag
11
+ t.datetime :created_at
12
+ end
13
+
14
+ create_table :tags do |t|
15
+ t.string :name
16
+ end
17
+ create_table :posts do |t|
18
+ t.string :title, :default => ''
19
+ end
20
+ end
21
+ end
22
+
23
+ CreateSchema.suppress_messages do
24
+ CreateSchema.migrate(:up)
25
+ end
26
+
27
+ class Tagging < ActiveRecord::Base
28
+ belongs_to :tag
29
+ belongs_to :tagged, :polymorphic => true
30
+ end
31
+
32
+ class Post < ActiveRecord::Base
33
+ tagged
34
+ end
35
+
36
+ class Tag < ActiveRecord::Base
37
+ has_many :taggings, :dependent => :destroy
38
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class TaggingTest < Test::Unit::TestCase
4
+ context "A tag_list" do
5
+ setup do
6
+ @list = Tagged::TagList.new
7
+ end
8
+
9
+ should 'be able to add tags with tags#+=' do
10
+ tags = ['foo', 'bar']
11
+ @list += tags
12
+ assert_equal tags, @list
13
+ end
14
+
15
+ should 'be able to add tags with <<' do
16
+ tags = ['foo', 'bar']
17
+ tags.each do |tag|
18
+ @list << tag
19
+ end
20
+ assert_equal tags, @list
21
+ end
22
+
23
+ should 'be able to represent the tags in a string' do
24
+ tags = ['foo', 'bar']
25
+ @list += tags
26
+ assert_equal "foo,bar", @list.to_s
27
+ end
28
+
29
+ should 'be able to remove tags' do
30
+ tags = ['foo', 'bar']
31
+ @list += tags
32
+ @list.delete('foo')
33
+ assert_equal ['bar'], @list
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ class Foo
4
+ include Tagged::Base
5
+ end
6
+
7
+ class TaggingTest < Test::Unit::TestCase
8
+ context "A tagged instance" do
9
+ setup do
10
+ @foo = Foo.new
11
+ @foo.tag("hoge, fuga, piyo")
12
+ end
13
+
14
+ should "respond with the correct tags" do
15
+ assert_equal ['hoge', 'fuga', 'piyo'], @foo.tag_list
16
+ end
17
+
18
+ should "be able to add tags" do
19
+ @foo.tag('osake')
20
+ assert_equal ['hoge', 'fuga', 'piyo', 'osake'], @foo.tag_list
21
+ end
22
+
23
+ should "be able to remove a tag" do
24
+ @foo.untag('fuga')
25
+ assert_equal ['hoge', 'piyo'], @foo.tag_list
26
+ end
27
+
28
+ should "be able to remove multiple tags" do
29
+ @foo.untag('hoge, fuga')
30
+ assert_equal ['piyo'], @foo.tag_list
31
+ end
32
+
33
+ should "be able to represent the tags as a string" do
34
+ assert_equal "hoge,fuga,piyo", @foo.tag_list.to_s
35
+ end
36
+
37
+ should "be able to represent the tags as a custom string" do
38
+ assert_equal "hoge, fuga, piyo", @foo.tag_list.to_s(', ')
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ $: << File.dirname(__FILE__)
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'tagged'
6
+ require 'shoulda'
7
+
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tagged
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - toastyapps
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-21 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simple ORM agnostic tagging.
17
+ email: matt@toastyapps.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - .gitignore
26
+ - Rakefile
27
+ - VERSION
28
+ - generators/tagged_migration/tagged_migration_generator.rb
29
+ - generators/tagged_migration/templates/migration.rb
30
+ - lib/tagged.rb
31
+ - lib/tagged/adapters/abstract_adapter.rb
32
+ - lib/tagged/adapters/active_record_adapter.rb
33
+ - lib/tagged/adapters/mongo_mapper_adapter.rb
34
+ - lib/tagged/tag.rb
35
+ - lib/tagged/tag_list.rb
36
+ - lib/tagged/tagging.rb
37
+ - rails/init.rb
38
+ - test/active_record_test.rb
39
+ - test/delimiter_test.rb
40
+ - test/mongo_mapper_schema.rb
41
+ - test/mongo_mapper_test.rb
42
+ - test/schema.rb
43
+ - test/tag_list_test.rb
44
+ - test/tagging_test.rb
45
+ - test/test_helper.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/toastyapps/tagged
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Simple ORM agnostic tagging.
74
+ test_files:
75
+ - test/active_record_test.rb
76
+ - test/delimiter_test.rb
77
+ - test/mongo_mapper_schema.rb
78
+ - test/mongo_mapper_test.rb
79
+ - test/schema.rb
80
+ - test/tag_list_test.rb
81
+ - test/tagging_test.rb
82
+ - test/test_helper.rb