amiando 0.0.1
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.
- 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
|