Active 0.0.42 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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