threetaps-client 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +17 -0
- data/Gemfile.lock +43 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +48 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/lib/client/client.rb +43 -0
- data/lib/client/geocoder_client.rb +42 -0
- data/lib/client/posting_client.rb +88 -0
- data/lib/client/reference_client.rb +60 -0
- data/lib/client/search_client.rb +82 -0
- data/lib/client/status_client.rb +72 -0
- data/lib/dto/geocoder/geocoder_request.rb +16 -0
- data/lib/dto/geocoder/geocoder_response.rb +7 -0
- data/lib/dto/posting/create_response.rb +23 -0
- data/lib/dto/posting/delete_response.rb +9 -0
- data/lib/dto/posting/exists_response.rb +16 -0
- data/lib/dto/posting/update_response.rb +9 -0
- data/lib/dto/search/best_match_response.rb +20 -0
- data/lib/dto/search/count_response.rb +9 -0
- data/lib/dto/search/query_request +0 -0
- data/lib/dto/search/range_request.rb +23 -0
- data/lib/dto/search/range_response.rb +26 -0
- data/lib/dto/search/search_request.rb +79 -0
- data/lib/dto/search/search_response.rb +37 -0
- data/lib/dto/search/summary_request.rb +13 -0
- data/lib/dto/search/summary_response.rb +20 -0
- data/lib/dto/status/get_status_response.rb +43 -0
- data/lib/dto/status/status_update_request.rb +27 -0
- data/lib/models/annotations/annotation.rb +21 -0
- data/lib/models/annotations/annotation_option.rb +9 -0
- data/lib/models/category.rb +26 -0
- data/lib/models/location.rb +30 -0
- data/lib/models/message.rb +9 -0
- data/lib/models/posting.rb +97 -0
- data/lib/models/posting_history.rb +8 -0
- data/lib/models/source.rb +27 -0
- data/lib/struct.rb +16 -0
- data/lib/threetaps-client.rb +44 -0
- data/spec/client/client_spec.rb +18 -0
- data/spec/client/geocoder_client_spec.rb +18 -0
- data/spec/client/posting_client_spec.rb +36 -0
- data/spec/client/reference_client_spec.rb +37 -0
- data/spec/client/search_client_spec.rb +53 -0
- data/spec/client/status_client_spec.rb +39 -0
- data/spec/dto/geocoder/geocoder_response_spec.rb +14 -0
- data/spec/dto/search/search_request_spec.rb +26 -0
- data/spec/dto/search/search_response_spec.rb +12 -0
- data/spec/spec_helper.rb +29 -0
- data/test/client/test_client.rb +11 -0
- data/test/client/test_geocoder_client.rb +43 -0
- data/test/client/test_posting_client.rb +88 -0
- data/test/client/test_reference_client.rb +32 -0
- data/test/client/test_search_client.rb +56 -0
- data/test/client/test_status_client.rb +49 -0
- data/test/dto/geocoder/test_geocoder_request.rb +16 -0
- data/test/dto/geocoder/test_geocoder_response.rb +14 -0
- data/test/dto/search/test_best_match_response.rb +10 -0
- data/test/dto/search/test_range_request.rb +13 -0
- data/test/dto/status/test_status_update_request.rb +18 -0
- data/test/helper.rb +18 -0
- data/test/models/test_posting.rb +28 -0
- data/test/test_struct.rb +17 -0
- data/test/test_threetaps-client.rb +7 -0
- data/threetaps-client.gemspec +153 -0
- metadata +266 -0
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
gem "supermodel", "~> 0.1.4"
|
3
|
+
gem "curb", "~> 0.7.9"
|
4
|
+
gem "activesupport", "~> 3.0.0"
|
5
|
+
# Add dependencies required to use your gem here.
|
6
|
+
# Example:
|
7
|
+
# gem "activesupport", ">= 2.3.5"
|
8
|
+
|
9
|
+
# Add dependencies to develop your gem here.
|
10
|
+
# Include everything needed to run rake, tests, features, etc.
|
11
|
+
group :development do
|
12
|
+
gem "shoulda", ">= 0"
|
13
|
+
gem "bundler", "~> 1.0.0"
|
14
|
+
gem "jeweler", "~> 1.5.2"
|
15
|
+
gem "rcov", ">= 0"
|
16
|
+
gem "rspec"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.3)
|
5
|
+
activesupport (= 3.0.3)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.4)
|
8
|
+
activesupport (3.0.3)
|
9
|
+
builder (2.1.2)
|
10
|
+
curb (0.7.12)
|
11
|
+
diff-lcs (1.1.2)
|
12
|
+
git (1.2.5)
|
13
|
+
i18n (0.5.0)
|
14
|
+
jeweler (1.5.2)
|
15
|
+
bundler (~> 1.0.0)
|
16
|
+
git (>= 1.2.5)
|
17
|
+
rake
|
18
|
+
rake (0.8.7)
|
19
|
+
rcov (0.9.9)
|
20
|
+
rspec (2.3.0)
|
21
|
+
rspec-core (~> 2.3.0)
|
22
|
+
rspec-expectations (~> 2.3.0)
|
23
|
+
rspec-mocks (~> 2.3.0)
|
24
|
+
rspec-core (2.3.1)
|
25
|
+
rspec-expectations (2.3.0)
|
26
|
+
diff-lcs (~> 1.1.2)
|
27
|
+
rspec-mocks (2.3.0)
|
28
|
+
shoulda (2.11.3)
|
29
|
+
supermodel (0.1.4)
|
30
|
+
activemodel (>= 3.0.0.beta)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
activesupport (~> 3.0.0)
|
37
|
+
bundler (~> 1.0.0)
|
38
|
+
curb (~> 0.7.9)
|
39
|
+
jeweler (~> 1.5.2)
|
40
|
+
rcov
|
41
|
+
rspec
|
42
|
+
shoulda
|
43
|
+
supermodel (~> 0.1.4)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 marat
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= threetaps-client
|
2
|
+
|
3
|
+
== Installation
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
=== Search
|
8
|
+
|
9
|
+
To perform a search you need to
|
10
|
+
1. create SearchRequest object and fill its attributes
|
11
|
+
|
12
|
+
request = SearchRequest.new
|
13
|
+
|
14
|
+
request.rpp = 10
|
15
|
+
|
16
|
+
request.text = "porsche"
|
17
|
+
|
18
|
+
2. create SearchClient object
|
19
|
+
|
20
|
+
client = SearchClient.new
|
21
|
+
|
22
|
+
3. call search method on client with request as a parameter and get an SearchResponse object.
|
23
|
+
|
24
|
+
response = client.search(request)
|
25
|
+
|
26
|
+
4. now you can operate with search results:
|
27
|
+
|
28
|
+
postings = response.results
|
29
|
+
|
30
|
+
quantity = response.num_results
|
31
|
+
|
32
|
+
execution_time = response.exec_time_ms
|
33
|
+
|
34
|
+
== Contributing to threetaps-client
|
35
|
+
|
36
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
37
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
38
|
+
* Fork the project
|
39
|
+
* Start a feature/bugfix branch
|
40
|
+
* Commit and push until you are happy with your contribution
|
41
|
+
* Make sure to add tests for it. This is important so we don't break it in a future version unintentionally.
|
42
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
43
|
+
|
44
|
+
== Copyright
|
45
|
+
|
46
|
+
Copyright (c) 2011 3taps.com. See LICENSE.txt for
|
47
|
+
further details.
|
48
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "threetaps-client"
|
16
|
+
gem.homepage = "https://github.com/3taps/3taps-Ruby-Client"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{A Ruby gem for accessing the 3taps API}
|
19
|
+
gem.description = %Q{A Ruby gem for accessing the 3taps API. See more at http://developers.3taps.net}
|
20
|
+
gem.email = "developers@3taps.com"
|
21
|
+
gem.authors = ["3taps.com"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rspec/core'
|
30
|
+
require 'rspec/core/rake_task'
|
31
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
32
|
+
spec.rspec_opts = ['--color']
|
33
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
37
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
38
|
+
spec.rcov = true
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :spec
|
42
|
+
|
43
|
+
# Run the unit tests
|
44
|
+
desc "Run all unit tests"
|
45
|
+
|
46
|
+
require 'rake/testtask'
|
47
|
+
Rake::TestTask.new(:test) do |test|
|
48
|
+
test.libs << 'lib' << 'test'
|
49
|
+
test.pattern = 'test/**/test_*.rb'
|
50
|
+
test.verbose = true
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'rcov/rcovtask'
|
54
|
+
Rcov::RcovTask.new(:rcovtest) do |test|
|
55
|
+
test.libs << 'test'
|
56
|
+
test.pattern = 'test/**/test_*.rb'
|
57
|
+
test.verbose = true
|
58
|
+
end
|
59
|
+
|
60
|
+
require 'rake/rdoctask'
|
61
|
+
Rake::RDocTask.new do |rdoc|
|
62
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
63
|
+
|
64
|
+
rdoc.rdoc_dir = 'rdoc'
|
65
|
+
rdoc.title = "threetaps-client #{version}"
|
66
|
+
rdoc.rdoc_files.include('README*')
|
67
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
68
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.1
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Base class for 3taps API client classes.
|
2
|
+
class Client
|
3
|
+
DEFAULT_URL = 'http://3taps.net'
|
4
|
+
DEFAULT_API_PORT = 80
|
5
|
+
# Initializes Client class with +baseUrl+ and +port+ parameters. By default
|
6
|
+
# DEFAULT_URL and DEFAULT_API_PORT are used. Examples:
|
7
|
+
# Client.new
|
8
|
+
# Client.new("http://3taps.com", 8080)
|
9
|
+
def initialize(baseUrl = DEFAULT_URL, port = DEFAULT_API_PORT)
|
10
|
+
@baseURL = baseUrl
|
11
|
+
@port = port
|
12
|
+
end
|
13
|
+
|
14
|
+
# Executes GET request on URL and port with +path+ and +params+ parameters.
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# execute_get("/search", "data=data")
|
18
|
+
def execute_get( path, params = nil )
|
19
|
+
address = params.nil? ? path : path + '?' + params
|
20
|
+
request = Curl::Easy.new("#{@baseURL}:#{@port}" + address)
|
21
|
+
begin
|
22
|
+
request.perform
|
23
|
+
rescue
|
24
|
+
"Some Error with Request."
|
25
|
+
end
|
26
|
+
request.body_str
|
27
|
+
end
|
28
|
+
|
29
|
+
# Executes POST request on URL and port with +path+ and +params+ parameters.
|
30
|
+
# Example:
|
31
|
+
#
|
32
|
+
# execute_post("search", "data=data")
|
33
|
+
def execute_post( path, params = nil )
|
34
|
+
c = Curl::Easy.http_post("#{@baseURL}:#{@port}/#{path}", params)
|
35
|
+
c.body_str
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def decode(data)
|
41
|
+
ActiveSupport::JSON.decode(data)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Class GeocoderClient represents server request of geocoding API (calculate
|
2
|
+
# the location to use for a posting based on location-specific details within
|
3
|
+
# the posting such as a street address or a latitude and longitude value).
|
4
|
+
#
|
5
|
+
# Its methods are used to query API with appropriate requests:
|
6
|
+
# geocode(requests) - returns array of responses
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# client = GeocoderClient.new
|
11
|
+
# request = GeocoderRequest.new
|
12
|
+
# request.latitude = '37.77493'
|
13
|
+
# request.longitude = '-122.41942'
|
14
|
+
#
|
15
|
+
# response = client.geocode(request)
|
16
|
+
#
|
17
|
+
# response.first.code # => "CAZ"
|
18
|
+
# response.first.latitude # => 39.77493
|
19
|
+
# response.first.longitude # => -122.41942
|
20
|
+
|
21
|
+
class GeocoderClient < Client
|
22
|
+
|
23
|
+
# Method geocode sends geocode request to Geocode API.
|
24
|
+
# Takes array of GeocoderRequest objects as +requests+ parameter.
|
25
|
+
#
|
26
|
+
# Examples:
|
27
|
+
#
|
28
|
+
# request = GeocoderRequest.new
|
29
|
+
# client.geocode(request) # => [GeocoderResponse]
|
30
|
+
#
|
31
|
+
# requests = [GeocoderRequest.new, GeocoderRequest.new]
|
32
|
+
# client.geocode(requests) # => [GeocoderResponse, GeocoderResponse]
|
33
|
+
#
|
34
|
+
def geocode(geocoder_requests)
|
35
|
+
geocoder_requests = [geocoder_requests] unless geocoder_requests.is_a? Array
|
36
|
+
params = "data=["
|
37
|
+
params << geocoder_requests.collect{|request| "#{request.to_params}"}.join(',')
|
38
|
+
params << "]"
|
39
|
+
response = execute_post('geocoder/geocode', params)
|
40
|
+
GeocoderResponse.from_array(decode(response))
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# The PostingClient class allows clients to use 3taps Posting API to store and
|
2
|
+
# retrieve postings in the 3taps system.
|
3
|
+
#
|
4
|
+
# Its methods are used to query API with appropriate requests:
|
5
|
+
# client = PostingClient.new
|
6
|
+
# client.get_posting(post_key) # => returns a single Posting object
|
7
|
+
# client.create_posting(postings) # => returns array of CreateResponse objects
|
8
|
+
# client.update_posting(postings) # => returns array of UpdateResponse objects
|
9
|
+
# client.delete_posting(post_keys) # => returns array of DeleteResponse objects
|
10
|
+
# client.exists_posting(posting) # => returns array of ExistsResponse objects
|
11
|
+
class PostingClient < Client
|
12
|
+
|
13
|
+
# Retrieves an information about a single posting.
|
14
|
+
#
|
15
|
+
# Example
|
16
|
+
# client = PostingClient.new
|
17
|
+
# client.get_posting("...postKey string...") => Posting object
|
18
|
+
#
|
19
|
+
def get_posting(post_key)
|
20
|
+
response = execute_get("/posting/get/" + post_key)
|
21
|
+
Posting.new(decode(response))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Method +create_posting+ saves a single new posting and multiple new postings in 3taps.
|
25
|
+
#
|
26
|
+
# Examples
|
27
|
+
# client = PostingClient.new
|
28
|
+
# client.update_posting([posting1, posting2]) #=> Array of CreateResponse objects
|
29
|
+
#
|
30
|
+
# client = PostingClient.new
|
31
|
+
# client.update_posting(posting2) #=> Array with single CreateResponse object
|
32
|
+
#
|
33
|
+
def create_posting(postings)
|
34
|
+
postings = [postings] unless postings.is_a? Array
|
35
|
+
data = "["
|
36
|
+
data << postings.collect{|posting| posting.to_json}.join(',')
|
37
|
+
data << "]"
|
38
|
+
params = "posts=#{data}"
|
39
|
+
response = execute_post("/posting/create", params)
|
40
|
+
CreateResponse.from_array(decode(response))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Method +update_posting+ updates a single posting and multiple postings on 3taps.
|
44
|
+
#
|
45
|
+
# Examples:
|
46
|
+
# client = PostingClient.new
|
47
|
+
# client.update_posting([posting1, posting2]) #=> Array of UpdateResponse objects
|
48
|
+
#
|
49
|
+
# client = PostingClient.new
|
50
|
+
# client.update_posting(posting) #=> Array with single UpdateResponse object
|
51
|
+
#
|
52
|
+
def update_posting(postings)
|
53
|
+
postings = [postings] unless postings.is_a? Array
|
54
|
+
data = "["
|
55
|
+
data << postings.collect{|posting| posting.to_json_for_update}.join(',')
|
56
|
+
data << "]"
|
57
|
+
params = "data=#{data}"
|
58
|
+
response = execute_post("posting/update", params)
|
59
|
+
UpdateResponse.from_hash(decode(response))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Method +delete_posting+ deletes a single posting and multiple postings from 3taps.
|
63
|
+
#
|
64
|
+
# Examples:
|
65
|
+
# client = PostingClient.new
|
66
|
+
# response = client.delete_posting(...Array of postKeys strings...) # => Array of DeleteResponse objects
|
67
|
+
#
|
68
|
+
# client = PostingClient.new
|
69
|
+
# key = some_posting.postKey
|
70
|
+
# response = client.delete_posting(key) # => Array with single DeleteResponse object
|
71
|
+
#
|
72
|
+
def delete_posting(post_keys)
|
73
|
+
post_keys = [post_keys] unless post_keys.is_a? Array
|
74
|
+
params = "data=['#{post_keys.join("','")}']"
|
75
|
+
response = execute_post("posting/delete", params)
|
76
|
+
DeleteResponse.from_hash(decode(response))
|
77
|
+
end
|
78
|
+
|
79
|
+
# NOT USED
|
80
|
+
#
|
81
|
+
# Returns information on the existence of postings.
|
82
|
+
#
|
83
|
+
def exists_posting(posting)
|
84
|
+
params = "ids=#{posting}"
|
85
|
+
response = execute_post("/posting/exists", params)
|
86
|
+
ExistsResponse.from_array(decode(response))
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Class ReferenceClient represents server request of reference API (provides a
|
2
|
+
# mechanism for accessing the standard "reference information" used by the
|
3
|
+
# 3taps system, including locations, categories, and sources).
|
4
|
+
#
|
5
|
+
# Its methods are used to query API with appropriate requests:
|
6
|
+
# client = ReferenceClient.new
|
7
|
+
# client.get_categories # => returns array of Category objects
|
8
|
+
# client.get_category(code) # => returns Category object
|
9
|
+
# client.get_locations # => returns array of Location objects
|
10
|
+
# client.get_sources # => returns array of Source objects
|
11
|
+
|
12
|
+
class ReferenceClient < Client
|
13
|
+
|
14
|
+
# Method +get_categories+ returns the 3taps categories.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
#
|
18
|
+
# client = ReferenceClient.new
|
19
|
+
# client.get_categories # => Array of Category
|
20
|
+
#
|
21
|
+
def get_categories
|
22
|
+
response = execute_get("/reference/category")
|
23
|
+
File.new("newfile", "w+") << response
|
24
|
+
Category.from_array(decode(response))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Method +get_category+ returns a single category by passing in the category code.
|
28
|
+
# Takes value of code objects as +String+ parameter.
|
29
|
+
#
|
30
|
+
# Example:
|
31
|
+
#
|
32
|
+
# client.get_category('NYC') # => Categoty
|
33
|
+
#
|
34
|
+
def get_category(code)
|
35
|
+
response = execute_get("/reference/category/" + code)
|
36
|
+
Category.from_hash(decode(response)[0])
|
37
|
+
end
|
38
|
+
|
39
|
+
# Method +get_locations+ returns the 3taps locations.
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
#
|
43
|
+
# client.get_locations # => Array of Location
|
44
|
+
#
|
45
|
+
def get_locations
|
46
|
+
response = execute_get("/reference/location")
|
47
|
+
Location.from_array(decode(response))
|
48
|
+
end
|
49
|
+
|
50
|
+
# Method +get_sources+ returns the 3taps sources.
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
#
|
54
|
+
# client.get_sources # => Array of Source
|
55
|
+
#
|
56
|
+
def get_sources
|
57
|
+
response = execute_get("/reference/source")
|
58
|
+
Source.from_array(decode(response))
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# The SearchClient class allows clients to query 3taps Search API for data,
|
2
|
+
# and data about data.
|
3
|
+
#
|
4
|
+
# Its methods are used to query API with appropriate requests:
|
5
|
+
# client = SearchClient.new
|
6
|
+
# client.search(search_request) # => returns array of SearchResponse objects
|
7
|
+
# client.range(range_request) # => returns array of RangeResponse objects
|
8
|
+
# client.summary(summary_request) # => returns array of SummaryResponse objects
|
9
|
+
# client.count(search_request) # => returns array of CountResponse objects
|
10
|
+
# client.best_match(keywords) # => returns array of BestMatchResponse objects
|
11
|
+
class SearchClient < Client
|
12
|
+
|
13
|
+
# Method +search+ searches 3taps for postings. Example:
|
14
|
+
#
|
15
|
+
# request = SearchRequest.new
|
16
|
+
# client = SearchClient.new
|
17
|
+
# client.search(request) # => SearchResponse
|
18
|
+
#
|
19
|
+
def search(search_request)
|
20
|
+
response = execute_get("/search", search_request.query_params)
|
21
|
+
SearchResponse.new(decode(response))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Method +range+ returns the minium and maximum values currently in 3taps for
|
25
|
+
# the given fields that match the given Common Search Criteria inside of the
|
26
|
+
# RangeResponse object. The purpose of the range method is to provide
|
27
|
+
# developers with sensible values for range-based UI filters.
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
#
|
31
|
+
# request = RangeRequest.new
|
32
|
+
# client = SearchClient.new(request)
|
33
|
+
# client.range(request) # => RangeResponse
|
34
|
+
#
|
35
|
+
def range(range_request)
|
36
|
+
response = execute_get("/search/range", range_request.query_params)
|
37
|
+
RangeResponse.from_array(decode(response))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Method +summary+ returns the total number of postings found in 3taps, across
|
41
|
+
# the given dimension, that match the given Common Search Criteria parameters
|
42
|
+
# inside of the SummaryResponse object. Searching for "text=toyota" across
|
43
|
+
# "dimension=source" would return a list of all sources in 3taps, along with
|
44
|
+
# the number of postings matching the search "text=toyota" in that source.
|
45
|
+
# You may currently search across dimensions source, category, and location.
|
46
|
+
#
|
47
|
+
# Examples:
|
48
|
+
#
|
49
|
+
# request = SummaryRequest.new
|
50
|
+
# client = SearchClient.new
|
51
|
+
# client.summary(request) # => SummaryResponse
|
52
|
+
#
|
53
|
+
def summary(summary_request)
|
54
|
+
response = execute_get("/search/summary", summary_request.query_params)
|
55
|
+
SummaryResponse.from_hash(decode(response))
|
56
|
+
end
|
57
|
+
|
58
|
+
# Method +count+ returns the total number of postings that match the given
|
59
|
+
# Common Search Criteria represented by SearchRequest. Example:
|
60
|
+
#
|
61
|
+
# request = SearchRequest.new
|
62
|
+
# client = SearchClient.new
|
63
|
+
# client.count(request) # => CountResponse
|
64
|
+
#
|
65
|
+
def count(search_request)
|
66
|
+
response = execute_get("/search/count", search_request.query_params)
|
67
|
+
CountResponse.new(decode(response))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Method +best_match+ returns the 3taps category associated with the keywords,
|
71
|
+
# along with the number of postings in that category. Example:
|
72
|
+
#
|
73
|
+
# keywords = "iPad,Apple,iPhone"
|
74
|
+
# client = SearchClient.new
|
75
|
+
# client.best_match(keywords) # => BestMatchResponse
|
76
|
+
#
|
77
|
+
def best_match(keywords)
|
78
|
+
response = execute_get("/search/best-match", "keywords=#{keywords}")
|
79
|
+
BestMatchResponse.from_hash(decode(response))
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# The StatusClient class provides access to the Status API.
|
2
|
+
#
|
3
|
+
# The Status API provides access to the status of postings, both inside and
|
4
|
+
# outside of the 3taps system. The Status API is built upon the assumption that
|
5
|
+
# most postings can be globally identified using two pieces of data: the source
|
6
|
+
# and the externalID. Since we can globally identify a posting, we can share the
|
7
|
+
# status of postings between various systems.
|
8
|
+
#
|
9
|
+
# For example, if a posting has been
|
10
|
+
# "sent" to the Posting API by an external source, that external source can
|
11
|
+
# optionally send a status of "sent" to the Status API. Once the Posting API has
|
12
|
+
# processed and saved the posting, it can send the status of "saved" to the
|
13
|
+
# Status API. Later, if somebody looks up the posting in the Status API, they
|
14
|
+
# will see both of these events (sent and saved), along with the time that they
|
15
|
+
# occurred, and any relevant attributes (postKey, errors, etc). Having this
|
16
|
+
# information available allows 3taps and sources to provide maximum visibility
|
17
|
+
# into their processes so that both can improve data yield.
|
18
|
+
#
|
19
|
+
# Class StatusClient provides access to the status API of postings
|
20
|
+
# server response returns the status of postings, if a posting has been "sent" to the Posting API by an
|
21
|
+
# external source, that external source can optionally send a status of "sent" the Status API.
|
22
|
+
#
|
23
|
+
# Its methods are used to query API with appropriate requests:
|
24
|
+
# client = StatusClient .new
|
25
|
+
# client.update_status(postings) # => returns Message
|
26
|
+
# client.get_status(postings) # => returns array of GetStatusResponse objects
|
27
|
+
# client.system_status # => returns Message
|
28
|
+
#
|
29
|
+
class StatusClient < Client
|
30
|
+
#
|
31
|
+
# Method +update_status+ send in status events for postings. Example:
|
32
|
+
#
|
33
|
+
# client = StatusClient.new
|
34
|
+
# request = StatusUpdateRequest.new
|
35
|
+
# client.update_status(request) # => Message
|
36
|
+
#
|
37
|
+
def update_status(postings)
|
38
|
+
postings = [postings] unless postings.is_a? Array
|
39
|
+
params ='events=['
|
40
|
+
params << postings.collect{|posting| "{#{posting.status.to_params}, #{posting.to_json_for_status_client}}" unless posting.status.event.empty?}.join(',')
|
41
|
+
params << "]"
|
42
|
+
response = execute_post("status/update", params)
|
43
|
+
Message.from_hash(decode(response))
|
44
|
+
end
|
45
|
+
#
|
46
|
+
# Method +get_status+ get status history for postings. Example:
|
47
|
+
#
|
48
|
+
# client = SearchClient.new
|
49
|
+
# postings = Posting.new
|
50
|
+
# response = client.get_status(postings) # => Array of GetStatusResponse
|
51
|
+
#
|
52
|
+
def get_status(postings)
|
53
|
+
postings = [postings] unless postings.is_a? Array
|
54
|
+
data = "["
|
55
|
+
data << postings.collect{|posting| "{#{posting.to_json_for_status_client}}"}.join(',')
|
56
|
+
data << "]"
|
57
|
+
params = "ids=#{data}"
|
58
|
+
response = execute_post("status/get", params)
|
59
|
+
GetStatusResponse.from_array(decode(response))
|
60
|
+
end
|
61
|
+
#
|
62
|
+
# Method +system_status+ get the current system status. Example:
|
63
|
+
#
|
64
|
+
# client = StatusClient.new
|
65
|
+
# response = client.system_status # => Message
|
66
|
+
#
|
67
|
+
def system_status
|
68
|
+
response = execute_get("/status/system")
|
69
|
+
Message.from_hash(decode(response))
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class GeocoderRequest < Struct.new(:latitude, :longitude, :country, :state, :city, :locality, :postal, :text)
|
2
|
+
|
3
|
+
def to_params
|
4
|
+
result = []
|
5
|
+
result << "\"latitude\":#{CGI.escape latitude}" unless latitude.nil?
|
6
|
+
result << "\"longitude\":#{CGI.escape longitude}" unless longitude.nil?
|
7
|
+
result << "\"country\":\"#{CGI.escape country}\"" unless country.nil?
|
8
|
+
result << "\"state\":\"#{CGI.escape state}\"" unless state.nil?
|
9
|
+
result << "\"city\":\"#{CGI.escape city}\"" unless city.nil?
|
10
|
+
result << "\"locality\":\"#{CGI.escape locality}\"" unless locality.nil?
|
11
|
+
result << "\"postal\":\"#{CGI.escape postal}\"" unless postal.nil?
|
12
|
+
result << "\"tex\":\"#{CGI.escape text}\"" unless text.nil?
|
13
|
+
'{' + result.join(", ") + '}'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Class CreateResponse represents server response on +create+ Posting API
|
2
|
+
# request. Server response is sent to +from_array+ method which creates objects
|
3
|
+
# with attributes +postKey+, +error+ accessible via getters:
|
4
|
+
#
|
5
|
+
# response = RangeResponse.from_array(...)
|
6
|
+
# response.postKey # => String
|
7
|
+
# response.post_key # => String
|
8
|
+
# response.error # => String
|
9
|
+
#
|
10
|
+
class CreateResponse < Struct.new(:postKey, :error) do
|
11
|
+
def post_key
|
12
|
+
postKey
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Method +from_array+ creates an array of CreateResponse objects from a given
|
17
|
+
# array of JSON hashes.
|
18
|
+
def self.from_array(array)
|
19
|
+
array.collect do |element|
|
20
|
+
CreateResponse.new(element)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Class DeleteResponse represents server response on +delete+ Posting API
|
2
|
+
# request. Server response is sent to +from_hash+ method which creates object
|
3
|
+
# with attribute +success+ accessible via getter:
|
4
|
+
#
|
5
|
+
# response = DeleteResponse.from_hash("success" => "true")
|
6
|
+
# response.success # => true
|
7
|
+
#
|
8
|
+
class DeleteResponse < Struct.new(:success)
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# NOT USED
|
2
|
+
#
|
3
|
+
# Class ExistsResponse represents server response on +exists+ Posting API
|
4
|
+
# request. Server response is sent to +from_hash+ method which creates object
|
5
|
+
# with attribute +success+ accessible via getter:
|
6
|
+
#
|
7
|
+
# response = ExistsResponse.from_hash("success" => "true")
|
8
|
+
# response.success # => true
|
9
|
+
#
|
10
|
+
class ExistsResponse
|
11
|
+
attr_accessor :exists, :postKey, :error
|
12
|
+
|
13
|
+
def self.from_array(json)
|
14
|
+
json
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Class UpdateResponse represents server response on +update+ Posting API
|
2
|
+
# request. Server response is sent to +from_hash+ method which creates object
|
3
|
+
# with attribute +success+ accessible via getter:
|
4
|
+
#
|
5
|
+
# response = UpdateResponse.from_hash("success" => "true")
|
6
|
+
# response.success # => true
|
7
|
+
#
|
8
|
+
class UpdateResponse < Struct.new(:success)
|
9
|
+
end
|