has_machine_tags 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +5 -0
- data/LICENSE.txt +1 -1
- data/README.rdoc +1 -0
- data/Rakefile +24 -39
- data/gemspec +18 -0
- data/init.rb +13 -1
- data/lib/has_machine_tags/console.rb +0 -9
- data/lib/has_machine_tags/tag_console.rb +10 -13
- data/lib/has_machine_tags/tag_list.rb +4 -0
- data/lib/has_machine_tags/version.rb +3 -0
- data/lib/has_machine_tags.rb +4 -7
- data/test/finder_test.rb +22 -24
- data/test/has_machine_tags_test.rb +17 -17
- data/test/tag_methods_test.rb +30 -30
- data/test/test_helper.rb +6 -6
- metadata +49 -31
- data/VERSION.yml +0 -4
- data/rails/init.rb +0 -13
data/CHANGELOG.rdoc
CHANGED
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -13,6 +13,7 @@ machine tags ripe for modeling relationships between objects. Read the HasMachin
|
|
13
13
|
documentation for a more thorough explanation.
|
14
14
|
|
15
15
|
A demo app using this plugin is {here}[http://github.com/cldwalker/tag-tree].
|
16
|
+
This gem should run on all major Ruby versions and work with Rails 2.3.x and up.
|
16
17
|
|
17
18
|
== Install
|
18
19
|
|
data/Rakefile
CHANGED
@@ -1,50 +1,35 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require '
|
3
|
-
require 'rake/rdoctask'
|
4
|
-
begin
|
5
|
-
require 'rcov/rcovtask'
|
2
|
+
require 'fileutils'
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
t.test_files = FileList['test/**/*_test.rb']
|
10
|
-
t.rcov_opts = ["-T -x '/Library/Ruby/*'"]
|
11
|
-
t.verbose = true
|
12
|
-
end
|
13
|
-
rescue LoadError
|
14
|
-
puts "Rcov not available. Install it for rcov-related tasks with: sudo gem install rcov"
|
4
|
+
def gemspec
|
5
|
+
@gemspec ||= eval(File.read('gemspec'), binding, 'gemspec')
|
15
6
|
end
|
16
7
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
29
|
-
s.files = FileList["CHANGELOG.rdoc", "README.rdoc", "LICENSE.txt", "init.rb", "Rakefile", "VERSION.yml", "{rails,generators,bin,lib,test}/**/*"]
|
30
|
-
end
|
8
|
+
desc "Build the gem"
|
9
|
+
task :gem=>:gemspec do
|
10
|
+
sh "gem build gemspec"
|
11
|
+
FileUtils.mkdir_p 'pkg'
|
12
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Install the gem locally"
|
16
|
+
task :install => :gem do
|
17
|
+
sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
|
18
|
+
end
|
31
19
|
|
32
|
-
|
33
|
-
|
20
|
+
desc "Generate the gemspec"
|
21
|
+
task :generate do
|
22
|
+
puts gemspec.to_ruby
|
34
23
|
end
|
35
24
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
t.verbose = false
|
25
|
+
desc "Validate the gemspec"
|
26
|
+
task :gemspec do
|
27
|
+
gemspec.validate
|
40
28
|
end
|
41
29
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
46
|
-
rdoc.rdoc_files.include('README*')
|
47
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
|
+
desc 'Run tests'
|
31
|
+
task :test do |t|
|
32
|
+
sh 'bacon -q -Ilib -I. test/*_test.rb'
|
48
33
|
end
|
49
34
|
|
50
|
-
task :default => :test
|
35
|
+
task :default => :test
|
data/gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'rubygems' unless Object.const_defined?(:Gem)
|
3
|
+
require File.dirname(__FILE__) + "/lib/has_machine_tags/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "has_machine_tags"
|
7
|
+
s.version = HasMachineTags::VERSION
|
8
|
+
s.authors = ["Gabriel Horner"]
|
9
|
+
s.email = "gabriel.horner@gmail.com"
|
10
|
+
s.homepage = "http://tagaholic.me/has_machine_tags/"
|
11
|
+
s.summary = "A rails tagging gem which implements flickr's machine tags and maybe more (semantic tags)."
|
12
|
+
s.description = "This gem implements Flickr's machine tags while still maintaining standard tagging behavior. This allows for more precise tagging as tags can have unlimited contexts provided by combinations of namespaces and predicates. These unlimited contexts also make machine tags ripe for modeling relationships between objects."
|
13
|
+
s.required_rubygems_version = ">= 1.3.6"
|
14
|
+
s.rubyforge_project = 'tagaholic'
|
15
|
+
s.add_development_dependency 'bacon'
|
16
|
+
s.files = Dir.glob(%w[{lib,test,generators}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c}]) + %w{Rakefile gemspec init.rb}
|
17
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
18
|
+
end
|
data/init.rb
CHANGED
@@ -1 +1,13 @@
|
|
1
|
-
require
|
1
|
+
require 'has_machine_tags'
|
2
|
+
require 'has_machine_tags/tag_methods'
|
3
|
+
|
4
|
+
#attempt to load constant
|
5
|
+
::Tag rescue nil
|
6
|
+
if Object.const_defined? :Tag
|
7
|
+
::Tag.class_eval %[include HasMachineTags::TagMethods]
|
8
|
+
else
|
9
|
+
require 'has_machine_tags/tag'
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'has_machine_tags/tagging'
|
13
|
+
ActiveRecord::Base.send :include, HasMachineTags
|
@@ -31,14 +31,5 @@ module HasMachineTags
|
|
31
31
|
self.tag_list
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
35
|
-
module ClassMethods
|
36
|
-
# Updates items tagged with an old tag to use the given new tag in place of the old tag.
|
37
|
-
def find_and_change_tag(old_tag, new_tag)
|
38
|
-
results = tagged_with(old_tag)
|
39
|
-
results.each {|e| e.tag_add_and_remove(old_tag, new_tag)}
|
40
|
-
puts "Changed tag for #{results.length} records"
|
41
|
-
end
|
42
|
-
end
|
43
34
|
end
|
44
35
|
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module HasMachineTags
|
2
|
-
|
3
|
-
|
2
|
+
# Provides named_scopes and class methods to the Tag model, useful in machine tag analysis from the console.
|
3
|
+
# To use:
|
4
|
+
# class Tag
|
5
|
+
# include HasMachineTags::TagConsole
|
6
|
+
# end
|
7
|
+
module TagConsole
|
8
|
+
def self.included(base) #:nodoc:
|
4
9
|
base.class_eval %[
|
5
10
|
named_scope :namespace_counts, :select=>'*, namespace as counter, count(namespace) as count', :group=>"namespace HAVING count(namespace)>=1"
|
6
11
|
named_scope :predicate_counts, :select=>'*, predicate as counter, count(predicate) as count', :group=>"predicate HAVING count(predicate)>=1"
|
@@ -13,20 +18,12 @@ module HasMachineTags
|
|
13
18
|
end
|
14
19
|
|
15
20
|
module ClassMethods
|
16
|
-
|
21
|
+
# Array of words in namespace field
|
17
22
|
def namespaces; distinct_namespaces.map(&:namespace).compact; end
|
23
|
+
# Array of words in predicate field
|
18
24
|
def predicates; distinct_predicates.map(&:predicate).compact; end
|
25
|
+
# Array of words in value field
|
19
26
|
def values; distinct_values.map(&:value).compact; end
|
20
|
-
#:startdoc:
|
21
|
-
|
22
|
-
# To be used with the *counts methods.
|
23
|
-
# For example:
|
24
|
-
# stat(:namespace_counts)
|
25
|
-
# This prints out pairs of a namespaces and their counts in the tags table.
|
26
|
-
def stat(type)
|
27
|
-
shortcuts = {:n=>:namespace_counts, :p=>:predicate_counts, :v=>:value_counts }
|
28
|
-
send(shortcuts[type] || type).map {|e| [e.counter, e.count] }
|
29
|
-
end
|
30
27
|
end
|
31
28
|
end
|
32
29
|
end
|
@@ -40,6 +40,10 @@ module HasMachineTags
|
|
40
40
|
}.flatten
|
41
41
|
end
|
42
42
|
|
43
|
+
def primary_namespace #:nodoc:
|
44
|
+
namespace_hashes.sort {|x,y| y[1].size <=> x[1].size }[0][0]
|
45
|
+
end
|
46
|
+
|
43
47
|
def namespace_hashes #:nodoc:
|
44
48
|
self.inject({}) {|h, e|
|
45
49
|
namespace, *predicate_value = Tag.split_machine_tag(e)
|
data/lib/has_machine_tags.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
current_dir = File.dirname(__FILE__)
|
2
|
-
$:.unshift(current_dir) unless $:.include?(current_dir) || $:.include?(File.expand_path(current_dir))
|
3
1
|
require 'has_machine_tags/finder'
|
4
2
|
require 'has_machine_tags/tag_list'
|
5
3
|
require 'has_machine_tags/console'
|
4
|
+
require 'has_machine_tags/version'
|
6
5
|
|
7
6
|
module HasMachineTags
|
8
7
|
def self.included(base) #:nodoc:
|
@@ -11,7 +10,7 @@ module HasMachineTags
|
|
11
10
|
|
12
11
|
module ClassMethods
|
13
12
|
# ==== Options:
|
14
|
-
# [:console] When true, adds additional
|
13
|
+
# [:console] When true, adds additional instance methods to use mainly in irb.
|
15
14
|
# [:reverse_has_many] Defines a has_many :through from tags to the model using the plural of the model name.
|
16
15
|
# [:quick_mode] When true, enables a quick mode to input machine tags with HasMachineTags::InstanceMethods.tag_list=(). See examples at HasMachineTags::TagList.new().
|
17
16
|
def has_machine_tags(options={})
|
@@ -24,10 +23,8 @@ module HasMachineTags
|
|
24
23
|
|
25
24
|
include HasMachineTags::InstanceMethods
|
26
25
|
extend HasMachineTags::Finder
|
27
|
-
if options[:console]
|
28
|
-
|
29
|
-
extend HasMachineTags::Console::ClassMethods
|
30
|
-
end
|
26
|
+
include HasMachineTags::Console::InstanceMethods if options[:console]
|
27
|
+
|
31
28
|
if respond_to?(:named_scope)
|
32
29
|
named_scope :tagged_with, lambda{ |*args|
|
33
30
|
find_options_for_tagged_with(*args)
|
data/test/finder_test.rb
CHANGED
@@ -1,80 +1,78 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
before
|
5
|
-
[Tag, Tagging, TaggableModel].each {|e| e.delete_all}
|
6
|
-
}
|
3
|
+
describe "Finder" do
|
4
|
+
before { [Tag, Tagging, TaggableModel].each {|e| e.delete_all} }
|
7
5
|
|
8
6
|
def create_extra_taggable
|
9
7
|
TaggableModel.create(:tag_list=>"blah:blih=bluh")
|
10
8
|
end
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
before
|
10
|
+
describe "TaggableModel" do
|
11
|
+
describe "finds by" do
|
12
|
+
before {
|
15
13
|
@taggable = TaggableModel.create(:tag_list=>"url:lang=ruby")
|
16
14
|
create_extra_taggable
|
17
15
|
}
|
18
16
|
|
19
|
-
|
17
|
+
it "namespace wildcard machine tag" do
|
20
18
|
TaggableModel.tagged_with("url:").should == [@taggable]
|
21
19
|
end
|
22
20
|
|
23
|
-
|
21
|
+
it "predicate wildcard machine tag" do
|
24
22
|
TaggableModel.tagged_with("lang=").should == [@taggable]
|
25
23
|
end
|
26
24
|
|
27
|
-
|
25
|
+
it "value wildcard machine tag" do
|
28
26
|
TaggableModel.tagged_with("=ruby").should == [@taggable]
|
29
27
|
end
|
30
28
|
|
31
|
-
|
29
|
+
it "namespace-value wildcard machine tag" do
|
32
30
|
TaggableModel.tagged_with("url.ruby").should == [@taggable]
|
33
31
|
end
|
34
32
|
|
35
|
-
|
33
|
+
it "predicate-value wildcard machine tag" do
|
36
34
|
TaggableModel.tagged_with("lang=ruby").should == [@taggable]
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
38
|
+
describe "finds with" do
|
39
|
+
it "multiple machine tags as an array" do
|
42
40
|
@taggable = TaggableModel.create(:tag_list=>"article:todo=later")
|
43
41
|
@taggable2 = TaggableModel.create(:tag_list=>"article:tags=funny")
|
44
42
|
create_extra_taggable
|
45
43
|
results = TaggableModel.tagged_with(["article:todo=later", "article:tags=funny"])
|
46
44
|
results.size.should == 2
|
47
|
-
results.include?(@taggable).should
|
48
|
-
results.include?(@taggable2).should
|
45
|
+
results.include?(@taggable).should == true
|
46
|
+
results.include?(@taggable2).should == true
|
49
47
|
end
|
50
48
|
|
51
|
-
|
49
|
+
it "multiple machine tags as a delimited string" do
|
52
50
|
@taggable = TaggableModel.create(:tag_list=>"article:todo=later")
|
53
51
|
@taggable2 = TaggableModel.create(:tag_list=>"article:tags=funny")
|
54
52
|
create_extra_taggable
|
55
53
|
results = TaggableModel.tagged_with("article:todo=later, article:tags=funny")
|
56
54
|
results.size.should == 2
|
57
|
-
results.include?(@taggable).should
|
58
|
-
results.include?(@taggable2).should
|
55
|
+
results.include?(@taggable).should == true
|
56
|
+
results.include?(@taggable2).should == true
|
59
57
|
end
|
60
58
|
|
61
|
-
|
59
|
+
it "condition option" do
|
62
60
|
@taggable = TaggableModel.create(:title=>"so limiting", :tag_list=>"url:tags=funny" )
|
63
61
|
create_extra_taggable
|
64
62
|
TaggableModel.tagged_with("url:tags=funny", :conditions=>"title = 'so limiting'").should == [@taggable]
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
68
|
-
|
69
|
-
before
|
70
|
-
|
66
|
+
describe "when queried with normal tag" do
|
67
|
+
before { @taggable = TaggableModel.new }
|
68
|
+
it "doesn't find if machine tagged" do
|
71
69
|
@taggable.tag_list = 'url:tags=square'
|
72
70
|
@taggable.save
|
73
71
|
Tag.count.should == 1
|
74
72
|
TaggableModel.tagged_with("square").should == []
|
75
73
|
end
|
76
74
|
|
77
|
-
|
75
|
+
it "finds if tagged normally" do
|
78
76
|
@taggable.tag_list = 'square, some:machine=tag'
|
79
77
|
@taggable.save
|
80
78
|
TaggableModel.tagged_with("square").should == [@taggable]
|
@@ -1,56 +1,56 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
before
|
3
|
+
describe "HasMachineTags" do
|
4
|
+
describe "TagList" do
|
5
|
+
before { @taggable = TaggableModel.new }
|
6
6
|
|
7
|
-
|
7
|
+
it "sets tag list with array" do
|
8
8
|
arr = ['some', 'tag:name=blah']
|
9
9
|
@taggable.tag_list = arr
|
10
10
|
@taggable.tag_list.should == arr
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
it "sets tag list with delimited string" do
|
14
14
|
arr = ['more', 'tag:type=clever']
|
15
15
|
@taggable.tag_list = arr.join(", ")
|
16
16
|
@taggable.tag_list.should == arr
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
it "sets tag list with messy delimited string" do
|
20
20
|
arr = ['more', 'tag:type=dumb', 'really']
|
21
21
|
@taggable.tag_list = "more,tag:type=dumb, really"
|
22
22
|
@taggable.tag_list.should == arr
|
23
23
|
@taggable.tag_list.to_s.should == arr.join(", ")
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
after(:all) { TaggableModel.quick_mode = false }
|
26
|
+
describe "with quick_mode" do
|
27
|
+
before_all { TaggableModel.quick_mode = true }
|
29
28
|
|
30
|
-
|
29
|
+
it "sets tag list normally with non quick_mode characters" do
|
31
30
|
arr = ['more', 'tag:type=dumb', 'really']
|
32
31
|
@taggable.tag_list = "more,tag:type=dumb, really"
|
33
32
|
@taggable.tag_list.should == arr
|
34
33
|
end
|
35
34
|
|
36
|
-
|
35
|
+
it "sets default predicate and infers namespace" do
|
37
36
|
@taggable.tag_list = "gem:irb;name=utility_belt, article"
|
38
37
|
@taggable.tag_list.should == ["gem:tags=irb", "gem:name=utility_belt", "article"]
|
39
38
|
end
|
39
|
+
after_all { TaggableModel.quick_mode = false }
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
before
|
43
|
+
describe "InstanceMethods" do
|
44
|
+
before { @taggable = TaggableModel.new }
|
45
45
|
|
46
|
-
|
46
|
+
it "creates all tags" do
|
47
47
|
tags = ['some', 'tag:name=blah']
|
48
48
|
@taggable.tag_list = tags
|
49
49
|
@taggable.save!
|
50
50
|
@taggable.tags.map(&:name).should == tags
|
51
51
|
end
|
52
52
|
|
53
|
-
|
53
|
+
it "only creates new tags" do
|
54
54
|
@taggable.tag_list = "bling"
|
55
55
|
@taggable.save!
|
56
56
|
tag_count = Tag.count
|
@@ -60,7 +60,7 @@ class HasMachineTagsTest < Test::Unit::TestCase
|
|
60
60
|
Tag.count.should == tag_count + 1
|
61
61
|
end
|
62
62
|
|
63
|
-
|
63
|
+
it "deletes unused tags" do
|
64
64
|
@taggable.tag_list == 'bling, bling3'
|
65
65
|
@taggable.save!
|
66
66
|
@taggable.tag_list = "bling4"
|
@@ -69,4 +69,4 @@ class HasMachineTagsTest < Test::Unit::TestCase
|
|
69
69
|
@taggable.tags.map(&:name).should == ['bling4']
|
70
70
|
end
|
71
71
|
end
|
72
|
-
end
|
72
|
+
end
|
data/test/tag_methods_test.rb
CHANGED
@@ -1,109 +1,109 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe "TagMethods" do
|
4
|
+
it "create with normal tag name only touches name" do
|
5
5
|
obj = Tag.create(:name=>'blah1')
|
6
6
|
[:name, :namespace, :predicate, :value].map {|e| obj.send(e)}.should == ['blah1', nil, nil, nil]
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
it "create with machine tag name sets all name fields" do
|
10
10
|
obj = Tag.create(:name=>'gem:name=machine')
|
11
11
|
[:name, :namespace, :predicate, :value].map {|e| obj.send(e)}.should == ['gem:name=machine', 'gem', 'name', 'machine']
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
before
|
14
|
+
describe "update" do
|
15
|
+
before { @obj = Tag.new }
|
16
16
|
|
17
|
-
|
17
|
+
it "with normal tag name only touches name" do
|
18
18
|
@obj.update_attributes :name=> 'bling'
|
19
19
|
[:name, :namespace, :predicate, :value].map {|e| @obj.send(e)}.should == ['bling', nil, nil, nil]
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
it "with machine tag name sets all name fields" do
|
23
23
|
@obj.update_attributes :name=>'gem:prop=value'
|
24
24
|
[:name, :namespace, :predicate, :value].map {|e| @obj.send(e)}.should == ['gem:prop=value', 'gem', 'prop', 'value']
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
it "with no name sets no name fields" do
|
28
28
|
@obj.update_attributes :name=>'blah2'
|
29
29
|
@obj.update_attributes :predicate=>'changed'
|
30
30
|
@obj.name.should == 'blah2'
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
describe "match_wildcard_machine_tag" do
|
35
|
+
it "matches namespace with asterisk" do
|
36
36
|
Tag.match_wildcard_machine_tag('name:*=').should == [[:namespace,'name']]
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it "matches namespace without asterisk" do
|
40
40
|
Tag.match_wildcard_machine_tag('name:').should == [[:namespace,'name']]
|
41
41
|
end
|
42
42
|
|
43
|
-
|
43
|
+
it "matches predicate with asterisk" do
|
44
44
|
Tag.match_wildcard_machine_tag('*:pred=').should == [[:predicate,'pred']]
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
it "matches predicate without asterisk" do
|
48
48
|
Tag.match_wildcard_machine_tag('pred=').should == [[:predicate,'pred']]
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
it "matches value with asterisk" do
|
52
52
|
Tag.match_wildcard_machine_tag('*:*=val').should == [[:value, 'val']]
|
53
53
|
end
|
54
54
|
|
55
|
-
|
55
|
+
it "matches value without asterisk" do
|
56
56
|
Tag.match_wildcard_machine_tag('=val').should == [[:value, 'val']]
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
it "matches namespace and predicate without asterisk" do
|
60
60
|
Tag.match_wildcard_machine_tag('name:pred').should == [[:namespace, 'name'], [:predicate, 'pred']]
|
61
61
|
end
|
62
62
|
|
63
|
-
|
63
|
+
it "matches namespace and predicate with asterisk" do
|
64
64
|
Tag.match_wildcard_machine_tag('name:pred=').should == [[:namespace, 'name'], [:predicate, 'pred']]
|
65
65
|
end
|
66
66
|
|
67
|
-
|
67
|
+
it "matches predicate and value without asterisk" do
|
68
68
|
Tag.match_wildcard_machine_tag('pred=val').should == [[:predicate, 'pred'], [:value, 'val']]
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
it "matches predicate and value with asterisk" do
|
72
72
|
Tag.match_wildcard_machine_tag('*:pred=val').should == [[:predicate, 'pred'], [:value, 'val']]
|
73
73
|
end
|
74
74
|
|
75
|
-
|
75
|
+
it "matches namespace and value without asterisk" do
|
76
76
|
Tag.match_wildcard_machine_tag('name.val').should == [[:namespace, 'name'], [:value, 'val']]
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
it "matches namespace and value with asterisk" do
|
80
80
|
Tag.match_wildcard_machine_tag('name:*=val').should == [[:namespace, 'name'], [:value, 'val']]
|
81
81
|
end
|
82
82
|
|
83
|
-
|
83
|
+
it "doesn't match total wildcard" do
|
84
84
|
Tag.match_wildcard_machine_tag('*:*=').should == []
|
85
85
|
end
|
86
86
|
|
87
|
-
|
87
|
+
it "doesn't match machine tag" do
|
88
88
|
Tag.match_wildcard_machine_tag('name:pred=val').should == nil
|
89
89
|
end
|
90
90
|
|
91
|
-
|
91
|
+
it "doesn't match normal tag" do
|
92
92
|
Tag.match_wildcard_machine_tag('name').should == nil
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
|
97
|
-
Tag.new(:name=>'valid!name_really?').valid?.should
|
96
|
+
it "validates name when no invalid characters" do
|
97
|
+
Tag.new(:name=>'valid!name_really?').valid?.should == true
|
98
98
|
end
|
99
99
|
|
100
|
-
|
101
|
-
Tag.new(:name=>'name:pred=value').valid?.should
|
100
|
+
it "validates name when machine tag format" do
|
101
|
+
Tag.new(:name=>'name:pred=value').valid?.should == true
|
102
102
|
end
|
103
103
|
|
104
|
-
|
104
|
+
it "invalidates name when invalid characters present" do
|
105
105
|
%w{some.tag another:tag so=invalid yet,another whoop*}.each do |e|
|
106
|
-
Tag.new(:name=>e).valid?.should
|
106
|
+
Tag.new(:name=>e).valid?.should == false
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'activerecord'
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require 'matchy' #gem install jeremymcanally-matchy -s http://gems.github.com
|
6
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'bacon'
|
4
|
+
require 'has_machine_tags'
|
7
5
|
require File.join(File.dirname(__FILE__), '..', 'init')
|
8
6
|
|
9
7
|
#Setup logger
|
@@ -22,5 +20,7 @@ class TaggableModel < ActiveRecord::Base
|
|
22
20
|
has_machine_tags
|
23
21
|
end
|
24
22
|
|
25
|
-
class
|
26
|
-
end
|
23
|
+
class Bacon::Context
|
24
|
+
def after_all; yield; end
|
25
|
+
def before_all; yield; end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_machine_tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 7
|
9
|
+
version: 0.1.7
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Gabriel Horner
|
@@ -9,29 +14,32 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-06-10 00:00:00 -04:00
|
13
18
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bacon
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
description: This gem implements Flickr's machine tags while still maintaining standard tagging behavior. This allows for more precise tagging as tags can have unlimited contexts provided by combinations of namespaces and predicates. These unlimited contexts also make machine tags ripe for modeling relationships between objects.
|
17
34
|
email: gabriel.horner@gmail.com
|
18
35
|
executables: []
|
19
36
|
|
20
37
|
extensions: []
|
21
38
|
|
22
39
|
extra_rdoc_files:
|
23
|
-
- LICENSE.txt
|
24
40
|
- README.rdoc
|
25
|
-
files:
|
26
|
-
- CHANGELOG.rdoc
|
27
41
|
- LICENSE.txt
|
28
|
-
|
29
|
-
- Rakefile
|
30
|
-
- VERSION.yml
|
31
|
-
- generators/has_machine_tags_migration/has_machine_tags_migration_generator.rb
|
32
|
-
- generators/has_machine_tags_migration/templates/migration.rb
|
33
|
-
- init.rb
|
34
|
-
- lib/has_machine_tags.rb
|
42
|
+
files:
|
35
43
|
- lib/has_machine_tags/console.rb
|
36
44
|
- lib/has_machine_tags/finder.rb
|
37
45
|
- lib/has_machine_tags/tag.rb
|
@@ -39,44 +47,54 @@ files:
|
|
39
47
|
- lib/has_machine_tags/tag_list.rb
|
40
48
|
- lib/has_machine_tags/tag_methods.rb
|
41
49
|
- lib/has_machine_tags/tagging.rb
|
42
|
-
-
|
50
|
+
- lib/has_machine_tags/version.rb
|
51
|
+
- lib/has_machine_tags.rb
|
43
52
|
- test/finder_test.rb
|
44
53
|
- test/has_machine_tags_test.rb
|
45
54
|
- test/schema.rb
|
46
55
|
- test/tag_methods_test.rb
|
47
56
|
- test/test_helper.rb
|
57
|
+
- generators/has_machine_tags_migration/has_machine_tags_migration_generator.rb
|
58
|
+
- generators/has_machine_tags_migration/templates/migration.rb
|
59
|
+
- LICENSE.txt
|
60
|
+
- CHANGELOG.rdoc
|
61
|
+
- README.rdoc
|
62
|
+
- Rakefile
|
63
|
+
- gemspec
|
64
|
+
- init.rb
|
48
65
|
has_rdoc: true
|
49
66
|
homepage: http://tagaholic.me/has_machine_tags/
|
50
67
|
licenses: []
|
51
68
|
|
52
69
|
post_install_message:
|
53
|
-
rdoc_options:
|
54
|
-
|
70
|
+
rdoc_options: []
|
71
|
+
|
55
72
|
require_paths:
|
56
73
|
- lib
|
57
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
58
76
|
requirements:
|
59
77
|
- - ">="
|
60
78
|
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
61
81
|
version: "0"
|
62
|
-
version:
|
63
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
64
84
|
requirements:
|
65
85
|
- - ">="
|
66
86
|
- !ruby/object:Gem::Version
|
67
|
-
|
68
|
-
|
87
|
+
segments:
|
88
|
+
- 1
|
89
|
+
- 3
|
90
|
+
- 6
|
91
|
+
version: 1.3.6
|
69
92
|
requirements: []
|
70
93
|
|
71
|
-
rubyforge_project:
|
72
|
-
|
73
|
-
rubygems_version: 1.3.5
|
94
|
+
rubyforge_project: tagaholic
|
95
|
+
rubygems_version: 1.3.7
|
74
96
|
signing_key:
|
75
97
|
specification_version: 3
|
76
|
-
summary: A rails tagging
|
77
|
-
test_files:
|
78
|
-
|
79
|
-
- test/has_machine_tags_test.rb
|
80
|
-
- test/schema.rb
|
81
|
-
- test/tag_methods_test.rb
|
82
|
-
- test/test_helper.rb
|
98
|
+
summary: A rails tagging gem which implements flickr's machine tags and maybe more (semantic tags).
|
99
|
+
test_files: []
|
100
|
+
|
data/VERSION.yml
DELETED
data/rails/init.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'has_machine_tags'
|
2
|
-
require 'has_machine_tags/tag_methods'
|
3
|
-
|
4
|
-
#attempt to load constant
|
5
|
-
::Tag rescue nil
|
6
|
-
if Object.const_defined? :Tag
|
7
|
-
::Tag.class_eval %[include HasMachineTags::TagMethods]
|
8
|
-
else
|
9
|
-
require 'has_machine_tags/tag'
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'has_machine_tags/tagging'
|
13
|
-
ActiveRecord::Base.send :include, HasMachineTags
|