rocket_tag 0.2.0 → 0.3.1
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.
- data/README.md +35 -0
- data/VERSION +1 -1
- data/lib/rocket_tag/taggable.rb +37 -6
- data/rocket_tag.gemspec +2 -2
- data/spec/rocket_tag/taggable_spec.rb +43 -4
- metadata +3 -3
data/README.md
CHANGED
@@ -48,10 +48,45 @@ Usage
|
|
48
48
|
# Match a miniumum number of tags
|
49
49
|
TaggableModel.tagged_with ["math", "kiting", "coding", "sleeping"], :min => 2, :on => "skills"
|
50
50
|
|
51
|
+
# Take advantage of the tags_count synthetic column returned with every query
|
52
|
+
TaggableModel.tagged_with(["math", "kiting", "coding", "sleeping"], :on => "skills").where{tags_count>=2}
|
51
53
|
|
52
54
|
# Mix with active relation
|
53
55
|
TaggableModel.tagged_with(["forking", "kiting"]).where( ["created_at > ?", Time.zone.now.ago(5.hours)])
|
54
56
|
|
57
|
+
# Find similar models based on tags on a specific context and return in decending order
|
58
|
+
# of 'tags_count'
|
59
|
+
model.find_similar :on => "skills"
|
60
|
+
model.find_similar :on => "habits"
|
61
|
+
|
62
|
+
# Find similar models based on tags on every context and return in decending order
|
63
|
+
# of 'tags_count'. Note that each tag is still scoped according to it's context
|
64
|
+
model.find_similar
|
65
|
+
|
66
|
+
# For reference the SQL generated for model.find_similar when there are
|
67
|
+
# context [:skills, :languages] available is
|
68
|
+
|
69
|
+
SELECT "taggable_models".* FROM
|
70
|
+
(
|
71
|
+
SELECT COUNT("taggable_models"."id") AS tags_count,
|
72
|
+
taggable_models.*
|
73
|
+
FROM "taggable_models"
|
74
|
+
INNER JOIN "taggings"
|
75
|
+
ON "taggings"."taggable_id" = "taggable_models"."id"
|
76
|
+
AND "taggings"."taggable_type" = 'TaggableModel'
|
77
|
+
INNER JOIN "tags"
|
78
|
+
ON "tags"."id" = "taggings"."tag_id"
|
79
|
+
WHERE "taggable_models"."id" != 2
|
80
|
+
AND (( ( "tags"."name" IN ( 'german', 'french' ) AND "taggings"."context" = 'languages' )
|
81
|
+
OR ( "tags"."name" IN ( 'a', 'b', 'x' ) AND "taggings"."context" = 'skills' )
|
82
|
+
))
|
83
|
+
GROUP BY "taggable_models"."id"
|
84
|
+
ORDER BY tags_count DESC
|
85
|
+
) taggable_models
|
86
|
+
|
87
|
+
|
88
|
+
# Note the aliasing of the inner select to shield the GROUP BY from downstream active relation
|
89
|
+
# queries
|
55
90
|
|
56
91
|
== Contributing to rocket_tag
|
57
92
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
data/lib/rocket_tag/taggable.rb
CHANGED
@@ -4,7 +4,7 @@ module RocketTag
|
|
4
4
|
module Taggable
|
5
5
|
def self.included(base)
|
6
6
|
base.extend ClassMethods
|
7
|
-
base.send :include, InstanceMethods
|
7
|
+
#base.send :include, InstanceMethods
|
8
8
|
end
|
9
9
|
|
10
10
|
class Manager
|
@@ -80,19 +80,45 @@ module RocketTag
|
|
80
80
|
@contexts ||= {}
|
81
81
|
@contexts[context.to_sym] || []
|
82
82
|
end
|
83
|
-
end
|
84
83
|
|
85
|
-
module InstanceMethods
|
86
84
|
def tagged_similar options = {}
|
87
85
|
context = options.delete :on
|
88
|
-
|
86
|
+
if context
|
87
|
+
raise Exception.new("#{context} is not a valid tag context for #{self.class}") unless self.class.rocket_tag.contexts.include? context
|
88
|
+
end
|
89
89
|
if context
|
90
90
|
contexts = [context]
|
91
91
|
else
|
92
92
|
contexts = self.class.rocket_tag.contexts
|
93
93
|
end
|
94
|
-
|
95
|
-
|
94
|
+
|
95
|
+
if contexts.size > 1
|
96
|
+
contexts = contexts.delete :tag
|
97
|
+
end
|
98
|
+
|
99
|
+
contexts = contexts.reject do |c|
|
100
|
+
send(c.to_sym).size == 0
|
101
|
+
end
|
102
|
+
|
103
|
+
conditions = contexts.map do |context|
|
104
|
+
_tags = send context.to_sym
|
105
|
+
self.class.squeel do
|
106
|
+
(tags.name.in(my{_tags}) & (taggings.context == my{context}))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
condition = conditions.inject do |s, t|
|
111
|
+
s | t
|
112
|
+
end
|
113
|
+
|
114
|
+
inner = self.class.select{count(~id).as(tags_count)}.
|
115
|
+
select("#{self.class.table_name}.*").
|
116
|
+
joins{tags}.where{condition}.
|
117
|
+
group{~id}.
|
118
|
+
where{~id != my{id}}.
|
119
|
+
order("tags_count DESC")
|
120
|
+
|
121
|
+
r = self.class.from("(#{inner.to_sql}) #{self.class.table_name}")
|
96
122
|
end
|
97
123
|
end
|
98
124
|
|
@@ -201,7 +227,12 @@ module RocketTag
|
|
201
227
|
end
|
202
228
|
end
|
203
229
|
|
230
|
+
@@acts_as_rocket_tag = false
|
204
231
|
def attr_taggable *contexts
|
232
|
+
unless @@acts_as_rocket_tag
|
233
|
+
include RocketTag::Taggable::InstanceMethods
|
234
|
+
@@acts_as_rocket_tag = true
|
235
|
+
end
|
205
236
|
|
206
237
|
if contexts.blank?
|
207
238
|
contexts = [:tag]
|
data/rocket_tag.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "rocket_tag"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brad Phelan"]
|
12
|
-
s.date = "2012-01-
|
12
|
+
s.date = "2012-01-25"
|
13
13
|
s.description = ""
|
14
14
|
s.email = "bradphelan@xtargets.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -100,6 +100,7 @@ describe TaggableModel do
|
|
100
100
|
@t01.languages = [ "german" , "italian"]
|
101
101
|
|
102
102
|
@t10.skills = [ "a" , "c"]
|
103
|
+
@t10.languages = [ "french" , "hebrew"]
|
103
104
|
|
104
105
|
@t11.skills = [ "a" , "c"]
|
105
106
|
|
@@ -165,9 +166,47 @@ describe TaggableModel do
|
|
165
166
|
end
|
166
167
|
|
167
168
|
describe "#tagged_similar" do
|
168
|
-
it "should
|
169
|
+
it "should return similar items" do
|
169
170
|
@t00.tagged_similar(:on => :skills).count.should == 3
|
171
|
+
@t00.tagged_similar(:on => :languages).count.should == 3
|
172
|
+
@t00.tagged_similar.count.should == 4
|
170
173
|
end
|
174
|
+
|
175
|
+
it "should return similar items in the correct order with the correct tags_count" do
|
176
|
+
|
177
|
+
# ----
|
178
|
+
similar = @t00.tagged_similar(:on => :skills).all
|
179
|
+
similar[0].id.should == @t01.id
|
180
|
+
similar[1].id.should == @t10.id
|
181
|
+
similar[2].id.should == @t11.id
|
182
|
+
|
183
|
+
similar[0].tags_count.should == 2
|
184
|
+
similar[1].tags_count.should == 1
|
185
|
+
similar[2].tags_count.should == 1
|
186
|
+
|
187
|
+
# ----
|
188
|
+
similar = @t00.tagged_similar(:on => :languages).all
|
189
|
+
similar[0].id.should == @t01.id
|
190
|
+
similar[1].id.should == @t10.id
|
191
|
+
similar[2].id.should == @t21.id
|
192
|
+
|
193
|
+
similar[0].tags_count.should == 1
|
194
|
+
similar[1].tags_count.should == 1
|
195
|
+
similar[2].tags_count.should == 1
|
196
|
+
|
197
|
+
# ----
|
198
|
+
similar = @t00.tagged_similar.all
|
199
|
+
similar[0].id.should == @t01.id
|
200
|
+
similar[1].id.should == @t10.id
|
201
|
+
similar[2].id.should == @t11.id
|
202
|
+
similar[3].id.should == @t21.id
|
203
|
+
|
204
|
+
similar[0].tags_count.should == 3
|
205
|
+
similar[1].tags_count.should == 2
|
206
|
+
similar[2].tags_count.should == 1
|
207
|
+
similar[3].tags_count.should == 1
|
208
|
+
end
|
209
|
+
|
171
210
|
end
|
172
211
|
|
173
212
|
describe "#tagged_with" do
|
@@ -237,8 +276,9 @@ describe TaggableModel do
|
|
237
276
|
l_t[:user_id].count.as("count_all")
|
238
277
|
).as "foo"
|
239
278
|
|
240
|
-
puts TaggableModel.joins("JOIN " + counts.to_sql ).to_sql
|
279
|
+
#puts TaggableModel.joins("JOIN " + counts.to_sql ).to_sql
|
241
280
|
end
|
281
|
+
|
242
282
|
it "should" do
|
243
283
|
u_t = Arel::Table::new :users
|
244
284
|
l_t = Arel::Table::new :logs
|
@@ -256,7 +296,7 @@ describe TaggableModel do
|
|
256
296
|
eq(counts[:user_id])).
|
257
297
|
project("*").project(counts[:count_all])
|
258
298
|
|
259
|
-
puts users.to_sql
|
299
|
+
# puts users.to_sql
|
260
300
|
|
261
301
|
end
|
262
302
|
end
|
@@ -270,7 +310,6 @@ describe TaggableModel do
|
|
270
310
|
x = TaggableModel.where do
|
271
311
|
TaggableModel.tagged_with_sifter(["a", "b"]) & TaggableModel.tagged_with_sifter(["c"])
|
272
312
|
end.to_sql
|
273
|
-
puts x
|
274
313
|
|
275
314
|
TaggableModel.where do
|
276
315
|
TaggableModel.tagged_with_sifter(["a", "b"])
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rocket_tag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.3.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Brad Phelan
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-25 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -144,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
144
|
requirements:
|
145
145
|
- - ">="
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
hash:
|
147
|
+
hash: 2545152122915663382
|
148
148
|
segments:
|
149
149
|
- 0
|
150
150
|
version: "0"
|