ticketevolution-ruby 0.6.6 → 0.7.0

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.
@@ -1,7 +1,7 @@
1
1
  source :gemcutter
2
2
 
3
3
  gem 'activesupport', '3.0.0'
4
- gem 'curb', '0.7.8'
4
+ gem 'faraday', '0.7.3'
5
5
  gem 'yajl-ruby', '0.7.7'
6
6
  gem 'multi_json', '0.0.4'
7
7
  gem 'nokogiri', '1.4.3'
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 object which responds to '<<'
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.6.2
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 = Curl::Easy.new('http://developer.ticketevolution.com/endpoints.xml')
36
- endpoints_connection.http_get
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)
@@ -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 object which responds to '<<'
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
- "#{method} #{process_params(method, path, content).gsub(TicketEvolution::Connection.protocol+'://', '').gsub(/\:\d{2,5}\//, '/')}"
67
+ d
64
68
  )).chomp
65
69
  end
66
70
 
67
71
  def build_request(method, path, params = nil)
68
- Curl::Easy.new(generate_url(method, self.uri(path), params)) do |request|
69
- if @config.has_key?(:ssl_verify)
70
- request.ssl_verify_host = @config[:ssl_verify]
71
- request.ssl_verify_peer = @config[:ssl_verify]
72
- end
73
- if self.logger.present?
74
- request.on_debug { |type, data| self.logger << data }
75
- end
76
- request.post_body = post_body(params) unless method == :GET
77
- request.headers["Accept"] = "application/vnd.ticketevolution.api+json; version=#{@config[:version]}" unless @config[:version] > 8
78
- request.headers["X-Signature"] = sign(method, self.uri(path), params)
79
- request.headers["X-Token"] = @config[:token]
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
- response = self.build_request(method, path, params, redirecting)
24
- response.http(method)
25
- response = self.naturalize_response(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.match(/Location: ([\w\.:\/]*)/).to_a[1].to_s.match(/^https?:\/\/[a-zA-Z_]+[\.a-zA-Z_]+(\/[\w\/]+)[\?]*/).to_a[1]
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.header_str
44
- resp.response_code = response.response_code
45
- resp.body = MultiJson.decode(response.body_str).merge({:connection => self.connection})
46
- resp.server_message = (CODES[response.response_code] || ['Unknown Error']).last
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
- def obj.endpoint=(e); @endpoint = e; end
52
- def obj.method_missing(method, *args); @endpoint.send(method, *args); end
53
- named_endpoint = "#{self.plural_class_name}::#{name.to_s.camelize}".constantize
54
- obj.endpoint = named_endpoint.new(:parent => self.plural_class.new(:id => self.id, :parent => @connection))
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
- params.each{|k, v| send("#{k}=", process_datum(v))}
8
- plural_class.new({:parent => @connection, :id => params.delete(:id)}).update(params)
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
- atts = self.attributes
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, "/#{self.id}", params)
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
@@ -1,3 +1,3 @@
1
1
  module TicketEvolution
2
- VERSION = '0.6.6'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'yajl'
3
3
  require 'multi_json'
4
- require 'curb'
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)
@@ -26,7 +26,7 @@ class Fake
26
26
 
27
27
  def self.redirect_response
28
28
  r = self.response
29
- r.header = "HTTP/1.1 301 Moved Permanently\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nStatus: 301\r\nX-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.11\r\nX-UA-Compatible: IE=Edge,chrome=1\r\nLocation: http://api.ticketevolution.com/something_else/1\r\nX-Runtime: 0.001401\r\nContent-Length: 102\r\nServer: nginx/1.0.11 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)\r\n\r\n"
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
- - F/qzyf3TZi71VSZ7GtP9yfgdfB/LFGKIqup6s5GoQ8E=
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.001958'
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
- - F/qzyf3TZi71VSZ7GtP9yfgdfB/LFGKIqup6s5GoQ8E=
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.001958'
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'