rocket_tag 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/rocket_tag/tag.rb +6 -0
- data/lib/rocket_tag/taggable.rb +97 -56
- data/rocket_tag.gemspec +2 -2
- data/spec/rocket_tag/taggable_spec.rb +6 -8
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/lib/rocket_tag/tag.rb
CHANGED
data/lib/rocket_tag/taggable.rb
CHANGED
@@ -1,4 +1,40 @@
|
|
1
1
|
require 'squeel'
|
2
|
+
module Squeel
|
3
|
+
module Adapters
|
4
|
+
module ActiveRecord
|
5
|
+
module RelationExtensions
|
6
|
+
|
7
|
+
# The purpose of this call is to close a query and make
|
8
|
+
# it behave as a simple table or view. If a query has
|
9
|
+
# aggregate functions applied then downstream active
|
10
|
+
# relation chaining causes unpredictable behaviour.
|
11
|
+
#
|
12
|
+
# This call isolates the group by behaviours.
|
13
|
+
def isolate_group_by_as(type)
|
14
|
+
type.from("(#{to_sql}) #{type.table_name}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def select_all
|
18
|
+
select('*')
|
19
|
+
end
|
20
|
+
|
21
|
+
# We really only want to group on id for practical
|
22
|
+
# purposes but POSTGRES requires that a group by outputs
|
23
|
+
# all the column names not under an aggregate function.
|
24
|
+
#
|
25
|
+
# This little helper generates such a group by
|
26
|
+
def group_by_all_columns
|
27
|
+
cn = self.column_names
|
28
|
+
group { cn.map { |col| __send__(col) } }
|
29
|
+
end
|
30
|
+
|
31
|
+
def exists
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
2
38
|
|
3
39
|
module RocketTag
|
4
40
|
module Taggable
|
@@ -81,6 +117,7 @@ module RocketTag
|
|
81
117
|
@contexts[context.to_sym] || []
|
82
118
|
end
|
83
119
|
|
120
|
+
|
84
121
|
def tagged_similar options = {}
|
85
122
|
context = options.delete :on
|
86
123
|
if context
|
@@ -111,14 +148,13 @@ module RocketTag
|
|
111
148
|
s | t
|
112
149
|
end
|
113
150
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
151
|
+
r = self.class.
|
152
|
+
joins{tags}.
|
153
|
+
where{condition}.
|
154
|
+
where{~id != my{id}}
|
155
|
+
|
156
|
+
self.class.count_tags(r)
|
120
157
|
|
121
|
-
r = self.class.from("(#{inner.to_sql}) #{self.class.table_name}")
|
122
158
|
end
|
123
159
|
end
|
124
160
|
|
@@ -128,9 +164,44 @@ module RocketTag
|
|
128
164
|
@rocket_tag ||= RocketTag::Taggable::Manager.new(self)
|
129
165
|
end
|
130
166
|
|
131
|
-
|
167
|
+
# Provides the tag counting functionality by adding an
|
168
|
+
# aggregate count on id. Assumes valid a join has been
|
169
|
+
# made.
|
170
|
+
def count_tags(rel)
|
171
|
+
rel.select_all.
|
172
|
+
select{count(~id).as(tags_count)}.
|
173
|
+
group_by_all_columns.
|
174
|
+
order("tags_count DESC").
|
175
|
+
isolate_group_by_as(self)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Filters tags according to
|
179
|
+
# context. context param can
|
180
|
+
# be either a single context
|
181
|
+
# id or an array of context ids
|
182
|
+
def with_tag_context context
|
132
183
|
if context
|
133
|
-
|
184
|
+
if context
|
185
|
+
if context.class == Array
|
186
|
+
contexts = context
|
187
|
+
else
|
188
|
+
contexts = [context]
|
189
|
+
end
|
190
|
+
else
|
191
|
+
contexts = []
|
192
|
+
end
|
193
|
+
|
194
|
+
conditions = contexts.map do |context|
|
195
|
+
squeel do
|
196
|
+
(taggings.context == context.to_s)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
condition = conditions.inject do |s, t|
|
201
|
+
s | t
|
202
|
+
end
|
203
|
+
|
204
|
+
where{condition}
|
134
205
|
else
|
135
206
|
where{ }
|
136
207
|
end
|
@@ -151,25 +222,17 @@ module RocketTag
|
|
151
222
|
# Generates a query that provides the matches
|
152
223
|
# along with an extra column :tags_count.
|
153
224
|
def tagged_with tags_list, options = {}
|
154
|
-
on = options.delete :on
|
155
225
|
|
156
|
-
|
157
|
-
select("#{self.table_name}.*").
|
158
|
-
joins{tags}.
|
226
|
+
r = joins{tags}.
|
159
227
|
where{tags.name.in(tags_list)}.
|
160
|
-
|
161
|
-
group(self.column_names.map{|col| "#{self.table_name}.#{col}"})
|
228
|
+
with_tag_context(options.delete :on)
|
162
229
|
|
163
|
-
|
164
|
-
|
165
|
-
# queries
|
166
|
-
r = from("(#{inner.to_sql}) #{table_name}")
|
230
|
+
|
231
|
+
r = count_tags(r)
|
167
232
|
|
168
233
|
if options.delete :all
|
169
234
|
r = r.where{tags_count==tags_list.length}
|
170
|
-
|
171
|
-
|
172
|
-
if min = options.delete(:min)
|
235
|
+
elsif min = options.delete(:min)
|
173
236
|
r = r.where{tags_count>=min}
|
174
237
|
end
|
175
238
|
|
@@ -178,7 +241,7 @@ module RocketTag
|
|
178
241
|
id.in(r.select{"id"})
|
179
242
|
end
|
180
243
|
else
|
181
|
-
r
|
244
|
+
r
|
182
245
|
end
|
183
246
|
|
184
247
|
end
|
@@ -186,45 +249,20 @@ module RocketTag
|
|
186
249
|
# Generates a query that returns list of popular tags
|
187
250
|
# for given model with an extra column :tags_count.
|
188
251
|
def popular_tags options={}
|
189
|
-
context = options.delete :on
|
190
|
-
if context
|
191
|
-
if context.class == Array
|
192
|
-
contexts = context
|
193
|
-
else
|
194
|
-
contexts = [context]
|
195
|
-
end
|
196
|
-
else
|
197
|
-
contexts = []
|
198
|
-
end
|
199
252
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
253
|
+
r =
|
254
|
+
RocketTag::Tag.
|
255
|
+
joins{taggings}.
|
256
|
+
with_tag_context(options.delete :on).
|
257
|
+
by_taggable_type(self)
|
205
258
|
|
206
|
-
|
207
|
-
s | t
|
208
|
-
end
|
209
|
-
inner = RocketTag::Tag.select{count(~id).as(tags_count)}.
|
210
|
-
select("#{RocketTag::Tag.table_name}.*").
|
211
|
-
joins{taggings.outer}.where{condition}.
|
212
|
-
where{ taggings.taggable_type == my{self.to_s} }.
|
213
|
-
group{~id} #.
|
214
|
-
#order("tags_count DESC")
|
215
|
-
r = from("(#{inner.to_sql}) #{table_name}")
|
259
|
+
r = count_tags(r)
|
216
260
|
|
217
261
|
if min = options.delete(:min)
|
218
262
|
r = r.where{tags_count>=min}
|
219
263
|
end
|
220
264
|
|
221
|
-
|
222
|
-
squeel do
|
223
|
-
id.in(r.select{"id"})
|
224
|
-
end
|
225
|
-
else
|
226
|
-
r.select("*")
|
227
|
-
end
|
265
|
+
r
|
228
266
|
end
|
229
267
|
|
230
268
|
def setup_for_rocket_tag
|
@@ -261,7 +299,10 @@ module RocketTag
|
|
261
299
|
tags_to_assign = exisiting_tags + created_tags
|
262
300
|
|
263
301
|
tags_to_assign.each do |tag|
|
264
|
-
tagging = Tagging.new :tag => tag,
|
302
|
+
tagging = Tagging.new :tag => tag,
|
303
|
+
:taggable => self,
|
304
|
+
:context => context,
|
305
|
+
:tagger => nil
|
265
306
|
self.taggings << tagging
|
266
307
|
end
|
267
308
|
end
|
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.5.
|
8
|
+
s.version = "0.5.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-06-
|
12
|
+
s.date = "2012-06-29"
|
13
13
|
s.description = ""
|
14
14
|
s.email = "bradphelan@xtargets.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -306,18 +306,16 @@ describe TaggableModel do
|
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
309
|
-
describe "
|
310
|
-
it "should be
|
309
|
+
describe "Using in subqueries" do
|
310
|
+
it "should be possible to select the 'id' of the relation to use in a subquery" do
|
311
|
+
|
311
312
|
TaggableModel.where do
|
312
|
-
TaggableModel.
|
313
|
+
id.in(TaggableModel.tagged_with(["a", "b"]).select{id}) &
|
314
|
+
id.in(TaggableModel.tagged_with(["c"]).select{id})
|
313
315
|
end.count.should == 2
|
314
316
|
|
315
|
-
x = TaggableModel.where do
|
316
|
-
TaggableModel.tagged_with_sifter(["a", "b"]) & TaggableModel.tagged_with_sifter(["c"])
|
317
|
-
end.to_sql
|
318
|
-
|
319
317
|
TaggableModel.where do
|
320
|
-
TaggableModel.
|
318
|
+
id.in(TaggableModel.tagged_with(["a", "b"]).select{id})
|
321
319
|
end.count.should == 4
|
322
320
|
end
|
323
321
|
|
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.
|
5
|
+
version: 0.5.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-06-
|
13
|
+
date: 2012-06-29 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: 88231840862745454
|
148
148
|
segments:
|
149
149
|
- 0
|
150
150
|
version: "0"
|