Active 0.0.14 → 0.0.17
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/Rakefile +1 -0
- data/lib/Active.rb +15 -0
- data/lib/services/IActivity.rb +34 -17
- data/lib/services/active_works.rb +5 -4
- data/lib/services/activity.rb +253 -70
- data/lib/services/address.rb +17 -0
- data/lib/services/ats.rb +82 -35
- data/lib/services/gsa.rb +153 -0
- data/lib/services/reg_center.rb +43 -21
- data/lib/services/sanitize.rb +108 -0
- data/lib/services/search.rb +101 -18
- data/lib/services/search.txt +403 -0
- data/lib/services/validators.rb +91 -0
- data/spec/Active_spec.rb +24 -1
- data/spec/activeworks_spec.rb +1 -1
- data/spec/activity_spec.rb +101 -170
- data/spec/ats_spec.rb +9 -3
- data/spec/gsa_spec.rb +123 -0
- data/spec/reg_spec.rb +17 -8
- data/spec/search_memcached_spec.rb +49 -0
- data/spec/search_spec.rb +404 -356
- data/version.txt +1 -1
- metadata +30 -6
data/lib/services/search.rb
CHANGED
@@ -4,6 +4,7 @@ require 'cgi'
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'mysql'
|
6
6
|
require 'active_record'
|
7
|
+
require 'digest/md5'
|
7
8
|
|
8
9
|
module Active
|
9
10
|
module Services
|
@@ -30,7 +31,7 @@ module Active
|
|
30
31
|
|
31
32
|
class Search
|
32
33
|
attr_accessor :api_key, :start_date, :end_date, :location, :channels, :keywords, :search, :radius, :limit, :sort, :page, :offset, :latitude, :longitude,
|
33
|
-
:view, :facet, :sort, :num_results, :asset_ids, :dma
|
34
|
+
:view, :facet, :sort, :num_results, :asset_ids, :dma, :city, :state, :country, :bounding_box
|
34
35
|
|
35
36
|
attr_reader :results, :endIndex, :pageSize, :searchTime, :numberOfResults, :end_point, :meta
|
36
37
|
|
@@ -39,11 +40,11 @@ module Active
|
|
39
40
|
|
40
41
|
def initialize(data={})
|
41
42
|
self.api_key = data[:api_key] || ""
|
42
|
-
self.location = data[:location]
|
43
|
+
self.location = data[:location]
|
43
44
|
self.zips = data[:zips] || []
|
44
45
|
self.channels = data[:channels] || []
|
45
46
|
self.keywords = data[:keywords] || []
|
46
|
-
self.radius = data[:radius] ||
|
47
|
+
self.radius = data[:radius] || nil
|
47
48
|
self.limit = data[:limit] || "10"
|
48
49
|
self.sort = data[:sort] || Sort.DATE_ASC
|
49
50
|
self.page = data[:page] || "1"
|
@@ -59,6 +60,10 @@ module Active
|
|
59
60
|
self.latitude = data[:latitude]
|
60
61
|
self.longitude = data[:longitude]
|
61
62
|
self.dma = data[:dma]
|
63
|
+
self.city = data[:city]
|
64
|
+
self.state = data[:state]
|
65
|
+
self.country = data[:country]
|
66
|
+
self.bounding_box = data[:bounding_box]
|
62
67
|
end
|
63
68
|
|
64
69
|
# Example
|
@@ -78,6 +83,7 @@ module Active
|
|
78
83
|
end
|
79
84
|
|
80
85
|
def location=(value)
|
86
|
+
return if value.nil?
|
81
87
|
@location = CGI.escape(value)
|
82
88
|
end
|
83
89
|
|
@@ -100,6 +106,16 @@ module Active
|
|
100
106
|
def asset_ids=(value)
|
101
107
|
@asset_ids = value
|
102
108
|
end
|
109
|
+
|
110
|
+
def bounding_box=(value)
|
111
|
+
return if value==nil
|
112
|
+
value = HashWithIndifferentAccess.new(value)
|
113
|
+
if value.has_key?("sw") && value.has_key?("ne")
|
114
|
+
@bounding_box=value
|
115
|
+
else
|
116
|
+
raise "bounding_box must be hash with keys sw and ne"
|
117
|
+
end
|
118
|
+
end
|
103
119
|
|
104
120
|
def asset_id=(value)
|
105
121
|
return if value.empty?
|
@@ -107,7 +123,8 @@ module Active
|
|
107
123
|
end
|
108
124
|
|
109
125
|
def end_point
|
110
|
-
meta_data
|
126
|
+
meta_data = ""
|
127
|
+
loc_str = ""
|
111
128
|
# CHANNELS
|
112
129
|
channel_keys = []
|
113
130
|
@channels.each do |c|
|
@@ -127,16 +144,27 @@ module Active
|
|
127
144
|
meta_data += temp_ids.join("+OR+")
|
128
145
|
end
|
129
146
|
# LOCATION
|
130
|
-
# 1 Look for
|
131
|
-
# 2 Look for
|
132
|
-
# 3 Look for
|
133
|
-
# 4 Look for a
|
134
|
-
|
147
|
+
# 1 Look for :city, :state, :country
|
148
|
+
# 2 Look for zip codes
|
149
|
+
# 3 Look for lat lng
|
150
|
+
# 4 Look for a formatted string "San Diego, CA, US"
|
151
|
+
# 5 Look for a dma
|
152
|
+
if @city or @state or @country
|
153
|
+
if @city
|
154
|
+
meta_data += "+AND+" unless meta_data == ""
|
155
|
+
meta_data += "meta:city=#{Search.double_encode_channel(@city)}"
|
156
|
+
end
|
157
|
+
if @state
|
158
|
+
meta_data += "+AND+" unless meta_data == ""
|
159
|
+
meta_data += "meta:state=#{Search.double_encode_channel(@state)}"
|
160
|
+
end
|
161
|
+
elsif !@zips.empty?
|
162
|
+
# if not @zips.empty?
|
135
163
|
loc_str = @zips.join(",")
|
136
164
|
elsif @latitude and @longitude
|
137
165
|
loc_str = "#{@latitude};#{@longitude}"
|
138
166
|
elsif @dma
|
139
|
-
|
167
|
+
|
140
168
|
meta_data += "+AND+" unless meta_data == ""
|
141
169
|
meta_data += "meta:dma=#{Search.double_encode_channel(@dma)}"
|
142
170
|
else
|
@@ -154,7 +182,42 @@ module Active
|
|
154
182
|
end
|
155
183
|
meta_data += "meta:startDate:daterange:#{@start_date}..#{@end_date}"
|
156
184
|
|
157
|
-
|
185
|
+
# BOUNDING BOX
|
186
|
+
if @bounding_box!=nil
|
187
|
+
#The values in the GSA metadata are shifted to prevent negative values. This was done b/c lat/long
|
188
|
+
# are searched as a number range and the GSA doesn't allow negative values in number ranges.
|
189
|
+
# We shift latitude values by 90 and longitude values by 180.
|
190
|
+
|
191
|
+
if @bounding_box[:sw].class==String
|
192
|
+
#String :bounding_box => { :sw => "37.695141,-123.013657", :ne => "37.832371,-122.356979"}
|
193
|
+
latitude1 = @bounding_box[:sw].split(",").first.to_f+90
|
194
|
+
latitude2 = @bounding_box[:ne].split(",").first.to_f+90
|
195
|
+
longitude1 = @bounding_box[:sw].split(",").last.to_f+180
|
196
|
+
longitude2 = @bounding_box[:ne].split(",").last.to_f+180
|
197
|
+
else
|
198
|
+
#hash query[:bounding_box] = { :sw => [123, 10], :ne => [222,10] }
|
199
|
+
latitude1 = @bounding_box[:sw].first.to_f+90
|
200
|
+
latitude2 = @bounding_box[:ne].first.to_f+90
|
201
|
+
longitude1 = @bounding_box[:sw].last.to_f+180
|
202
|
+
longitude2 = @bounding_box[:ne].last.to_f+180
|
203
|
+
end
|
204
|
+
meta_data += "+AND+" unless meta_data == ""
|
205
|
+
meta_data += "meta:latitudeShifted:#{latitude1}..#{latitude2}+AND+meta:longitudeShifted:#{longitude1}..#{longitude2}"
|
206
|
+
end
|
207
|
+
|
208
|
+
# url = "#{SEARCH_URL}/search?api_key=#{@api_key}&num=#{@num_results}&page=#{@page}&l=#{loc_str}&f=#{@facet}&v=#{@view}&r=#{@radius}&s=#{@sort}&k=#{@keywords.join("+")}&m=#{meta_data}"
|
209
|
+
urla = ["#{SEARCH_URL}/search?api_key=#{@api_key}"]
|
210
|
+
urla << "num=#{@num_results}" if @num_results
|
211
|
+
urla << "page=#{@page}" if @page
|
212
|
+
urla << "l=#{loc_str}" unless loc_str.nil? or loc_str.empty?
|
213
|
+
urla << "f=#{@facet}" if @facet
|
214
|
+
urla << "v=#{@view}" if @view
|
215
|
+
urla << "r=#{@radius}" if @radius
|
216
|
+
urla << "s=#{@sort}" if @sort
|
217
|
+
urla << "k=#{@keywords.join("+")}" if @keywords and !@keywords.empty?
|
218
|
+
urla << "m=#{meta_data}" if meta_data
|
219
|
+
|
220
|
+
return urla.join("&")
|
158
221
|
end
|
159
222
|
|
160
223
|
def search
|
@@ -163,8 +226,7 @@ module Active
|
|
163
226
|
http = Net::HTTP.new(searchurl.host, searchurl.port)
|
164
227
|
http.read_timeout = DEFAULT_TIMEOUT
|
165
228
|
|
166
|
-
puts "#{searchurl.path}?#{searchurl.query}"
|
167
|
-
|
229
|
+
puts "Active Search [GET] #{"#{searchurl.path}?#{searchurl.query}"}"
|
168
230
|
res = http.start { |http|
|
169
231
|
http.get("#{searchurl.path}?#{searchurl.query}")
|
170
232
|
}
|
@@ -176,7 +238,10 @@ module Active
|
|
176
238
|
@pageSize = parsed_json["pageSize"]
|
177
239
|
@searchTime = parsed_json["searchTime"]
|
178
240
|
@numberOfResults = parsed_json["numberOfResults"]
|
179
|
-
@results = parsed_json['_results'].collect { |a| Activity.new(a) }
|
241
|
+
@results = parsed_json['_results'].collect { |a| Activity.new(GSA.new(a)) }
|
242
|
+
|
243
|
+
Active.CACHE.set( Digest::MD5.hexdigest(end_point), self) if Active.CACHE
|
244
|
+
|
180
245
|
rescue JSON::ParserError => e
|
181
246
|
raise RuntimeError, "JSON::ParserError json=#{res.body}"
|
182
247
|
@endIndex = 0
|
@@ -223,10 +288,29 @@ module Active
|
|
223
288
|
# http://developer.active.com/docs/Activecom_Search_API_Reference
|
224
289
|
# returns an array of results and query info
|
225
290
|
def self.search(data=nil)
|
226
|
-
search
|
227
|
-
search.
|
228
|
-
|
291
|
+
search = Search.new(data)
|
292
|
+
search_hash = Digest::MD5.hexdigest(search.end_point)
|
293
|
+
puts "search_hash #{search_hash}"
|
294
|
+
cache = Search.return_cached(search_hash)
|
295
|
+
if cache != nil
|
296
|
+
return cache
|
297
|
+
else
|
298
|
+
search.search
|
299
|
+
return search
|
300
|
+
end
|
229
301
|
end
|
302
|
+
|
303
|
+
def self.return_cached key
|
304
|
+
if Active.CACHE
|
305
|
+
cached_version = Active.CACHE.get(key)
|
306
|
+
if cached_version
|
307
|
+
puts "Active Search [CACHE] #{key}"
|
308
|
+
return cached_version
|
309
|
+
end
|
310
|
+
end
|
311
|
+
nil
|
312
|
+
end
|
313
|
+
|
230
314
|
|
231
315
|
def []
|
232
316
|
@results
|
@@ -239,7 +323,6 @@ module Active
|
|
239
323
|
str.gsub!(/\-/,"%252D")
|
240
324
|
str
|
241
325
|
end
|
242
|
-
|
243
326
|
end
|
244
327
|
|
245
328
|
# TODO move to a reflection service
|
@@ -0,0 +1,403 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'cgi'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mysql'
|
6
|
+
require 'active_record'
|
7
|
+
|
8
|
+
module Active
|
9
|
+
module Services
|
10
|
+
|
11
|
+
# we should remove this class and just replace with symbols
|
12
|
+
class Sort
|
13
|
+
def self.DATE_ASC
|
14
|
+
"date_asc"
|
15
|
+
end
|
16
|
+
def self.DATE_DESC
|
17
|
+
"date_desc"
|
18
|
+
end
|
19
|
+
def self.RELEVANCE
|
20
|
+
"relevance"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# we should remove this class and just replace with symbols
|
25
|
+
class Facet
|
26
|
+
def self.ACTIVITIES
|
27
|
+
"activities"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Search
|
32
|
+
attr_accessor :api_key, :start_date, :end_date, :location, :channels, :keywords, :search, :radius, :limit, :sort, :page, :offset, :latitude, :longitude,
|
33
|
+
:view, :facet, :sort, :num_results, :asset_ids, :dma, :city, :state, :country
|
34
|
+
|
35
|
+
attr_reader :results, :endIndex, :pageSize, :searchTime, :numberOfResults, :end_point, :meta
|
36
|
+
|
37
|
+
SEARCH_URL = "http://search.active.com"
|
38
|
+
DEFAULT_TIMEOUT = 60
|
39
|
+
|
40
|
+
def initialize(data={})
|
41
|
+
self.api_key = data[:api_key] || ""
|
42
|
+
self.location = data[:location] || ""
|
43
|
+
self.zips = data[:zips] || []
|
44
|
+
self.channels = data[:channels] || []
|
45
|
+
self.keywords = data[:keywords] || []
|
46
|
+
self.radius = data[:radius] || nil
|
47
|
+
self.limit = data[:limit] || "10"
|
48
|
+
self.sort = data[:sort] || Sort.DATE_ASC
|
49
|
+
self.page = data[:page] || "1"
|
50
|
+
self.offset = data[:offset] || "0"
|
51
|
+
self.view = data[:view] || "json"
|
52
|
+
self.facet = data[:facet] || Facet.ACTIVITIES
|
53
|
+
self.num_results = data[:num_results] || "10"
|
54
|
+
self.search = data[:search] || ""
|
55
|
+
self.start_date = data[:start_date] || "today"
|
56
|
+
self.end_date = data[:end_date] || "+"
|
57
|
+
self.asset_ids = data[:asset_ids] || []
|
58
|
+
self.asset_id = data[:asset_id] || ""
|
59
|
+
self.latitude = data[:latitude]
|
60
|
+
self.longitude = data[:longitude]
|
61
|
+
self.dma = data[:dma]
|
62
|
+
self.city = data[:city]
|
63
|
+
self.state = data[:state]
|
64
|
+
self.country = data[:country]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Example
|
68
|
+
# Search.search( {:zips => "92121, 92078, 92114"} )
|
69
|
+
# or
|
70
|
+
# Search.new( {:zips => [92121, 92078, 92114]} )
|
71
|
+
def zips=(value)
|
72
|
+
if value.class == String
|
73
|
+
@zips = value.split(",").each { |k| k.strip! }
|
74
|
+
else
|
75
|
+
@zips = value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def zips
|
80
|
+
@zips
|
81
|
+
end
|
82
|
+
|
83
|
+
def location=(value)
|
84
|
+
@location = CGI.escape(value)
|
85
|
+
end
|
86
|
+
|
87
|
+
def keywords=(value)
|
88
|
+
if value.class == String
|
89
|
+
@keywords = value.gsub(",", " ").split(" ").each { |k| k.strip! }
|
90
|
+
else
|
91
|
+
@keywords = value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def channels=(value)
|
96
|
+
if value.class == String
|
97
|
+
@channels = value.split(",").each { |k| k.strip! }
|
98
|
+
else
|
99
|
+
@channels = value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def asset_ids=(value)
|
104
|
+
@asset_ids = value
|
105
|
+
end
|
106
|
+
|
107
|
+
def asset_id=(value)
|
108
|
+
return if value.empty?
|
109
|
+
@asset_ids<<value
|
110
|
+
end
|
111
|
+
|
112
|
+
def end_point
|
113
|
+
meta_data = ""
|
114
|
+
loc_str = ""
|
115
|
+
# CHANNELS
|
116
|
+
channel_keys = []
|
117
|
+
@channels.each do |c|
|
118
|
+
c.to_sym
|
119
|
+
if Categories.CHANNELS.include?(c)
|
120
|
+
channel_keys << Categories.CHANNELS[c]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
meta_data = channel_keys.collect { |channel| "meta:channel=#{Search.double_encode_channel(channel)}" }.join("+OR+")
|
124
|
+
# ASSET IDS
|
125
|
+
unless asset_ids.empty?
|
126
|
+
meta_data += "+AND+" unless meta_data == ""
|
127
|
+
temp_ids = []
|
128
|
+
asset_ids.each do |id|
|
129
|
+
temp_ids << "meta:" + CGI.escape("assetId=#{id.gsub("-","%2d")}")
|
130
|
+
end
|
131
|
+
meta_data += temp_ids.join("+OR+")
|
132
|
+
end
|
133
|
+
# LOCATION
|
134
|
+
# 1 Look for :city, :state, :country
|
135
|
+
# 2 Look for zip codes
|
136
|
+
# 3 Look for lat lng
|
137
|
+
# 4 Look for a formatted string "San Diego, CA, US"
|
138
|
+
# 5 Look for a dma
|
139
|
+
|
140
|
+
if @city or @state or @country
|
141
|
+
if @city
|
142
|
+
meta_data += "+AND+" unless meta_data == ""
|
143
|
+
meta_data += "meta:city=#{Search.double_encode_channel(@city)}"
|
144
|
+
end
|
145
|
+
if @state
|
146
|
+
meta_data += "+AND+" unless meta_data == ""
|
147
|
+
meta_data += "meta:state=#{Search.double_encode_channel(@state)}"
|
148
|
+
end
|
149
|
+
elsif !@zips.empty?
|
150
|
+
# if not @zips.empty?
|
151
|
+
loc_str = @zips.join(",")
|
152
|
+
elsif @latitude and @longitude
|
153
|
+
loc_str = "#{@latitude};#{@longitude}"
|
154
|
+
elsif @dma
|
155
|
+
|
156
|
+
meta_data += "+AND+" unless meta_data == ""
|
157
|
+
meta_data += "meta:dma=#{Search.double_encode_channel(@dma)}"
|
158
|
+
else
|
159
|
+
loc_str = @location
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
# AND DATE
|
164
|
+
meta_data += "+AND+" unless meta_data == ""
|
165
|
+
if @start_date.class == Date
|
166
|
+
@start_date = URI.escape(@start_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F")
|
167
|
+
end
|
168
|
+
if @end_date.class == Date
|
169
|
+
@end_date = URI.escape(@end_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F")
|
170
|
+
end
|
171
|
+
meta_data += "meta:startDate:daterange:#{@start_date}..#{@end_date}"
|
172
|
+
|
173
|
+
# url = "#{SEARCH_URL}/search?api_key=#{@api_key}&num=#{@num_results}&page=#{@page}&l=#{loc_str}&f=#{@facet}&v=#{@view}&r=#{@radius}&s=#{@sort}&k=#{@keywords.join("+")}&m=#{meta_data}"
|
174
|
+
urla = ["#{SEARCH_URL}/search?api_key=#{@api_key}"]
|
175
|
+
urla << "num=#{@num_results}" if @num_results
|
176
|
+
urla << "page=#{@page}" if @page
|
177
|
+
urla << "l=#{loc_str}" unless loc_str.empty?
|
178
|
+
urla << "f=#{@facet}" if @facet
|
179
|
+
urla << "v=#{@view}" if @view
|
180
|
+
urla << "r=#{@radius}" if @radius
|
181
|
+
urla << "s=#{@sort}" if @sort
|
182
|
+
urla << "k=#{@keywords.join("+")}" if @keywords and !@keywords.empty?
|
183
|
+
urla << "m=#{meta_data}" if meta_data
|
184
|
+
|
185
|
+
return urla.join("&")
|
186
|
+
end
|
187
|
+
|
188
|
+
def search
|
189
|
+
searchurl = URI.parse(end_point)
|
190
|
+
req = Net::HTTP::Get.new(searchurl.path)
|
191
|
+
http = Net::HTTP.new(searchurl.host, searchurl.port)
|
192
|
+
http.read_timeout = DEFAULT_TIMEOUT
|
193
|
+
|
194
|
+
puts "#{searchurl.path}?#{searchurl.query}"
|
195
|
+
|
196
|
+
res = http.start { |http|
|
197
|
+
http.get("#{searchurl.path}?#{searchurl.query}")
|
198
|
+
}
|
199
|
+
|
200
|
+
if (200..307).include?(res.code.to_i)
|
201
|
+
begin
|
202
|
+
parsed_json = JSON.parse(res.body)
|
203
|
+
@endIndex = parsed_json["endIndex"]
|
204
|
+
@pageSize = parsed_json["pageSize"]
|
205
|
+
@searchTime = parsed_json["searchTime"]
|
206
|
+
@numberOfResults = parsed_json["numberOfResults"]
|
207
|
+
@results = parsed_json['_results'].collect { |a| GSA.new(a) }
|
208
|
+
rescue JSON::ParserError => e
|
209
|
+
raise RuntimeError, "JSON::ParserError json=#{res.body}"
|
210
|
+
@endIndex = 0
|
211
|
+
@pageSize = 0
|
212
|
+
@searchTime = 0
|
213
|
+
@numberOfResults = 0
|
214
|
+
@results = []
|
215
|
+
end
|
216
|
+
|
217
|
+
else
|
218
|
+
raise RuntimeError, "Active Search responded with a #{res.code} for your query."
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# examples
|
223
|
+
#
|
224
|
+
#
|
225
|
+
# = Keywords =
|
226
|
+
# Keywords can be set like this
|
227
|
+
# Search.new({:keywords => "Dog,Cat,Cow"})
|
228
|
+
# Search.new({:keywords => %w(Dog Cat Cow)})
|
229
|
+
# Search.new({:keywords => ["Dog","Cat","Cow"]})
|
230
|
+
#
|
231
|
+
# = Location =
|
232
|
+
# The location will be set in this order and will override other values. For example is you set a zip code and a location only the zip will be used.
|
233
|
+
#
|
234
|
+
# 1 Look for zip codes
|
235
|
+
# Search.search( {:zips => "92121, 92078, 92114"} )
|
236
|
+
# Search.search( {:zips => %w(92121, 92078, 92114)} )
|
237
|
+
# Search.search( {:zips => [92121, 92078, 92114]} )
|
238
|
+
#
|
239
|
+
# 2 Look for lat lng
|
240
|
+
# Search.search( {:latitude=>"37.785895", :longitude=>"-122.40638"} )
|
241
|
+
#
|
242
|
+
# 3 Look for a formatted string "San Diego, CA, US"
|
243
|
+
# Search.search( {:location = "San Diego, CA, US"} )
|
244
|
+
#
|
245
|
+
# 4 Look for a DMA
|
246
|
+
# Search.new({:dma=>"San Francisco - Oakland - San Jose"})
|
247
|
+
#
|
248
|
+
# = How to look at the results =
|
249
|
+
#
|
250
|
+
#
|
251
|
+
# http://developer.active.com/docs/Activecom_Search_API_Reference
|
252
|
+
# returns an array of results and query info
|
253
|
+
def self.search(data=nil)
|
254
|
+
search = Search.new(data)
|
255
|
+
search.search
|
256
|
+
return search
|
257
|
+
end
|
258
|
+
|
259
|
+
def []
|
260
|
+
@results
|
261
|
+
end
|
262
|
+
|
263
|
+
private
|
264
|
+
def self.double_encode_channel str
|
265
|
+
str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
266
|
+
str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
267
|
+
str.gsub!(/\-/,"%252D")
|
268
|
+
str
|
269
|
+
end
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
# TODO move to a reflection service
|
274
|
+
class Categories
|
275
|
+
def self.CHANNELS
|
276
|
+
{
|
277
|
+
:active_lifestyle => '',
|
278
|
+
:fitness => 'Fitness',
|
279
|
+
:body_building => 'Fitness\Body Building',
|
280
|
+
:boxing => 'Fitness\Boxing',
|
281
|
+
:weight_lifting => 'Fitness\Weight Lifting',
|
282
|
+
:gear => 'Gear',
|
283
|
+
:lifestyle_vehicles => 'Lifestyle Vehicles',
|
284
|
+
:mind_mody => 'Mind & Body',
|
285
|
+
:meditation => 'Mind & Body\Meditation',
|
286
|
+
:pilates => 'Mind & Body\Pilates',
|
287
|
+
:yoga => 'Mind & Body\Yoga',
|
288
|
+
:nutrition => 'Nutrition',
|
289
|
+
:travel => 'Travel',
|
290
|
+
:women => 'Women',
|
291
|
+
:other => 'Other',
|
292
|
+
:corporate => 'Corporate',
|
293
|
+
:not_specified => 'Not Specified',
|
294
|
+
:unknown => 'Unknown',
|
295
|
+
:special_interest => 'Special+Interest',
|
296
|
+
:giving => 'Giving',
|
297
|
+
:parks_recreation => 'Parks & Recreation',
|
298
|
+
:gear => 'Parks & Recreation\Gear',
|
299
|
+
:mind_body => 'Parks & Recreation\Mind & Body',
|
300
|
+
:travel => 'Parks & Recreation\Travel',
|
301
|
+
:vehicles => 'Parks & Recreation\Vehicles',
|
302
|
+
:women => 'Parks & Recreation\Women',
|
303
|
+
:reunions => 'Reunions',
|
304
|
+
:sports => 'Sports',
|
305
|
+
:action_sports => 'Action Sports',
|
306
|
+
:auto_racing => 'Action Sports\Auto Racing',
|
307
|
+
:bmx => 'Action Sports\BMX',
|
308
|
+
:dirt_bike_racing => 'Action Sports\Dirt Bike Racing',
|
309
|
+
:motocross => 'Action Sports\Motocross',
|
310
|
+
:motorcycle_racing => 'Action Sports\Motorcycle Racing',
|
311
|
+
:skateboarding => 'Action Sports\Skateboarding',
|
312
|
+
:skydiving => 'Action Sports\Skydiving',
|
313
|
+
:surfing => 'Action Sports\Surfing',
|
314
|
+
:wake_kite_boarding => 'Action Sports\Wake/Kite Boarding',
|
315
|
+
:water_skiing => 'Action Sports\Water Skiing',
|
316
|
+
:wind_surfing => 'Action Sports\Wind Surfing',
|
317
|
+
:baseball => 'Baseball',
|
318
|
+
:little_league_baseball => 'Baseball\Little League Baseball',
|
319
|
+
:tee_ball => 'Baseball\Tee Ball',
|
320
|
+
:basketball => 'Basketball',
|
321
|
+
:cheerleading => 'Cheerleading',
|
322
|
+
:cycling => 'Cycling',
|
323
|
+
:field_hockey => 'Field Hockey',
|
324
|
+
:football => 'Football',
|
325
|
+
:flag_football => 'Football\Flag Football',
|
326
|
+
:football_au => 'Football\Football-AU',
|
327
|
+
:golf => 'Golf',
|
328
|
+
:ice_hockey => 'Ice Hockey',
|
329
|
+
:lacrosse => 'Lacrosse',
|
330
|
+
:more_sports => 'More Sports',
|
331
|
+
:adventure_racing => 'More Sports\Adventure Racing',
|
332
|
+
:archery => 'More Sports\Archery',
|
333
|
+
:badminton => 'More Sports\Badminton',
|
334
|
+
:billiards => 'More Sports\Billiards',
|
335
|
+
:bowling => 'More Sports\Bowling',
|
336
|
+
:cricket => 'More Sports\Cricket',
|
337
|
+
:croquet => 'More Sports\Croquet',
|
338
|
+
:curling => 'More Sports\Curling',
|
339
|
+
:dance => 'More Sports\Dance',
|
340
|
+
:disc_sports => 'More Sports\Disc Sports',
|
341
|
+
:dodgeball => 'More Sports\Dodgeball',
|
342
|
+
:duathlon => 'More Sports\Duathlon',
|
343
|
+
:equestrian => 'More Sports\Equestrian',
|
344
|
+
:fencing => 'More Sports\Fencing',
|
345
|
+
:figure_skating => 'More Sports\Figure Skating',
|
346
|
+
:gymnastics => 'More Sports\Gymnastics',
|
347
|
+
:inline_hockey => 'More Sports\Inline Hockey',
|
348
|
+
:inline_skating => 'More Sports\Inline Skating',
|
349
|
+
:kickball => 'More Sports\Kickball',
|
350
|
+
:martial_arts => 'More Sports\Martial Arts',
|
351
|
+
:paintball => 'More Sports\Paintball',
|
352
|
+
:polo => 'More Sports\Polo',
|
353
|
+
:racquetball => 'More Sports\Racquetball',
|
354
|
+
:rowing => 'More Sports\Rowing',
|
355
|
+
:rugby => 'More Sports\Rugby',
|
356
|
+
:scouting => 'More Sports\Scouting',
|
357
|
+
:scuba_diving => 'More Sports\Scuba Diving',
|
358
|
+
:skating => 'More Sports\Skating',
|
359
|
+
:squash => 'More Sports\Squash',
|
360
|
+
:ultimate_frisbee => 'More Sports\Ultimate Frisbee',
|
361
|
+
:water_polo => 'More Sports\Water Polo',
|
362
|
+
:mountain_biking => 'Mountain Biking',
|
363
|
+
:outdoors => 'Outdoors',
|
364
|
+
:canoeing => 'Outdoors\Canoeing',
|
365
|
+
:climbing => 'Outdoors\Climbing',
|
366
|
+
:hiking => 'Outdoors\Hiking',
|
367
|
+
:kayaking => 'Outdoors\Kayaking',
|
368
|
+
:orienteering => 'Outdoors\Orienteering',
|
369
|
+
:outrigging => 'Outdoors\Outrigging',
|
370
|
+
:rafting => 'Outdoors\Rafting',
|
371
|
+
:racquetball => 'Racquetball',
|
372
|
+
:rugby => 'Rugby',
|
373
|
+
:running => 'Running',
|
374
|
+
:cross_country => 'Running\Cross Country',
|
375
|
+
:marathon_running => 'Running\Marathon Running',
|
376
|
+
:track_field => 'Running\Track & Field',
|
377
|
+
:trail_running => 'Running\Trail Running',
|
378
|
+
:sailing => 'Sailing',
|
379
|
+
:snow_sports => 'Snow Sports',
|
380
|
+
:skiing => 'Snow Sports\Skiing',
|
381
|
+
:snowboarding => 'Snow Sports\Snowboarding',
|
382
|
+
:snowshoeing => 'Snow Sports\Snowshoeing',
|
383
|
+
:soccer => 'Soccer',
|
384
|
+
:softball => 'Softball',
|
385
|
+
:softball_dixie => 'Softball\Softball-Dixie',
|
386
|
+
:softball_fast_pitch => 'Softball\Softball-Fast Pitch',
|
387
|
+
:softball_slow_pitch => 'Softball\Softball-Slow Pitch',
|
388
|
+
:squash => 'Squash',
|
389
|
+
:swimming => 'Swimming',
|
390
|
+
:diving => 'Swimming\Diving',
|
391
|
+
:tennis => 'Tennis',
|
392
|
+
:other_tennis => 'Tennis\Other Tennis',
|
393
|
+
:usta => 'Tennis\USTA',
|
394
|
+
:triathlon => 'Triathlon',
|
395
|
+
:volleyball => 'Volleyball',
|
396
|
+
:walking => 'Walking',
|
397
|
+
:wrestling => 'Wrestling'
|
398
|
+
}
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
end
|
403
|
+
end
|