gutentag 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -1
- data/gutentag.gemspec +1 -1
- data/lib/gutentag.rb +1 -1
- data/lib/gutentag/active_record.rb +8 -8
- data/lib/gutentag/persistence.rb +38 -0
- data/spec/acceptance/tag_names_spec.rb +18 -26
- metadata +3 -3
- data/lib/gutentag/tag_names.rb +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dda4e9077e5d19af15ad0ae9bab60a64147f4c11
|
4
|
+
data.tar.gz: dcd0271e7e842c8edf3fc25ba1f4254c4853369a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc49c2eaa8236fd2991c5213fb53bce4077890135185f0cf5730331603a384813fe0ecf3427d370719e11931044095ba65297c38052a43a4343e396311e77d68
|
7
|
+
data.tar.gz: b734e64f5731e2458af240c09a26e650a2d103d5d9bdb8649c52a0cf9d868cb1d06f1fd0fd61271c93b4764c3a7ea0dfa79b3f61ae5e6e932e042bd6321977ff
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Gutentag
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/gutentag.png)](http://badge.fury.io/rb/gutentag)
|
3
4
|
[![Build Status](https://travis-ci.org/pat/gutentag.png?branch=master)](https://travis-ci.org/pat/gutentag)
|
4
5
|
[![Code Climate](https://codeclimate.com/github/pat/gutentag.png)](https://codeclimate.com/github/pat/gutentag)
|
5
6
|
|
@@ -11,7 +12,7 @@ This was built partly as a proof-of-concept, and partly to see how a tagging gem
|
|
11
12
|
|
12
13
|
Get it into your Gemfile - and don't forget the version constraint!
|
13
14
|
|
14
|
-
gem 'gutentag', '~> 0.
|
15
|
+
gem 'gutentag', '~> 0.3.0'
|
15
16
|
|
16
17
|
Next: your tags get persisted to your database, so let's import and run the migrations to get the tables set up:
|
17
18
|
|
@@ -36,6 +37,11 @@ That's all it takes to get a tags association on each article. Of course, popula
|
|
36
37
|
article.tag_names -= ['ruby']
|
37
38
|
article.tag_names #=> ['pancakes', 'melbourne', 'portland']
|
38
39
|
|
40
|
+
Changes to tag_names are not persisted immediately - you must save your taggable object to have the tag changes reflected in your database:
|
41
|
+
|
42
|
+
article.tag_names << 'ruby'
|
43
|
+
article.save
|
44
|
+
|
39
45
|
## Licence
|
40
46
|
|
41
47
|
Copyright (c) 2013, Gutentag is developed and maintained by Pat Allan, and is released under the open MIT Licence.
|
data/gutentag.gemspec
CHANGED
data/lib/gutentag.rb
CHANGED
@@ -9,18 +9,18 @@ module Gutentag::ActiveRecord
|
|
9
9
|
:dependent => :destroy
|
10
10
|
has_many :tags, :class_name => 'Gutentag::Tag',
|
11
11
|
:through => :taggings
|
12
|
+
|
13
|
+
after_save Gutentag::Persistence
|
14
|
+
|
15
|
+
attr_writer :tag_names
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
16
|
-
@tag_names
|
19
|
+
def reset_tag_names
|
20
|
+
@tag_names = nil
|
17
21
|
end
|
18
22
|
|
19
|
-
def tag_names
|
20
|
-
|
21
|
-
@tag_names = names
|
22
|
-
else
|
23
|
-
@tag_names = Gutentag::TagNames.new_with_names self, names
|
24
|
-
end
|
23
|
+
def tag_names
|
24
|
+
@tag_names ||= tags.collect(&:name)
|
25
25
|
end
|
26
26
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Gutentag::Persistence
|
2
|
+
def self.after_save(taggable)
|
3
|
+
new(taggable).persist
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(taggable)
|
7
|
+
@taggable = taggable
|
8
|
+
@existing = normalised taggable.tags.collect(&:name)
|
9
|
+
@changes = normalised taggable.tag_names
|
10
|
+
end
|
11
|
+
|
12
|
+
def persist
|
13
|
+
remove_old
|
14
|
+
add_new
|
15
|
+
|
16
|
+
taggable.reset_tag_names
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :taggable, :existing, :changes
|
22
|
+
|
23
|
+
def add_new
|
24
|
+
(changes - existing).each do |name|
|
25
|
+
taggable.tags << Gutentag::Tag.find_or_create(name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalised(names)
|
30
|
+
names.collect { |name| Gutentag::TagName.normalise(name) }.uniq
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_old
|
34
|
+
(existing - changes).each do |name|
|
35
|
+
taggable.tags.delete Gutentag::Tag.find_by_name(name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -8,11 +8,12 @@ describe "Managing tags via names" do
|
|
8
8
|
|
9
9
|
article.tags << melbourne
|
10
10
|
|
11
|
-
article.tag_names.
|
11
|
+
article.tag_names.should == ['melbourne']
|
12
12
|
end
|
13
13
|
|
14
14
|
it "adds tags via their names" do
|
15
15
|
article.tag_names << 'melbourne'
|
16
|
+
article.save!
|
16
17
|
|
17
18
|
article.tags.collect(&:name).should == ['melbourne']
|
18
19
|
end
|
@@ -20,32 +21,24 @@ describe "Managing tags via names" do
|
|
20
21
|
it "doesn't complain when adding an existing tag" do
|
21
22
|
article.tag_names << 'melbourne'
|
22
23
|
article.tag_names << 'melbourne'
|
24
|
+
article.save!
|
23
25
|
|
24
26
|
article.tags.collect(&:name).should == ['melbourne']
|
25
27
|
end
|
26
28
|
|
27
29
|
it "accepts a completely new set of tags" do
|
28
30
|
article.tag_names = ['portland', 'oregon']
|
31
|
+
article.save!
|
29
32
|
|
30
33
|
article.tags.collect(&:name).should == ['portland', 'oregon']
|
31
34
|
end
|
32
35
|
|
33
|
-
it "enumerates through tag names" do
|
34
|
-
article.tag_names = ['melbourne', 'victoria']
|
35
|
-
names = []
|
36
|
-
|
37
|
-
article.tag_names.each do |name|
|
38
|
-
names << name
|
39
|
-
end
|
40
|
-
|
41
|
-
names.should == ['melbourne', 'victoria']
|
42
|
-
end
|
43
|
-
|
44
36
|
it "does not allow duplication of tags" do
|
45
37
|
existing = Article.create
|
46
38
|
existing.tags << Gutentag::Tag.create(:name => 'portland')
|
47
39
|
|
48
40
|
article.tag_names = ['portland']
|
41
|
+
article.save!
|
49
42
|
|
50
43
|
existing.tag_ids.should == article.tag_ids
|
51
44
|
end
|
@@ -53,6 +46,7 @@ describe "Managing tags via names" do
|
|
53
46
|
it "appends tag names" do
|
54
47
|
article.tag_names = ['portland']
|
55
48
|
article.tag_names += ['oregon', 'ruby']
|
49
|
+
article.save!
|
56
50
|
|
57
51
|
article.tags.collect(&:name).should == ['portland', 'oregon', 'ruby']
|
58
52
|
end
|
@@ -60,6 +54,7 @@ describe "Managing tags via names" do
|
|
60
54
|
it "does not repeat appended names that already exist" do
|
61
55
|
article.tag_names = ['portland', 'oregon']
|
62
56
|
article.tag_names += ['oregon', 'ruby']
|
57
|
+
article.save!
|
63
58
|
|
64
59
|
article.tags.collect(&:name).should == ['portland', 'oregon', 'ruby']
|
65
60
|
end
|
@@ -67,6 +62,7 @@ describe "Managing tags via names" do
|
|
67
62
|
it "removes a single tag name" do
|
68
63
|
article.tag_names = ['portland', 'oregon']
|
69
64
|
article.tag_names.delete 'oregon'
|
65
|
+
article.save!
|
70
66
|
|
71
67
|
article.tags.collect(&:name).should == ['portland']
|
72
68
|
end
|
@@ -74,32 +70,28 @@ describe "Managing tags via names" do
|
|
74
70
|
it "removes tag names" do
|
75
71
|
article.tag_names = ['portland', 'oregon', 'ruby']
|
76
72
|
article.tag_names -= ['oregon', 'ruby']
|
73
|
+
article.save!
|
77
74
|
|
78
75
|
article.tags.collect(&:name).should == ['portland']
|
79
76
|
end
|
80
77
|
|
81
|
-
it "provides union operators" do
|
82
|
-
article.tag_names = ['portland', 'ruby']
|
83
|
-
article.tag_names |= ['ruby', 'melbourne']
|
84
|
-
|
85
|
-
article.tags.collect(&:name).should == ['portland', 'ruby', 'melbourne']
|
86
|
-
end
|
87
|
-
|
88
|
-
it "provides intersection operators" do
|
89
|
-
article.tag_names = ['portland', 'ruby']
|
90
|
-
article.tag_names &= ['ruby', 'melbourne']
|
91
|
-
|
92
|
-
article.tags.collect(&:name).should == ['ruby']
|
93
|
-
end
|
94
|
-
|
95
78
|
it "matches tag names ignoring case" do
|
96
79
|
article.tag_names = ['portland']
|
97
80
|
article.tag_names += ['Portland']
|
81
|
+
article.save!
|
98
82
|
|
99
83
|
article.tags.collect(&:name).should == ['portland']
|
100
84
|
|
101
85
|
article.tag_names << 'Portland'
|
86
|
+
article.save!
|
102
87
|
|
103
88
|
article.tags.collect(&:name).should == ['portland']
|
104
89
|
end
|
90
|
+
|
91
|
+
it "allows setting of tag names on unpersisted objects" do
|
92
|
+
article = Article.new :tag_names => ['melbourne', 'pancakes']
|
93
|
+
article.save!
|
94
|
+
|
95
|
+
article.tag_names.should == ['melbourne', 'pancakes']
|
96
|
+
end
|
105
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gutentag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07
|
11
|
+
date: 2013-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -86,8 +86,8 @@ files:
|
|
86
86
|
- lib/gutentag.rb
|
87
87
|
- lib/gutentag/active_record.rb
|
88
88
|
- lib/gutentag/engine.rb
|
89
|
+
- lib/gutentag/persistence.rb
|
89
90
|
- lib/gutentag/tag_name.rb
|
90
|
-
- lib/gutentag/tag_names.rb
|
91
91
|
- spec/acceptance/tag_names_spec.rb
|
92
92
|
- spec/acceptance/tags_spec.rb
|
93
93
|
- spec/gutentag/tag_name_spec.rb
|
data/lib/gutentag/tag_names.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
class Gutentag::TagNames
|
2
|
-
include Enumerable
|
3
|
-
|
4
|
-
def self.new_with_names(taggable, names)
|
5
|
-
new(taggable).replace names
|
6
|
-
end
|
7
|
-
|
8
|
-
def initialize(taggable)
|
9
|
-
@taggable = taggable
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_a
|
13
|
-
taggable.tags.collect &:name
|
14
|
-
end
|
15
|
-
|
16
|
-
def +(array)
|
17
|
-
normalised(array).each { |name| self.<< name }
|
18
|
-
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
def -(array)
|
23
|
-
normalised(array).each { |name| self.delete name }
|
24
|
-
|
25
|
-
self
|
26
|
-
end
|
27
|
-
|
28
|
-
def <<(name)
|
29
|
-
tag = Gutentag::Tag.find_or_create name
|
30
|
-
|
31
|
-
taggable.tags << tag unless taggable.tags.include?(tag)
|
32
|
-
end
|
33
|
-
|
34
|
-
def |(array)
|
35
|
-
to_a | normalised(array)
|
36
|
-
end
|
37
|
-
|
38
|
-
def &(array)
|
39
|
-
to_a & normalised(array)
|
40
|
-
end
|
41
|
-
|
42
|
-
def clear
|
43
|
-
taggable.tags.clear
|
44
|
-
end
|
45
|
-
|
46
|
-
def delete(name)
|
47
|
-
taggable.tags.delete Gutentag::Tag.find_by_name(name)
|
48
|
-
end
|
49
|
-
|
50
|
-
def each(&block)
|
51
|
-
to_a.each &block
|
52
|
-
end
|
53
|
-
|
54
|
-
def replace(names)
|
55
|
-
clear
|
56
|
-
self.+ names
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
attr_reader :taggable
|
62
|
-
|
63
|
-
def normalised(array)
|
64
|
-
array.collect { |name| Gutentag::TagName.normalise(name) }
|
65
|
-
end
|
66
|
-
end
|