amiando 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +17 -0
- data/Guardfile +11 -0
- data/README.md +26 -0
- data/Rakefile +12 -0
- data/amiando.gemspec +27 -0
- data/lib/amiando.rb +59 -0
- data/lib/amiando/api_key.rb +35 -0
- data/lib/amiando/boolean.rb +33 -0
- data/lib/amiando/event.rb +131 -0
- data/lib/amiando/request.rb +38 -0
- data/lib/amiando/resource.rb +152 -0
- data/lib/amiando/result.rb +33 -0
- data/lib/amiando/ticket_category.rb +99 -0
- data/lib/amiando/ticket_shop.rb +63 -0
- data/lib/amiando/user.rb +148 -0
- data/lib/amiando/version.rb +3 -0
- data/test/amiando/amiando_test.rb +13 -0
- data/test/amiando/api_key_test.rb +58 -0
- data/test/amiando/boolean_test.rb +21 -0
- data/test/amiando/event_test.rb +141 -0
- data/test/amiando/resource_test.rb +68 -0
- data/test/amiando/result_test.rb +25 -0
- data/test/amiando/ticket_category_test.rb +89 -0
- data/test/amiando/ticket_shop_test.rb +42 -0
- data/test/amiando/user_test.rb +130 -0
- data/test/fixtures/ApiKey/018fa0a2281ec9026bc122bc346366f6.yml +60 -0
- data/test/fixtures/ApiKey/1f62195e173114773b3ec2613582ece9.yml +60 -0
- data/test/fixtures/ApiKey/76860dbafe66279f25f56cd66b3f6ba1.yml +62 -0
- data/test/fixtures/ApiKey/97d82801a10696aaf385bf5873034b60.yml +60 -0
- data/test/fixtures/ApiKey/a703d1fcec1576fa8cb4ca1c5f53f545.yml +62 -0
- data/test/fixtures/ApiKey/a948a98b153ab66978e37160f352bfbc.yml +60 -0
- data/test/fixtures/ApiKey/b7ecc9e79dd856dec661554cd00490ed.yml +62 -0
- data/test/fixtures/ApiKey/ded8694c21d2e1c0cec845f72ba452b5.yml +60 -0
- data/test/fixtures/ApiKey/fa883db60c0390aa8948098d32497015.yml +60 -0
- data/test/fixtures/Event/29a95cd545b2fba8121dce97a3c859e3.yml +60 -0
- data/test/fixtures/Event/361940ebc5f074b1d6d96c2dbeb573ab.yml +60 -0
- data/test/fixtures/Event/3a90bf0a17eb1d647f1496d04640797a.yml +60 -0
- data/test/fixtures/Event/3b8ae154ad13c7152366b79c0d34b053.yml +60 -0
- data/test/fixtures/Event/49877df5f8c251e3364a3560ab1ab46c.yml +60 -0
- data/test/fixtures/Event/50cb3d76b40032b0fa5731ce7d2ae2f6.yml +62 -0
- data/test/fixtures/Event/5d6016557d86e7b7ff83d07d1ef4bf44.yml +60 -0
- data/test/fixtures/Event/67e55d2f91fa702eb8dc612cbfa661f9.yml +60 -0
- data/test/fixtures/Event/813535fc6ee153c1a6d8e826f1fe04dc.yml +60 -0
- data/test/fixtures/Event/8eabb0f839e03cde5818397c7121e6b4.yml +61 -0
- data/test/fixtures/Event/96a5ccd0281a67a4bdb276516b77e756.yml +62 -0
- data/test/fixtures/Event/9e689bd5495dc898a710cba8e6d1d779.yml +62 -0
- data/test/fixtures/Event/a816e5664ff66b8e3d27b74435a0c123.yml +60 -0
- data/test/fixtures/Event/c5ad7e1d1c160d7d1132297892a9ec94.yml +60 -0
- data/test/fixtures/Event/c88c85889575508f75deee325e16e49d.yml +60 -0
- data/test/fixtures/Event/d6a585196f1a2a94d22f22a2140d4c07.yml +60 -0
- data/test/fixtures/Event/e00eebd4faf194fe592fa6e7615909b8.yml +60 -0
- data/test/fixtures/Event/e753b6f404795c6635856ea43b0c7d35.yml +60 -0
- data/test/fixtures/Event/eb341dbccefaad75aad439f10cc7d82d.yml +60 -0
- data/test/fixtures/Event/ebab641e40ca57f8e0883d8ea003bd78.yml +60 -0
- data/test/fixtures/Event/ef17351e4bbc84eb776fe16dda31e1e4.yml +62 -0
- data/test/fixtures/Global/505952258352958b3b59a3812372ed02.yml +60 -0
- data/test/fixtures/Global/d41a6ca323b5db99b4e3c06e108c52cc.yml +60 -0
- data/test/fixtures/TicketCategory/0412c9d453efd804e171c6ba57fd980a.yml +66 -0
- data/test/fixtures/TicketCategory/49877df5f8c251e3364a3560ab1ab46c.yml +60 -0
- data/test/fixtures/TicketCategory/4d3f8d9ff3fb728fc37aaa6e40355a00.yml +62 -0
- data/test/fixtures/TicketCategory/5d4fdfda01ed8193c6bbc5e089db5a4b.yml +60 -0
- data/test/fixtures/TicketCategory/655e7a8089d67b8eeea1176398e4b289.yml +60 -0
- data/test/fixtures/TicketCategory/a9b19dc83437d00ffc4603c04f78159f.yml +62 -0
- data/test/fixtures/TicketCategory/bee3d6eb4247fec0849d91fb2f768524.yml +60 -0
- data/test/fixtures/TicketCategory/c6f8563714904f006b28ac06312b107d.yml +60 -0
- data/test/fixtures/TicketCategory/e6076c26b1b75eec091c5b91c9f75ad9.yml +62 -0
- data/test/fixtures/TicketCategory/ebfcf07be91b8cb6d05156713592abc9.yml +60 -0
- data/test/fixtures/TicketCategory/fe63648cf867613ec93b380e06257349.yml +60 -0
- data/test/fixtures/TicketShop/03d35073550910e61201cf425b4ff73e.yml +60 -0
- data/test/fixtures/TicketShop/0524d80dc6e3fad88d49adf71ffa2ab9.yml +60 -0
- data/test/fixtures/TicketShop/09729fb0d9f1490bec3acfa0e6742190.yml +60 -0
- data/test/fixtures/TicketShop/15c36c73e9f1d3255a61a559e3b98562.yml +60 -0
- data/test/fixtures/TicketShop/4605dd240202cd7510bfecaf474ac615.yml +62 -0
- data/test/fixtures/TicketShop/5c1f5488a196f44f2c18cc186816fd42.yml +60 -0
- data/test/fixtures/TicketShop/71f80402a72be32fdd34074d4426b765.yml +62 -0
- data/test/fixtures/TicketShop/bc24338e918c6edb07a55f4d580c5af3.yml +60 -0
- data/test/fixtures/TicketShop/d095062bf22d235f277c979b025e5cac.yml +60 -0
- data/test/fixtures/TicketShop/ece5150c24e5000bf4eff8dcdb6311bb.yml +60 -0
- data/test/fixtures/User/0b4a60c6c962b4b3af9ab21832cd76b2.yml +60 -0
- data/test/fixtures/User/0f635f4bb82fdc84af205efe76f43ae0.yml +60 -0
- data/test/fixtures/User/1c2f2c8a5372e998f38b9d387107cee2.yml +60 -0
- data/test/fixtures/User/1e3ab0fb92b5b1992f35256b4be7497b.yml +71 -0
- data/test/fixtures/User/3bac6d29256056f2b9a1ea6fad26966d.yml +60 -0
- data/test/fixtures/User/3ffaba64188557400a8678dbefd75990.yml +60 -0
- data/test/fixtures/User/5a26c7f9edf6d6027b19b57feda4a96f.yml +60 -0
- data/test/fixtures/User/5c17b4b5287f5d0ba390e25e99cf2270.yml +49 -0
- data/test/fixtures/User/6501a4db53a97afe6f7b9afeeb996888.yml +60 -0
- data/test/fixtures/User/6ad0dd77081f413e3df25d6a625d38cd.yml +60 -0
- data/test/fixtures/User/7d493f7758d9795ad522bc827cb51b77.yml +60 -0
- data/test/fixtures/User/89e6cb6ae39e29a154c99e0e33bb1b91.yml +60 -0
- data/test/fixtures/User/90a3bfe214f17305e356ad3f1a9c9ce7.yml +60 -0
- data/test/fixtures/User/92ad6537c8be5aab7cbd778d424f4944.yml +60 -0
- data/test/fixtures/User/9485b68940997e23e3721a413d4fbdd5.yml +49 -0
- data/test/fixtures/User/98348fe6fbecb7916faadd835916d94d.yml +60 -0
- data/test/fixtures/User/b63d7aa4703a3140b4d9884e9f302362.yml +60 -0
- data/test/fixtures/User/b8c3fd04d7bd0925c3ccd3a3978ab8e6.yml +49 -0
- data/test/fixtures/User/baa28f50439b903e423dbdf918fff20b.yml +62 -0
- data/test/fixtures/User/e51278f9f771be0c6c3ac0e4ee1b6459.yml +59 -0
- data/test/fixtures/User/eb30a195ac7829d506954f472e9e6dea.yml +60 -0
- data/test/support/factory.rb +45 -0
- data/test/support/hydra_cache.rb +59 -0
- data/test/test_helper.rb +36 -0
- metadata +330 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in amiando.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
unless ENV["TRAVIS"]
|
7
|
+
gem 'ruby-debug19', :platforms => :ruby_19
|
8
|
+
gem 'ruby-debug', :platforms => :mri_18
|
9
|
+
end
|
10
|
+
|
11
|
+
group :development do
|
12
|
+
gem 'guard-minitest'
|
13
|
+
if RbConfig::CONFIG['target_os'] =~ /darwin/i
|
14
|
+
gem 'rb-fsevent', '>= 0.4.0', :require => false
|
15
|
+
gem 'growl', '~> 1.0.3', :require => false
|
16
|
+
end
|
17
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'minitest' do
|
5
|
+
# with Minitest::Unit
|
6
|
+
watch(%r|^test/(.*)_test\.rb|)
|
7
|
+
watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
|
8
|
+
watch(%r|^test/test_helper\.rb|) { "test" }
|
9
|
+
watch(%r|^test/support/(.*)\.rb|) { "test" }
|
10
|
+
watch(%r|^lib/amiando.rb|) { "test" }
|
11
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# amiando
|
2
|
+
|
3
|
+
This is a gem to access the amiando REST API. You can check the original
|
4
|
+
documentation here:
|
5
|
+
|
6
|
+
http://developers.amiando.com/index.php/REST_API
|
7
|
+
|
8
|
+
## Basic usage
|
9
|
+
|
10
|
+
The gem has been implemented with the idea that requests can be done in
|
11
|
+
parallel using [Typhoeus](https://github.com/dbalatero/typhoeus).
|
12
|
+
|
13
|
+
You can query multiple requests and run then like this:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
albert = Amiando::User.find(1234)
|
17
|
+
jorge = Amiando::User.find(5678)
|
18
|
+
|
19
|
+
Amiando.run
|
20
|
+
```
|
21
|
+
|
22
|
+
Both requests will happen in parallel.
|
23
|
+
|
24
|
+
All attributes should be used in snake_case format instead of the CamelCase
|
25
|
+
used in the official documentation. For example, for a user, you should call
|
26
|
+
first_name instead of firstName.
|
data/Rakefile
ADDED
data/amiando.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "amiando/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "amiando"
|
7
|
+
s.version = Amiando::VERSION
|
8
|
+
s.authors = ["Jorge Dias", "Albert Llop"]
|
9
|
+
s.email = ["jorge@mrdias.com","mrsimo@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A ruby client for the amiando REST API}
|
12
|
+
s.description = %q{A ruby client for the amiando REST API with parallel requests in mind}
|
13
|
+
|
14
|
+
s.rubyforge_project = "amiando"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'yajl-ruby', '0.8.2'
|
22
|
+
s.add_dependency 'typhoeus', '0.2.4'
|
23
|
+
|
24
|
+
s.add_development_dependency 'minitest'
|
25
|
+
s.add_development_dependency 'webmock'
|
26
|
+
s.add_development_dependency 'rake'
|
27
|
+
end
|
data/lib/amiando.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "amiando/version"
|
2
|
+
require "typhoeus"
|
3
|
+
require "yajl"
|
4
|
+
|
5
|
+
module Amiando
|
6
|
+
autoload :Request, 'amiando/request'
|
7
|
+
autoload :Resource, 'amiando/resource'
|
8
|
+
autoload :Boolean, 'amiando/boolean'
|
9
|
+
autoload :Result, 'amiando/result'
|
10
|
+
autoload :ApiKey, 'amiando/api_key'
|
11
|
+
autoload :User, 'amiando/user'
|
12
|
+
autoload :Event, 'amiando/event'
|
13
|
+
autoload :TicketCategory, 'amiando/ticket_category'
|
14
|
+
autoload :TicketShop, 'amiando/ticket_shop'
|
15
|
+
|
16
|
+
module Error
|
17
|
+
class ServiceDown < Exception; end
|
18
|
+
class ApiKeyNeeded < Exception; end
|
19
|
+
class NotAuthorized < Exception; end
|
20
|
+
class NotFound < Exception; end
|
21
|
+
class NotImplemented < Exception; end
|
22
|
+
class NotInitialized < Exception; end
|
23
|
+
class MissingApiKey < Exception; end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
attr_accessor :api_key
|
28
|
+
|
29
|
+
URL = 'https://amiando.com'
|
30
|
+
TEST_URL = 'https://test.amiando.com'
|
31
|
+
|
32
|
+
def production!
|
33
|
+
@production = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def development!
|
37
|
+
@production = false
|
38
|
+
end
|
39
|
+
|
40
|
+
def base_url
|
41
|
+
@production ? URL : TEST_URL
|
42
|
+
end
|
43
|
+
|
44
|
+
def requests
|
45
|
+
@requests ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
def run
|
49
|
+
requests.each{ |request| hydra.queue(request) }
|
50
|
+
hydra.run
|
51
|
+
ensure
|
52
|
+
@requests = []
|
53
|
+
end
|
54
|
+
|
55
|
+
def hydra
|
56
|
+
@hydra ||= Typhoeus::Hydra.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Amiando
|
2
|
+
|
3
|
+
##
|
4
|
+
# http://developers.amiando.com/index.php/REST_API_ApiKey
|
5
|
+
class ApiKey < Resource
|
6
|
+
|
7
|
+
##
|
8
|
+
# Creates an {ApiKey}.
|
9
|
+
#
|
10
|
+
# @param [Hash] possible attributes that can be set on creation.
|
11
|
+
def self.create(attributes)
|
12
|
+
raise ArgumentError.new('ApiKey name field is mandatory') unless attributes[:name]
|
13
|
+
|
14
|
+
object = new
|
15
|
+
request = post object, '/api/apiKey/create', :params => attributes
|
16
|
+
|
17
|
+
object
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Updates an {ApiKey}.
|
22
|
+
#
|
23
|
+
# @param [Hash] possible attributes that can be updated.
|
24
|
+
def self.update(id, attributes)
|
25
|
+
object = Boolean.new(:success)
|
26
|
+
request = post object, "/api/apiKey/#{id}", :params => attributes
|
27
|
+
|
28
|
+
object
|
29
|
+
end
|
30
|
+
|
31
|
+
def populate(response_body)
|
32
|
+
extract_attributes_from(response_body, 'apiKey')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Amiando
|
2
|
+
|
3
|
+
##
|
4
|
+
# This object is intended to be used when an api will return a boolean
|
5
|
+
# response, but due to the delayed nature of doing requests in parallel,
|
6
|
+
# can't be initialized from the beginning.
|
7
|
+
#
|
8
|
+
# After the object is populated, you can ask the result with the result
|
9
|
+
# method.
|
10
|
+
class Boolean
|
11
|
+
attr_accessor :request, :response
|
12
|
+
|
13
|
+
def initialize(response_attribute)
|
14
|
+
@response_attribute = response_attribute.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def populate(response_body)
|
18
|
+
if response_body.key?(@response_attribute)
|
19
|
+
@result = response_body[@response_attribute]
|
20
|
+
else
|
21
|
+
raise Error::NotInitialized.new("The response doesn't have the expected attribute")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def result
|
26
|
+
if defined?(@result)
|
27
|
+
@result
|
28
|
+
else
|
29
|
+
raise Error::NotInitialized.new('Called result before the query was run')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Amiando
|
2
|
+
|
3
|
+
##
|
4
|
+
# http://developers.amiando.com/index.php/REST_API_Events
|
5
|
+
class Event < Resource
|
6
|
+
map :host_id, :hostId
|
7
|
+
map :selected_date, :selectedDate, :type => :time
|
8
|
+
map :selected_end_date, :selectedEndDate, :type => :time
|
9
|
+
map :short_description, :shortDescription
|
10
|
+
map :event_type, :eventType
|
11
|
+
map :organisator_display_name, :organisatorDisplayName
|
12
|
+
map :partner_event_url, :partnerEventUrl
|
13
|
+
map :publish_search_engines, :publishSearchEngines
|
14
|
+
map :search_engine_tags, :searchEngineTags
|
15
|
+
map :location_description, :locationDescription
|
16
|
+
map :zip_code, :zipCode
|
17
|
+
map :creation_time, :creationTime, :type => :time
|
18
|
+
map :last_modified, :lastModified, :type => :time
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates an event.
|
22
|
+
#
|
23
|
+
# @return [Event] will not return the full event and only the id attribute
|
24
|
+
# will be available.
|
25
|
+
def self.create(attributes)
|
26
|
+
object = new
|
27
|
+
request = post object, '/api/event/create',
|
28
|
+
:params => map_params(attributes),
|
29
|
+
:populate_method => :populate_create
|
30
|
+
|
31
|
+
object
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Updates an event.
|
36
|
+
#
|
37
|
+
# @return [Boolean] if it was successful or not.
|
38
|
+
def self.update(id, attributes)
|
39
|
+
object = Result.new do |response_body, result|
|
40
|
+
unless response_body['success']
|
41
|
+
result.errors = response_body['errors']
|
42
|
+
end
|
43
|
+
response_body['success']
|
44
|
+
end
|
45
|
+
request = post object, "/api/event/#{id}", :params => map_params(attributes)
|
46
|
+
|
47
|
+
object
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Fetch an event
|
52
|
+
def self.find(id)
|
53
|
+
object = new
|
54
|
+
request = get object, "/api/event/#{id}"
|
55
|
+
|
56
|
+
object
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# See if an event id exists
|
61
|
+
def self.exists?(identifier)
|
62
|
+
object = Boolean.new('exists')
|
63
|
+
request = get object, "api/event/exists",
|
64
|
+
:params => { :identifier => identifier }
|
65
|
+
|
66
|
+
object
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Deletes an event
|
71
|
+
#
|
72
|
+
# @param [Integer] event id
|
73
|
+
#
|
74
|
+
# @return [Boolean] with the result of the operation
|
75
|
+
def self.delete(id)
|
76
|
+
object = Boolean.new('deleted')
|
77
|
+
request = do_request object, :delete, "/api/event/#{id}"
|
78
|
+
|
79
|
+
object
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Activate an event
|
84
|
+
#
|
85
|
+
# @param [Integer] the event id
|
86
|
+
#
|
87
|
+
# @return [Result] if it was activated or not.
|
88
|
+
def self.activate(id)
|
89
|
+
object = Result.new do |response_body, result|
|
90
|
+
unless response_body['success']
|
91
|
+
result.errors = response_body['errors']
|
92
|
+
end
|
93
|
+
response_body['success']
|
94
|
+
end
|
95
|
+
request = post object, "/api/event/#{id}/activate"
|
96
|
+
|
97
|
+
object
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Search by identifier or title.
|
102
|
+
#
|
103
|
+
# @param [Hash] a hash with 1 entry, either :identifier or :title
|
104
|
+
#
|
105
|
+
# @return [Result] with an array of ids
|
106
|
+
def self.search(by)
|
107
|
+
unless by[:identifier].nil? ^ by[:title].nil? # XOR
|
108
|
+
raise ArgumentError.new('Events can be searched either by identifier or by title, include only one.')
|
109
|
+
end
|
110
|
+
|
111
|
+
object = Result.new { |response_body| response_body['ids'] }
|
112
|
+
request = get object, '/api/event/find', :params => by
|
113
|
+
|
114
|
+
object
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.find_all_by_user_id(user_id)
|
118
|
+
object = Result.new do |response_body|
|
119
|
+
response_body['events']
|
120
|
+
end
|
121
|
+
request = get object, "/api/user/#{user_id}/events"
|
122
|
+
object
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def populate(response_body)
|
128
|
+
extract_attributes_from(response_body, 'event')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Amiando
|
2
|
+
class Request < Typhoeus::Request
|
3
|
+
attr_reader :object
|
4
|
+
|
5
|
+
def initialize(object, verb, path, params)
|
6
|
+
@object = object
|
7
|
+
|
8
|
+
if verb == :post
|
9
|
+
path = build_url(path, default_params)
|
10
|
+
else
|
11
|
+
path = build_url(path)
|
12
|
+
params = default_params.merge(params || {})
|
13
|
+
end
|
14
|
+
|
15
|
+
super(path, :method => verb, :params => params, :verbose => 1)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def default_params
|
21
|
+
default = {
|
22
|
+
:format => :json,
|
23
|
+
:version => 1
|
24
|
+
}
|
25
|
+
default.merge!(:apikey => Amiando.api_key) if Amiando.api_key
|
26
|
+
default
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_url(url, merge_params = {})
|
30
|
+
url = URI.join(Amiando.base_url, url).to_s
|
31
|
+
unless merge_params.empty?
|
32
|
+
query_params = merge_params.map{|k,v| "#{k}=#{v}"}.join('&')
|
33
|
+
url = "#{url}?#{query_params}"
|
34
|
+
end
|
35
|
+
url
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Amiando
|
2
|
+
class Resource
|
3
|
+
attr_accessor :request, :response
|
4
|
+
attr_reader :success, :attributes
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def map(local, remote, options = {})
|
8
|
+
mapping[local] = remote
|
9
|
+
typecasting[local] = options[:type] if options[:type]
|
10
|
+
end
|
11
|
+
|
12
|
+
def typecasting
|
13
|
+
@@typecasting ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def mapping
|
17
|
+
@@mapping ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# From { :first_name => '1', :last_name => '2' }
|
22
|
+
# to { :firstName => '1', :lastName => '2' }
|
23
|
+
def map_params(attributes)
|
24
|
+
mapped_attributes = attributes.map do |key,value|
|
25
|
+
mapped_key = mapping[key] || key
|
26
|
+
value = typecast(key, value)
|
27
|
+
[mapped_key, value]
|
28
|
+
end
|
29
|
+
Hash[mapped_attributes]
|
30
|
+
end
|
31
|
+
|
32
|
+
def reverse_map_params(attributes)
|
33
|
+
inverted_mapping = mapping.invert
|
34
|
+
mapped_attributes = attributes.map do |key,value|
|
35
|
+
key = key.to_sym
|
36
|
+
mapped_key = inverted_mapping[key] || key
|
37
|
+
value = inverse_typecast(key, value)
|
38
|
+
[mapped_key, value]
|
39
|
+
end
|
40
|
+
Hash[mapped_attributes]
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def do_request(object, verb, path, options = {})
|
46
|
+
req = Request.new(object, verb, path, options[:params] || {})
|
47
|
+
object.request = req
|
48
|
+
|
49
|
+
req.on_complete do |response|
|
50
|
+
|
51
|
+
# Raise different errors depending on the return codes
|
52
|
+
case response.code
|
53
|
+
when 403
|
54
|
+
raise Error::NotAuthorized.new(response.body)
|
55
|
+
when 404
|
56
|
+
raise Error::NotFound.new(response.body)
|
57
|
+
when 503
|
58
|
+
raise Error::ServiceDown.new(response.body)
|
59
|
+
end
|
60
|
+
|
61
|
+
parsed_body = Yajl::Parser.parse(response.body)
|
62
|
+
|
63
|
+
if parsed_body['errors'] && parsed_body['errors'].include?('com.amiando.api.rest.MissingParam.apikey')
|
64
|
+
raise Error::MissingApiKey.new('This call requires an apikey')
|
65
|
+
end
|
66
|
+
|
67
|
+
object.response = response
|
68
|
+
object.send(options[:populate_method] || :populate, parsed_body)
|
69
|
+
end
|
70
|
+
|
71
|
+
Amiando.requests << req
|
72
|
+
end
|
73
|
+
|
74
|
+
def get(object, path, options = {})
|
75
|
+
do_request(object, :get, path, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def post(object, path, options = {})
|
79
|
+
do_request(object, :post, path, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def typecast(key, value)
|
83
|
+
if typecasting[key] == :time || value.is_a?(Time)
|
84
|
+
value.iso8601
|
85
|
+
else
|
86
|
+
value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def inverse_typecast(key, value)
|
91
|
+
if typecasting[key] == :time
|
92
|
+
Time.parse(value)
|
93
|
+
else
|
94
|
+
value
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def initialize(attributes = nil)
|
100
|
+
set_attributes(attributes)
|
101
|
+
end
|
102
|
+
|
103
|
+
def [](key)
|
104
|
+
@attributes[key.to_sym]
|
105
|
+
end
|
106
|
+
|
107
|
+
def method_missing(method_name, *args, &block)
|
108
|
+
if @attributes.key?(method_name) && args.empty?
|
109
|
+
@attributes[method_name]
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def id
|
116
|
+
@attributes[:id]
|
117
|
+
end
|
118
|
+
|
119
|
+
def populate(reponse_body)
|
120
|
+
raise Error::NotImplemented.new("populate method not implemented for #{self.class}")
|
121
|
+
end
|
122
|
+
|
123
|
+
def populate_create(response_body)
|
124
|
+
@attributes = {:id => response_body['id'], :errors => response_body['errors']}
|
125
|
+
@success = response_body['success']
|
126
|
+
end
|
127
|
+
|
128
|
+
def extract_attributes_from(response_body, key)
|
129
|
+
@attributes = {}
|
130
|
+
|
131
|
+
set_attributes(response_body[key])
|
132
|
+
|
133
|
+
@success = response_body['success']
|
134
|
+
end
|
135
|
+
|
136
|
+
def ==(resource)
|
137
|
+
id == resource.id
|
138
|
+
end
|
139
|
+
|
140
|
+
protected
|
141
|
+
|
142
|
+
def set_attributes(attributes)
|
143
|
+
@attributes = {}
|
144
|
+
|
145
|
+
if attributes
|
146
|
+
self.class.reverse_map_params(attributes).each do |k,v|
|
147
|
+
@attributes[k.to_sym] = v
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|