ticketevolution-ruby 0.6.6 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.minimum.versions.gemfile +1 -1
- data/README.markdown +2 -2
- data/Rakefile +2 -3
- data/lib/docs/objects.markdown +1 -1
- data/lib/faraday/response/verbose_logger.rb +34 -0
- data/lib/ticket_evolution/core/connection.rb +21 -23
- data/lib/ticket_evolution/core/endpoint/request_handler.rb +19 -9
- data/lib/ticket_evolution/core/model.rb +6 -4
- data/lib/ticket_evolution/modules/update.rb +18 -5
- data/lib/ticket_evolution/version.rb +1 -1
- data/lib/ticket_evolution.rb +3 -1
- data/spec/fixtures/fake.rb +1 -1
- data/spec/fixtures/net/core/connection.yml +43 -4
- data/spec/fixtures/net/endpoints/accounts.yml +44 -0
- data/spec/fixtures/net/endpoints/brokerages.yml +44 -0
- data/spec/fixtures/net/endpoints/clients/create.yml +287 -0
- data/spec/fixtures/net/endpoints/clients/update_fail.yml +958 -0
- data/spec/fixtures/net/endpoints/clients/update_success.yml +820 -0
- data/spec/fixtures/net/endpoints/clients.yml +585 -158
- data/spec/fixtures/net/endpoints/search.yml +49 -0
- data/spec/lib/ticket_evolution/accounts_spec.rb +1 -1
- data/spec/lib/ticket_evolution/client_spec.rb +37 -1
- data/spec/lib/ticket_evolution/clients_spec.rb +2 -2
- data/spec/lib/ticket_evolution/core/connection_spec.rb +23 -15
- data/spec/lib/ticket_evolution/search_spec.rb +1 -10
- data/spec/shared_examples/endpoints/class.rb +19 -26
- data/spec/shared_examples/endpoints/update.rb +51 -12
- data/spec/support/connection.rb +2 -0
- data/ticketevolution-ruby.gemspec +2 -2
- metadata +36 -26
data/.minimum.versions.gemfile
CHANGED
data/README.markdown
CHANGED
@@ -58,7 +58,7 @@ Each set of API credentials can be combined with a mode and api version to creat
|
|
58
58
|
:version => 8 # => (optional) API version to use - the only available
|
59
59
|
version at the time of this writing is 8
|
60
60
|
:logger => nil # => (optional) Object to use for logging requests and
|
61
|
-
# responses. Any
|
61
|
+
# responses. Any 'Logger' instance object
|
62
62
|
# is valid. EX: Logger.new('log/te_api.log')
|
63
63
|
})
|
64
64
|
|
@@ -256,7 +256,7 @@ Click on the links next to each endpoint for more detail.
|
|
256
256
|
@venue = @connection.venues.show(id)
|
257
257
|
|
258
258
|
|
259
|
-
######ticketevolution-ruby v0.
|
259
|
+
######ticketevolution-ruby v0.7.0
|
260
260
|
|
261
261
|
License
|
262
262
|
-------
|
data/Rakefile
CHANGED
@@ -32,9 +32,8 @@ namespace :documentation do
|
|
32
32
|
# Endpoints
|
33
33
|
contents << load_doc('endpoints')
|
34
34
|
|
35
|
-
endpoints_connection =
|
36
|
-
endpoints_connection.
|
37
|
-
endpoints_xml = Nokogiri::XML(endpoints_connection.body_str)
|
35
|
+
endpoints_connection = Faraday.new('http://developer.ticketevolution.com/endpoints.xml').get
|
36
|
+
endpoints_xml = Nokogiri::XML(endpoints_connection.body)
|
38
37
|
|
39
38
|
endpoints_xml.xpath('//endpoint').sort_by{|x| x.xpath('name').children.to_s}.each do |xml|
|
40
39
|
presenter = ThisTask::EndpointPresenter.new(xml)
|
data/lib/docs/objects.markdown
CHANGED
@@ -16,7 +16,7 @@ Each set of API credentials can be combined with a mode and api version to creat
|
|
16
16
|
:version => 8 # => (optional) API version to use - the only available
|
17
17
|
version at the time of this writing is 8
|
18
18
|
:logger => nil # => (optional) Object to use for logging requests and
|
19
|
-
# responses. Any
|
19
|
+
# responses. Any 'Logger' instance object
|
20
20
|
# is valid. EX: Logger.new('log/te_api.log')
|
21
21
|
})
|
22
22
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Response::VerboseLogger < Response::Middleware
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize(app, logger)
|
8
|
+
super(app)
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
info "#{env[:method]} #{env[:url].to_s}"
|
16
|
+
debug('request headers') { dump_headers env[:request_headers] }
|
17
|
+
debug('request body') { env[:body] }
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_complete(env)
|
22
|
+
info('Status') { env[:status].to_s }
|
23
|
+
debug('response headers') { dump_headers env[:response_headers] }
|
24
|
+
debug('response body') { env[:body] }
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def dump_headers(headers)
|
30
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module TicketEvolution
|
2
2
|
class Connection < Base
|
3
|
-
cattr_reader :default_options, :expected_options, :oldest_version_in_service
|
3
|
+
cattr_reader :default_options, :expected_options, :oldest_version_in_service, :adapter
|
4
4
|
cattr_accessor :protocol, :url_base
|
5
5
|
|
6
6
|
@@oldest_version_in_service = 8
|
@@ -24,7 +24,10 @@ module TicketEvolution
|
|
24
24
|
@@url_base = "ticketevolution.com"
|
25
25
|
@@protocol = "https"
|
26
26
|
|
27
|
+
@@adapter = :net_http
|
28
|
+
|
27
29
|
def initialize(opts = {})
|
30
|
+
@adapter = self.class.adapter
|
28
31
|
@config = self.class.default_options.merge(opts)
|
29
32
|
@config.delete_if{|k, v| ! TicketEvolution::Connection.expected_options.include?(k)}
|
30
33
|
|
@@ -56,27 +59,31 @@ module TicketEvolution
|
|
56
59
|
end
|
57
60
|
|
58
61
|
def sign(method, path, content = nil)
|
62
|
+
d = "#{method} #{process_params(method, path, content).gsub(TicketEvolution::Connection.protocol+'://', '').gsub(/\:\d{2,5}\//, '/')}"
|
59
63
|
Base64.encode64(
|
60
64
|
OpenSSL::HMAC.digest(
|
61
65
|
OpenSSL::Digest::Digest.new('sha256'),
|
62
66
|
@config[:secret],
|
63
|
-
|
67
|
+
d
|
64
68
|
)).chomp
|
65
69
|
end
|
66
70
|
|
67
71
|
def build_request(method, path, params = nil)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
72
|
+
options = {
|
73
|
+
:headers => {
|
74
|
+
"X-Signature" => sign(method, self.uri(path), params),
|
75
|
+
"X-Token" => @config[:token]
|
76
|
+
},
|
77
|
+
:ssl => {
|
78
|
+
:verify => @config[:ssl_verify]
|
79
|
+
}
|
80
|
+
}
|
81
|
+
options[:ssl][:verify] = false unless @config[:mode].to_s == 'production' ## REMOVE ME WHEN SANDBOX SSL IS FIXED
|
82
|
+
options[:params] = params if method == :GET
|
83
|
+
options[:headers]["Accept"] = "application/vnd.ticketevolution.api+json; version=#{@config[:version]}" unless @config[:version] > 8
|
84
|
+
Faraday.new(self.uri(path), options) do |builder|
|
85
|
+
builder.use Faraday::Response::VerboseLogger, self.logger if self.logger.present?
|
86
|
+
builder.adapter @adapter
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
@@ -90,15 +97,6 @@ module TicketEvolution
|
|
90
97
|
MultiJson.encode(params)
|
91
98
|
end
|
92
99
|
|
93
|
-
def generate_url(method, uri, params)
|
94
|
-
case method
|
95
|
-
when :GET
|
96
|
-
process_params(method, uri, params)
|
97
|
-
else
|
98
|
-
uri
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
100
|
def process_params(method, uri, params)
|
103
101
|
"#{uri}?#{if params.present?
|
104
102
|
case method
|
@@ -20,11 +20,20 @@ module TicketEvolution
|
|
20
20
|
|
21
21
|
def request(method, path, params = nil, &response_handler)
|
22
22
|
redirecting = caller.first =~ /request_handler/ ? false : true
|
23
|
-
|
24
|
-
|
25
|
-
response = self.naturalize_response
|
23
|
+
request = self.build_request(method, path, params, redirecting)
|
24
|
+
|
25
|
+
response = self.naturalize_response do
|
26
|
+
method = method.to_s.downcase.to_sym
|
27
|
+
if method == :get
|
28
|
+
request.send(method)
|
29
|
+
else
|
30
|
+
request.send(method) do |req|
|
31
|
+
req.body = MultiJson.encode(params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
26
35
|
if [301, 302].include?(response.response_code)
|
27
|
-
new_path = response.header
|
36
|
+
new_path = response.header['location'].match(/^https?:\/\/[a-zA-Z_]+[\.a-zA-Z_]+(\/[\w\/]+)[\?]*/).to_a[1]
|
28
37
|
self.request(method, new_path, params, &response_handler)
|
29
38
|
elsif response.response_code >= 300
|
30
39
|
TicketEvolution::ApiError.new(response)
|
@@ -38,12 +47,13 @@ module TicketEvolution
|
|
38
47
|
self.connection.build_request(method, "#{build_path ? self.base_path : ''}#{path}", params)
|
39
48
|
end
|
40
49
|
|
41
|
-
def naturalize_response(response)
|
50
|
+
def naturalize_response(response = nil)
|
51
|
+
response = yield if block_given?
|
42
52
|
OpenStruct.new.tap do |resp|
|
43
|
-
resp.header = response.
|
44
|
-
resp.response_code = response.
|
45
|
-
resp.body = MultiJson.decode(response.
|
46
|
-
resp.server_message = (CODES[
|
53
|
+
resp.header = response.headers
|
54
|
+
resp.response_code = response.status
|
55
|
+
resp.body = MultiJson.decode(response.body).merge({:connection => self.connection})
|
56
|
+
resp.server_message = (CODES[resp.response_code] || ['Unknown Error']).last
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
@@ -48,10 +48,12 @@ module TicketEvolution
|
|
48
48
|
define_method(name) do
|
49
49
|
begin
|
50
50
|
obj = @table[name]
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
unless obj.nil?
|
52
|
+
def obj.endpoint=(e); @endpoint = e; end
|
53
|
+
def obj.method_missing(method, *args); @endpoint.send(method, *args); end
|
54
|
+
named_endpoint = "#{self.plural_class_name}::#{name.to_s.camelize}".constantize
|
55
|
+
obj.endpoint = named_endpoint.new(:parent => self.plural_class.new(:id => self.id, :parent => @connection))
|
56
|
+
end
|
55
57
|
obj
|
56
58
|
rescue
|
57
59
|
@table[name]
|
@@ -4,20 +4,33 @@ module TicketEvolution
|
|
4
4
|
def self.included(klass)
|
5
5
|
Class.new{extend SingularClass}.singular_class(klass.name).send(:include, Module.new{
|
6
6
|
def update_attributes(params)
|
7
|
-
|
8
|
-
|
7
|
+
atts = self.attributes.merge(params)
|
8
|
+
id = atts.delete(:id)
|
9
|
+
response = plural_class.new({:parent => @connection, :id => id}).update(atts)
|
10
|
+
if response.is_a?(TicketEvolution::ApiError)
|
11
|
+
response
|
12
|
+
else
|
13
|
+
self.attributes = response.attributes
|
14
|
+
self
|
15
|
+
end
|
9
16
|
end
|
10
17
|
|
11
18
|
def save
|
12
|
-
|
13
|
-
plural_class.new({:parent => @connection, :id => atts.delete(:id)}).update(atts)
|
19
|
+
update_attributes({})
|
14
20
|
end
|
15
21
|
})
|
16
22
|
end
|
17
23
|
|
18
24
|
def update(params = nil)
|
19
25
|
ensure_id
|
20
|
-
request(:PUT,
|
26
|
+
request(:PUT, nil, params, &method(:build_for_update))
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_for_update(response)
|
30
|
+
singular_class.new(response.body.merge({
|
31
|
+
:status_code => response.response_code,
|
32
|
+
:server_message => response.server_message
|
33
|
+
}))
|
21
34
|
end
|
22
35
|
end
|
23
36
|
end
|
data/lib/ticket_evolution.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'yajl'
|
3
3
|
require 'multi_json'
|
4
|
-
require '
|
4
|
+
require 'faraday'
|
5
5
|
|
6
6
|
require 'ostruct'
|
7
7
|
require 'base64'
|
@@ -18,6 +18,8 @@ require 'active_support/core_ext/module'
|
|
18
18
|
require 'active_support/core_ext/object'
|
19
19
|
require 'active_support/inflector'
|
20
20
|
|
21
|
+
require 'faraday/response/verbose_logger'
|
22
|
+
|
21
23
|
if ActiveSupport::VERSION::STRING < "3.1.0"
|
22
24
|
class Hash
|
23
25
|
def to_param(namespace = nil)
|
data/spec/fixtures/fake.rb
CHANGED
@@ -26,7 +26,7 @@ class Fake
|
|
26
26
|
|
27
27
|
def self.redirect_response
|
28
28
|
r = self.response
|
29
|
-
r.header =
|
29
|
+
r.header = {'location' => 'http://api.ticketevolution.com/something_else/1'}
|
30
30
|
r.response_code = 302
|
31
31
|
r.server_message = TicketEvolution::Endpoint::RequestHandler::CODES[302].last
|
32
32
|
r
|
@@ -86,7 +86,7 @@
|
|
86
86
|
accept:
|
87
87
|
- application/vnd.ticketevolution.api+json; version=8
|
88
88
|
x-signature:
|
89
|
-
-
|
89
|
+
- 6tWs3CIO4szKWCKxo8OkrtPCxTsdgjAT32LrpgZvr4M=
|
90
90
|
x-token:
|
91
91
|
- 621e8a816a4e31a4dcf9f450e6de150f
|
92
92
|
response: !ruby/struct:VCR::Response
|
@@ -107,7 +107,7 @@
|
|
107
107
|
location:
|
108
108
|
- http://developer.ticketevolution.com
|
109
109
|
x-runtime:
|
110
|
-
- '0.
|
110
|
+
- '0.001729'
|
111
111
|
content-length:
|
112
112
|
- '102'
|
113
113
|
server:
|
@@ -123,7 +123,7 @@
|
|
123
123
|
accept:
|
124
124
|
- application/vnd.ticketevolution.api+json; version=8
|
125
125
|
x-signature:
|
126
|
-
-
|
126
|
+
- 6tWs3CIO4szKWCKxo8OkrtPCxTsdgjAT32LrpgZvr4M=
|
127
127
|
x-token:
|
128
128
|
- 621e8a816a4e31a4dcf9f450e6de150f
|
129
129
|
response: !ruby/struct:VCR::Response
|
@@ -144,7 +144,46 @@
|
|
144
144
|
location:
|
145
145
|
- http://developer.ticketevolution.com
|
146
146
|
x-runtime:
|
147
|
-
- '0.
|
147
|
+
- '0.001729'
|
148
|
+
content-length:
|
149
|
+
- '102'
|
150
|
+
server:
|
151
|
+
- nginx/1.0.11 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)
|
152
|
+
body: <html><body>You are being <a href="http://developer.ticketevolution.com">redirected</a>.</body></html>
|
153
|
+
http_version: '1.1'
|
154
|
+
- !ruby/struct:VCR::HTTPInteraction
|
155
|
+
request: !ruby/struct:VCR::Request
|
156
|
+
method: :get
|
157
|
+
uri: https://api.sandbox.ticketevolution.com:443/
|
158
|
+
body: !!null
|
159
|
+
headers:
|
160
|
+
x-signature:
|
161
|
+
- EHMCoxW80aA60GAi04x5zWHsthNwAijm8tu85Dw9mw0=
|
162
|
+
x-token:
|
163
|
+
- 621e8a816a4e31a4dcf9f450e6de150f
|
164
|
+
accept:
|
165
|
+
- application/vnd.ticketevolution.api+json; version=8
|
166
|
+
accept-encoding:
|
167
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
168
|
+
response: !ruby/struct:VCR::Response
|
169
|
+
status: !ruby/struct:VCR::ResponseStatus
|
170
|
+
code: 301
|
171
|
+
message: Moved Permanently
|
172
|
+
headers:
|
173
|
+
content-type:
|
174
|
+
- text/html
|
175
|
+
connection:
|
176
|
+
- keep-alive
|
177
|
+
status:
|
178
|
+
- '301'
|
179
|
+
x-powered-by:
|
180
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.11
|
181
|
+
x-ua-compatible:
|
182
|
+
- IE=Edge,chrome=1
|
183
|
+
location:
|
184
|
+
- http://developer.ticketevolution.com
|
185
|
+
x-runtime:
|
186
|
+
- '0.002040'
|
148
187
|
content-length:
|
149
188
|
- '102'
|
150
189
|
server:
|
@@ -327,3 +327,47 @@
|
|
327
327
|
- nginx/1.0.11 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)
|
328
328
|
body: <html><body>You are being <a href="http://developer.ticketevolution.com">redirected</a>.</body></html>
|
329
329
|
http_version: '1.1'
|
330
|
+
- !ruby/struct:VCR::HTTPInteraction
|
331
|
+
request: !ruby/struct:VCR::Request
|
332
|
+
method: :get
|
333
|
+
uri: https://api.sandbox.ticketevolution.com:443/accounts/62
|
334
|
+
body: !!null
|
335
|
+
headers:
|
336
|
+
x-signature:
|
337
|
+
- pJI/Zi+UHr/bfyNIT2P604nnFQdEoC6CyuasOGhKP68=
|
338
|
+
x-token:
|
339
|
+
- b2b5a7a33b1a78896ed1b53d81c5c9cc
|
340
|
+
accept:
|
341
|
+
- application/vnd.ticketevolution.api+json; version=8
|
342
|
+
accept-encoding:
|
343
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
344
|
+
response: !ruby/struct:VCR::Response
|
345
|
+
status: !ruby/struct:VCR::ResponseStatus
|
346
|
+
code: 200
|
347
|
+
message: OK
|
348
|
+
headers:
|
349
|
+
content-type:
|
350
|
+
- application/vnd.ticketevolution.api+json; version=8; charset=utf-8
|
351
|
+
transfer-encoding:
|
352
|
+
- chunked
|
353
|
+
connection:
|
354
|
+
- keep-alive
|
355
|
+
status:
|
356
|
+
- '200'
|
357
|
+
x-powered-by:
|
358
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.11
|
359
|
+
etag:
|
360
|
+
- ! '"2aa05292e24fd9ebd325cc99027a64a1"'
|
361
|
+
x-ua-compatible:
|
362
|
+
- IE=Edge,chrome=1
|
363
|
+
x-runtime:
|
364
|
+
- '0.057554'
|
365
|
+
cache-control:
|
366
|
+
- max-age=0, private, must-revalidate
|
367
|
+
strict-transport-security:
|
368
|
+
- max-age=31536000
|
369
|
+
server:
|
370
|
+
- nginx/1.0.11 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)
|
371
|
+
body: ! '{"balance":"8583.71","url":"/accounts/62","updated_at":"2012-02-13T18:47:04Z","currency":"USD","id":"62","client":{"url":"/clients/3","name":"Main
|
372
|
+
Office","id":"3"}}'
|
373
|
+
http_version: '1.1'
|
@@ -255,3 +255,47 @@
|
|
255
255
|
- NY","_score":1.4142135,"name":"Totally New York","url":"/brokerages/725","id":"725","updated_at":"2011-02-10T13:44:47Z"},{"_type":"Brokerage","natb_member":false,"abbreviation":"At
|
256
256
|
New York","_score":1.4142135,"name":"At New York & Company","url":"/brokerages/781","id":"781","updated_at":"2011-03-28T16:21:41Z"}]}'
|
257
257
|
http_version: '1.1'
|
258
|
+
- !ruby/struct:VCR::HTTPInteraction
|
259
|
+
request: !ruby/struct:VCR::Request
|
260
|
+
method: :get
|
261
|
+
uri: https://api.sandbox.ticketevolution.com:443/brokerages/2
|
262
|
+
body: !!null
|
263
|
+
headers:
|
264
|
+
x-signature:
|
265
|
+
- 36B0ISsVd28X7Ml4r2v/QTYLf0q9lCnA0WFb98NZ004=
|
266
|
+
x-token:
|
267
|
+
- b2b5a7a33b1a78896ed1b53d81c5c9cc
|
268
|
+
accept:
|
269
|
+
- application/vnd.ticketevolution.api+json; version=8
|
270
|
+
accept-encoding:
|
271
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
272
|
+
response: !ruby/struct:VCR::Response
|
273
|
+
status: !ruby/struct:VCR::ResponseStatus
|
274
|
+
code: 200
|
275
|
+
message: OK
|
276
|
+
headers:
|
277
|
+
content-type:
|
278
|
+
- application/vnd.ticketevolution.api+json; version=8; charset=utf-8
|
279
|
+
transfer-encoding:
|
280
|
+
- chunked
|
281
|
+
connection:
|
282
|
+
- keep-alive
|
283
|
+
status:
|
284
|
+
- '200'
|
285
|
+
x-powered-by:
|
286
|
+
- Phusion Passenger (mod_rails/mod_rack) 3.0.11
|
287
|
+
etag:
|
288
|
+
- ! '"6d78396d1811212dc31c155b1b14a8a7"'
|
289
|
+
x-ua-compatible:
|
290
|
+
- IE=Edge,chrome=1
|
291
|
+
x-runtime:
|
292
|
+
- '0.447611'
|
293
|
+
cache-control:
|
294
|
+
- max-age=0, private, must-revalidate
|
295
|
+
strict-transport-security:
|
296
|
+
- max-age=31536000
|
297
|
+
server:
|
298
|
+
- nginx/1.0.11 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)
|
299
|
+
body: ! '{"natb_member":true,"url":"/brokerages/2","updated_at":"2012-01-11T23:07:43Z","abbreviation":"Golden
|
300
|
+
Tickets","name":"Golden Tickets","id":"2"}'
|
301
|
+
http_version: '1.1'
|