rocket_tag 0.5.0 → 0.5.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/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"
|