Active 0.0.42 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.irbrc +21 -0
- data/.rspec +1 -0
- data/.rvmrc +2 -0
- data/Active.gemspec +28 -29
- data/Gemfile +4 -0
- data/History.txt +5 -2
- data/{README.txt → README.md} +4 -20
- data/Rakefile +11 -17
- data/lib/Active.rb +11 -79
- data/lib/active/activity.rb +7 -0
- data/lib/active/article.rb +7 -0
- data/lib/active/asset.rb +205 -0
- data/lib/active/errors.rb +9 -0
- data/lib/active/query.rb +225 -0
- data/lib/active/result.rb +7 -0
- data/lib/active/results.rb +6 -0
- data/lib/active/training.rb +7 -0
- data/lib/active/version.rb +3 -0
- data/lib/ext/hash_extensions.rb +8 -0
- data/spec/asset_spec.rb +47 -0
- data/spec/search_spec.rb +383 -432
- data/spec/spec_helper.rb +23 -2
- metadata +113 -116
- data/bin/Active +0 -7
- data/lib/.DS_Store +0 -0
- data/lib/services/.DS_Store +0 -0
- data/lib/services/IActivity.rb +0 -39
- data/lib/services/_ats.rb +0 -215
- data/lib/services/active_works.rb +0 -167
- data/lib/services/activity.rb +0 -512
- data/lib/services/address.rb +0 -17
- data/lib/services/ats.rb +0 -229
- data/lib/services/dto/user.rb +0 -9
- data/lib/services/gsa.rb +0 -205
- data/lib/services/reg_center.rb +0 -270
- data/lib/services/sanitize.rb +0 -108
- data/lib/services/search.rb +0 -494
- data/lib/services/validators.rb +0 -124
- data/rspec-tm +0 -1
- data/rvmrc +0 -1
- data/spec/.DS_Store +0 -0
- data/spec/Active_spec.rb +0 -28
- data/spec/activeworks_spec.rb +0 -60
- data/spec/activity_spec.rb +0 -421
- data/spec/ats_spec.rb +0 -106
- data/spec/benchmark/search_bench.rb +0 -55
- data/spec/custom_matchers_spec.rb +0 -27
- data/spec/gsa_spec.rb +0 -210
- data/spec/reg_spec.rb +0 -173
- data/spec/search_memcached_spec.rb +0 -42
- data/spec/validators_spec.rb +0 -19
- data/test/test_Active.rb +0 -0
- data/version.txt +0 -1
data/.gitignore
ADDED
data/.irbrc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Project-specific .irbrc file
|
2
|
+
|
3
|
+
# In order for this file to be picked up automatically by irb, you need to add
|
4
|
+
# the following code (or equivalent) to your own ~/.irbrc file:
|
5
|
+
|
6
|
+
# if Dir.pwd != File.expand_path("~")
|
7
|
+
# local_irbrc = File.expand_path '.irbrc'
|
8
|
+
# if File.exist? local_irbrc
|
9
|
+
# puts "Loading #{local_irbrc}"
|
10
|
+
# load local_irbrc
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
|
14
|
+
# When irb is started within this project folder (read: during gem development)
|
15
|
+
# this file will add lib/ to the load_path and require the gem.
|
16
|
+
|
17
|
+
# Doesn't work if you have the Active Gem also installed
|
18
|
+
|
19
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
|
20
|
+
require 'lib/Active'
|
21
|
+
puts "Using Active v#{Active::VERSION}"
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.rvmrc
ADDED
data/Active.gemspec
CHANGED
@@ -1,36 +1,35 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "active/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |s|
|
4
|
-
s.name
|
5
|
-
s.version
|
6
|
-
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
6
|
+
s.name = "Active"
|
7
|
+
s.version = Active::VERSION
|
8
|
+
s.date = "2012-01-03"
|
9
|
+
s.authors = ["Jonathan Spooner, Marc Leglise"]
|
10
|
+
s.email = ["jspooner@gmail.com"]
|
11
|
+
s.homepage = "http://developer.active.com/docs/Activecom_Search_API_Reference"
|
12
|
+
s.summary = %q{Search api for Active Network}
|
11
13
|
s.description = %q{Search api for Active Network}
|
12
|
-
s.email = %q{jspooner [at] gmail.com}
|
13
|
-
s.executables = ["Active"]
|
14
|
-
s.extra_rdoc_files = ["History.txt", "README.txt", "bin/Active", "version.txt"]
|
15
|
-
s.files = [".bnsignore", "Active.gemspec", "History.txt", "README.txt", "Rakefile", "bin/Active", "lib/Active.rb", "lib/services/activity.rb", "lib/services/search.rb", "spec/.DS_Store", "spec/Active_spec.rb", "spec/activity_spec.rb", "spec/search_spec.rb", "spec/spec_helper.rb", "test/test_Active.rb", "version.txt"]
|
16
|
-
s.homepage = %q{http://developer.active.com/docs/Activecom_Search_API_Reference}
|
17
|
-
s.rdoc_options = ["--main", "README.txt"]
|
18
|
-
s.require_paths = ["lib"]
|
19
|
-
s.rubyforge_project = %q{Active}
|
20
|
-
s.rubygems_version = %q{1.3.7}
|
21
|
-
s.summary = %q{Search api for Active Network}
|
22
|
-
s.test_files = ["test/test_Active.rb"]
|
23
14
|
|
24
|
-
|
25
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
-
s.specification_version = 3
|
15
|
+
s.rubyforge_project = "Active"
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.extra_rdoc_files = ["History.txt", "README.md"]
|
23
|
+
s.rdoc_options = ["--main", "README.md"]
|
24
|
+
|
25
|
+
s.add_dependency "json", "~> 1"
|
26
|
+
s.add_dependency "hashie", "~> 1"
|
27
|
+
s.add_dependency "activesupport", "> 3"
|
28
|
+
s.add_dependency "htmlentities", "> 4"
|
29
|
+
# s.add_dependency "savon", "= 0.7.9"
|
30
|
+
# s.add_dependency "dalli", "= 0.9.8"
|
31
|
+
|
32
|
+
s.add_development_dependency "rspec", "~> 2"
|
33
|
+
s.add_development_dependency "metric_fu", "~> 2"
|
34
|
+
# s.add_development_dependency "mocha", "= 0.9.8"
|
36
35
|
end
|
data/Gemfile
ADDED
data/History.txt
CHANGED
data/{README.txt → README.md}
RENAMED
@@ -1,33 +1,17 @@
|
|
1
1
|
Active
|
2
|
-
by Jonathan Spooner and
|
2
|
+
by Jonathan Spooner and Marc Leglise
|
3
3
|
http://developer.active.com/docs/Activecom_Search_API_Reference
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
7
|
Search api for Active Network
|
8
8
|
|
9
|
-
|
9
|
+
For use with Ruby 1.9
|
10
10
|
|
11
|
-
|
11
|
+
== Development
|
12
12
|
|
13
|
-
|
13
|
+
To use in irb do `rake install` then `irb` and `require 'Active'`
|
14
14
|
|
15
|
-
Search.search( {:location => "San Diego, CA, US"} )
|
16
|
-
|
17
|
-
List all categories
|
18
|
-
Active::Services::Search.CHANNELS.each do |key, value|
|
19
|
-
puts key.to_s.humanize
|
20
|
-
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
== REQUIREMENTS:
|
25
|
-
|
26
|
-
* none
|
27
|
-
|
28
|
-
== INSTALL:
|
29
|
-
|
30
|
-
* sudo gem install Active
|
31
15
|
|
32
16
|
== LICENSE:
|
33
17
|
|
data/Rakefile
CHANGED
@@ -1,24 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
rescue LoadError
|
4
|
+
abort '### Please install the "bundler" gem ###'
|
5
|
+
end
|
1
6
|
|
2
7
|
begin
|
3
|
-
require '
|
8
|
+
require 'metric_fu'
|
4
9
|
rescue LoadError
|
5
|
-
abort '### Please install the "bones" gem ###'
|
6
10
|
end
|
7
11
|
|
8
|
-
task :default => 'test:run'
|
9
|
-
task 'gem:release' => 'test:run'
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
url 'http://developer.active.com/docs/Activecom_Search_API_Reference'
|
16
|
-
gem.extras[:post_install_message] = <<-MSG
|
17
|
-
--------------------------
|
18
|
-
Welcome to Active Network
|
19
|
-
--------------------------
|
20
|
-
MSG
|
21
|
-
depend_on 'savon', '0.7.9'
|
22
|
-
depend_on 'dalli', '0.9.8'
|
23
|
-
}
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
15
|
+
# t.pattern = 'spec/search_spec.rb'
|
16
|
+
end
|
24
17
|
|
18
|
+
task :default => :spec
|
data/lib/Active.rb
CHANGED
@@ -1,80 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# attr_reader :CACHE
|
5
|
-
# attr_accessor :CACHE
|
6
|
-
|
7
|
-
# :stopdoc:
|
8
|
-
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
9
|
-
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
10
|
-
# :startdoc:
|
11
|
-
|
12
|
-
# Returns the version string for the library.
|
13
|
-
#
|
14
|
-
def self.version
|
15
|
-
@version ||= File.read(path('version.txt')).strip
|
16
|
-
end
|
17
|
-
|
18
|
-
# Returns the library path for the module. If any arguments are given,
|
19
|
-
# they will be joined to the end of the libray path using
|
20
|
-
# <tt>File.join</tt>.
|
21
|
-
#
|
22
|
-
def self.libpath( *args, &block )
|
23
|
-
rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
24
|
-
if block
|
25
|
-
begin
|
26
|
-
$LOAD_PATH.unshift LIBPATH
|
27
|
-
rv = block.call
|
28
|
-
ensure
|
29
|
-
$LOAD_PATH.shift
|
30
|
-
end
|
31
|
-
end
|
32
|
-
return rv
|
33
|
-
end
|
34
|
-
|
35
|
-
# Returns the lpath for the module. If any arguments are given,
|
36
|
-
# they will be joined to the end of the path using
|
37
|
-
# <tt>File.join</tt>.
|
38
|
-
#
|
39
|
-
def self.path( *args, &block )
|
40
|
-
rv = args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
41
|
-
if block
|
42
|
-
begin
|
43
|
-
$LOAD_PATH.unshift PATH
|
44
|
-
rv = block.call
|
45
|
-
ensure
|
46
|
-
$LOAD_PATH.shift
|
47
|
-
end
|
48
|
-
end
|
49
|
-
return rv
|
50
|
-
end
|
1
|
+
require 'active/version'
|
2
|
+
require 'ext/hash_extensions.rb'
|
51
3
|
|
52
|
-
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
Dir.glob(search_me).sort.each {|rb| require rb}
|
63
|
-
end
|
64
|
-
|
65
|
-
# Active.memcache_host = "localhost:11211"
|
66
|
-
def self.memcache_host(url)
|
67
|
-
require 'dalli'
|
68
|
-
@CACHE = Dalli::Client.new(url)
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.CACHE
|
72
|
-
@CACHE
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
end # module Active
|
77
|
-
|
78
|
-
Active.require_all_libs_relative_to(__FILE__)
|
79
|
-
Active.require_all_libs_relative_to(__FILE__, 'services')
|
80
|
-
require 'savon'
|
4
|
+
module Active
|
5
|
+
# require files in order!
|
6
|
+
[
|
7
|
+
:errors, :query, :asset, :results,
|
8
|
+
:activity, :article, :result, :training
|
9
|
+
].each do |constant|
|
10
|
+
require "active/#{constant.to_s}"
|
11
|
+
end
|
12
|
+
end
|
data/lib/active/asset.rb
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'json'
|
3
|
+
require 'htmlentities'
|
4
|
+
require 'active_support/multibyte/unicode'
|
5
|
+
|
6
|
+
module Active
|
7
|
+
class Asset < Hashie::Mash
|
8
|
+
|
9
|
+
# * No punctuation: Returns the value of the hash for that key, or nil if none exists.
|
10
|
+
# * Assignment (<tt>=</tt>): Sets the attribute of the given method name.
|
11
|
+
# * Existence (<tt>?</tt>): Returns true or false depending on whether that key has been set.
|
12
|
+
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it as "touch" for mashes.
|
13
|
+
#
|
14
|
+
# == Basic Example
|
15
|
+
#
|
16
|
+
# mash = Mash.new
|
17
|
+
# mash.name? # => false
|
18
|
+
# mash.name = "Bob"
|
19
|
+
# mash.name # => "Bob"
|
20
|
+
# mash.name? # => true
|
21
|
+
#
|
22
|
+
# == Hash Conversion Example
|
23
|
+
#
|
24
|
+
# hash = {:a => {:b => 23, :d => {:e => "abc"}}, :f => [{:g => 44, :h => 29}, 12]}
|
25
|
+
# mash = Mash.new(hash)
|
26
|
+
# mash.a.b # => 23
|
27
|
+
# mash.a.d.e # => "abc"
|
28
|
+
# mash.f.first.g # => 44
|
29
|
+
# mash.f.last # => 12
|
30
|
+
#
|
31
|
+
# == Bang Example
|
32
|
+
#
|
33
|
+
# mash = Mash.new
|
34
|
+
# mash.author # => nil
|
35
|
+
# mash.author! # => <Mash>
|
36
|
+
#
|
37
|
+
# mash = Mash.new
|
38
|
+
# mash.author!.name = "Michael Bleigh"
|
39
|
+
# mash.author # => <Mash name="Michael Bleigh">
|
40
|
+
#
|
41
|
+
def title
|
42
|
+
return @title if @title
|
43
|
+
if self.title?
|
44
|
+
# Notice we have to use self['hash'] to get the original value so we don't stackoverflow
|
45
|
+
@title = ActiveSupport::Multibyte::Unicode.tidy_bytes(self['title'])
|
46
|
+
@title = @title.split("|")[0].strip if @title.include?("|")
|
47
|
+
@title = @title.gsub(/<\/?[^>]*>/, "")
|
48
|
+
@title = @title.gsub("...", "")
|
49
|
+
@title = ::HTMLEntities.new.decode( @title )
|
50
|
+
end
|
51
|
+
@title
|
52
|
+
end
|
53
|
+
|
54
|
+
def description
|
55
|
+
return @description if @description
|
56
|
+
if self.meta!.summary?
|
57
|
+
# Notice we have to use self['hash'] to get the original value so we don't stackoverflow
|
58
|
+
@description = ActiveSupport::Multibyte::Unicode.tidy_bytes( self.meta.summary )
|
59
|
+
@description = @description.gsub(/<\/?[^>]*>/, "")
|
60
|
+
@description = ::HTMLEntities.new.decode( @description )
|
61
|
+
end
|
62
|
+
@description
|
63
|
+
end
|
64
|
+
|
65
|
+
def start_date
|
66
|
+
if self.meta!.startDate?
|
67
|
+
if self.meta!.startTime?
|
68
|
+
Time.parse("#{self.meta.startDate} #{self.meta.startTime}")
|
69
|
+
else
|
70
|
+
Date.parse(self.meta.startDate)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def asset_id
|
78
|
+
aid = self.meta!.assetId
|
79
|
+
if aid.kind_of?(Array)
|
80
|
+
aid = aid.first
|
81
|
+
end
|
82
|
+
aid.upcase
|
83
|
+
end
|
84
|
+
|
85
|
+
def address
|
86
|
+
if self.meta['address']
|
87
|
+
return self.meta['address']
|
88
|
+
elsif self.meta['location']
|
89
|
+
return self.meta['location']
|
90
|
+
else
|
91
|
+
return "#{self.meta.city}, #{self.meta.state}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def zip
|
96
|
+
self.meta['zip'] # an inheritated object defines zip so we need to override it.
|
97
|
+
end
|
98
|
+
|
99
|
+
class << self
|
100
|
+
def factory(data)
|
101
|
+
begin
|
102
|
+
category = data['meta']['category']
|
103
|
+
rescue NoMethodError
|
104
|
+
category = nil
|
105
|
+
end
|
106
|
+
|
107
|
+
type = case category
|
108
|
+
when 'Activities'
|
109
|
+
Active::Activity
|
110
|
+
when 'Articles'
|
111
|
+
Active::Article
|
112
|
+
when 'Training plans'
|
113
|
+
Active::Training
|
114
|
+
else
|
115
|
+
Active::Asset
|
116
|
+
end
|
117
|
+
type.new(data)
|
118
|
+
end
|
119
|
+
|
120
|
+
# this code smells
|
121
|
+
def find(asset_ids=nil)
|
122
|
+
raise Active::InvalidOption, "Couldn't find Asset without an ID" if asset_ids.nil?
|
123
|
+
query = Active::Query.new
|
124
|
+
ids = asset_ids.kind_of?(Array) ? asset_ids : [asset_ids]
|
125
|
+
query.options[:meta][:assetId] = ids.collect{ |id| id.gsub("-","%2d") }
|
126
|
+
|
127
|
+
# Executes the actual search API call
|
128
|
+
res = query.search
|
129
|
+
|
130
|
+
# Ensure we have found all of the IDs requested, otherwise raise an error
|
131
|
+
# that includes which ID(s) are missing.
|
132
|
+
if res['numberOfResults'] != ids.length
|
133
|
+
missing_ids = Array.new(ids)
|
134
|
+
res['_results'].each do |r|
|
135
|
+
found_id = r['meta']['assetId'] & missing_ids
|
136
|
+
missing_ids -= found_id
|
137
|
+
end
|
138
|
+
raise Active::RecordNotFound, "Couldn't find record with asset_id: #{missing_ids.join(',')}"
|
139
|
+
end
|
140
|
+
|
141
|
+
a = []
|
142
|
+
res['_results'].collect do |d|
|
143
|
+
t = self.new(d)
|
144
|
+
a << t
|
145
|
+
end
|
146
|
+
|
147
|
+
if a.length == 1
|
148
|
+
return a.first
|
149
|
+
else
|
150
|
+
return a
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Active::Activity.find_by_url("http://www.active.com#{request.fullpath}")
|
155
|
+
# url = http://search.active.com/search?v=list&m=site:www.active.com/running/san-diego-ca/americas-finest-city-half-marathon-and-5k-2011
|
156
|
+
def find_by_url(url)
|
157
|
+
raise Active::InvalidOption, "Couldn't find Asset without a url" if url.nil?
|
158
|
+
query = Active::Query.new
|
159
|
+
query.options[:m] << "site:#{url}"
|
160
|
+
|
161
|
+
# Executes the actual search API call
|
162
|
+
res = query.search
|
163
|
+
if res['numberOfResults'].to_i < 1
|
164
|
+
raise Active::RecordNotFound, "Couldn't find record with asset_id: #{url}"
|
165
|
+
end
|
166
|
+
|
167
|
+
a = []
|
168
|
+
res['_results'].collect do |d|
|
169
|
+
t = self.new(d)
|
170
|
+
a << t
|
171
|
+
end
|
172
|
+
|
173
|
+
if a.length == 1
|
174
|
+
return a.first
|
175
|
+
else
|
176
|
+
return a
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Example
|
181
|
+
# Asset.zip("92121")
|
182
|
+
[
|
183
|
+
:sort, :order, :limit, :per_page, :page,
|
184
|
+
:category, :keywords, :channel, :splitMediaType,
|
185
|
+
:location, :state, :city, :zip, :zips, :bounding_box, :dma, :near,
|
186
|
+
:date_range, :future, :past, :today, :radius
|
187
|
+
].each do |method_name|
|
188
|
+
define_method(method_name) do |*val|
|
189
|
+
Active::Query.new(:facet => self.facet).send(method_name, *val)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# We have several different types of data in the Search index. To restrict a search to a particular type, use the facet parameter. The available values are:
|
194
|
+
# activities - things like running events or camps
|
195
|
+
# results - race results from results.active.com
|
196
|
+
# training - training plans
|
197
|
+
# articles - articles on active.com and ihoops.com
|
198
|
+
# This method should be overridden in child classes to return the appropriate type string.
|
199
|
+
def facet
|
200
|
+
''
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|