Active 0.0.42 → 0.1.7

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.
Files changed (54) hide show
  1. data/.gitignore +6 -0
  2. data/.irbrc +21 -0
  3. data/.rspec +1 -0
  4. data/.rvmrc +2 -0
  5. data/Active.gemspec +28 -29
  6. data/Gemfile +4 -0
  7. data/History.txt +5 -2
  8. data/{README.txt → README.md} +4 -20
  9. data/Rakefile +11 -17
  10. data/lib/Active.rb +11 -79
  11. data/lib/active/activity.rb +7 -0
  12. data/lib/active/article.rb +7 -0
  13. data/lib/active/asset.rb +205 -0
  14. data/lib/active/errors.rb +9 -0
  15. data/lib/active/query.rb +225 -0
  16. data/lib/active/result.rb +7 -0
  17. data/lib/active/results.rb +6 -0
  18. data/lib/active/training.rb +7 -0
  19. data/lib/active/version.rb +3 -0
  20. data/lib/ext/hash_extensions.rb +8 -0
  21. data/spec/asset_spec.rb +47 -0
  22. data/spec/search_spec.rb +383 -432
  23. data/spec/spec_helper.rb +23 -2
  24. metadata +113 -116
  25. data/bin/Active +0 -7
  26. data/lib/.DS_Store +0 -0
  27. data/lib/services/.DS_Store +0 -0
  28. data/lib/services/IActivity.rb +0 -39
  29. data/lib/services/_ats.rb +0 -215
  30. data/lib/services/active_works.rb +0 -167
  31. data/lib/services/activity.rb +0 -512
  32. data/lib/services/address.rb +0 -17
  33. data/lib/services/ats.rb +0 -229
  34. data/lib/services/dto/user.rb +0 -9
  35. data/lib/services/gsa.rb +0 -205
  36. data/lib/services/reg_center.rb +0 -270
  37. data/lib/services/sanitize.rb +0 -108
  38. data/lib/services/search.rb +0 -494
  39. data/lib/services/validators.rb +0 -124
  40. data/rspec-tm +0 -1
  41. data/rvmrc +0 -1
  42. data/spec/.DS_Store +0 -0
  43. data/spec/Active_spec.rb +0 -28
  44. data/spec/activeworks_spec.rb +0 -60
  45. data/spec/activity_spec.rb +0 -421
  46. data/spec/ats_spec.rb +0 -106
  47. data/spec/benchmark/search_bench.rb +0 -55
  48. data/spec/custom_matchers_spec.rb +0 -27
  49. data/spec/gsa_spec.rb +0 -210
  50. data/spec/reg_spec.rb +0 -173
  51. data/spec/search_memcached_spec.rb +0 -42
  52. data/spec/validators_spec.rb +0 -19
  53. data/test/test_Active.rb +0 -0
  54. data/version.txt +0 -1
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ tmp/*
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
@@ -0,0 +1,2 @@
1
+ rvm use 1.9.2@R2D2
2
+
@@ -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 = %q{Active}
5
- s.version = "0.0.5"
6
-
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Jonathan Spooner, Brian Levine"]
9
- s.date = %q{2010-09-02}
10
- s.default_executable = %q{Active}
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
- if s.respond_to? :specification_version then
25
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
- s.specification_version = 3
15
+ s.rubyforge_project = "Active"
27
16
 
28
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
- s.add_development_dependency(%q<bones>, [">= 3.4.7"])
30
- else
31
- s.add_dependency(%q<bones>, [">= 3.4.7"])
32
- end
33
- else
34
- s.add_dependency(%q<bones>, [">= 3.4.7"])
35
- end
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
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in Active.gemspec
4
+ gemspec
@@ -1,4 +1,7 @@
1
- == 1.0.0 / 2010-08-30
1
+ == 0.1.1 / 2011-07-11
2
+ * Fixed GSA number of results GSA bug to make pagination work as expected.
2
3
 
3
- * 1 major enhancement
4
+ == 0.1.0 / 2010-08-30
5
+
6
+ * Improving organization and api
4
7
  * Birthday!
@@ -1,33 +1,17 @@
1
1
  Active
2
- by Jonathan Spooner and Brian Levine
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
- == FEATURES/PROBLEMS:
9
+ For use with Ruby 1.9
10
10
 
11
- * Seach API
11
+ == Development
12
12
 
13
- == SYNOPSIS:
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 'bones'
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
- Bones {
12
- name 'Active'
13
- authors 'Jonathan Spooner, Brian Levine'
14
- email 'jspooner [at] gmail.com'
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
@@ -1,80 +1,12 @@
1
- module Active
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
- # Utility method used to require all files ending in .rb that lie in the
53
- # directory below this file that has the same name as the filename passed
54
- # in. Optionally, a specific _directory_ name can be passed in such that
55
- # the _filename_ does not have to be equivalent to the directory.
56
- #
57
- def self.require_all_libs_relative_to( fname, dir = nil )
58
- dir ||= ::File.basename(fname, '.*')
59
- search_me = ::File.expand_path(
60
- ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
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
@@ -0,0 +1,7 @@
1
+ module Active
2
+ class Activity < Asset
3
+ def self.facet
4
+ 'activities'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Active
2
+ class Article < Asset
3
+ def self.facet
4
+ 'articles'
5
+ end
6
+ end
7
+ end
@@ -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