ticketinghub 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 130aebb5aef14ed672ce1cde1860e5e0b448ed02
4
+ data.tar.gz: 7d9fc8c378fae6e5c96674ec0d2ec9adda1c36d8
5
+ SHA512:
6
+ metadata.gz: 3874d989f510f5c9f311362bb73a2c6113fd46a558a9654884411756156ad986e3e439b759e184e1eeeeb7d1d8251abb7dbba439857a29ebf270a90ee764ed32
7
+ data.tar.gz: 97acdb59c6818625a952420cf489e6f5bf7245f23dcc624f788e982ec9da92e8cc438c0daf02a5686a542d8832e3fd015edd1ae82971f1b3b660de8ef826d536
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ features/**/*.feature
4
+ -
5
+ LICENSE.md
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,18 @@
1
+ ## Submitting a Pull Request
2
+ 1. [Fork the repository.][fork]
3
+ 2. [Create a topic branch.][branch]
4
+ 3. Add specs for your unimplemented feature or bug fix.
5
+ 4. Run `bundle exec rake spec`. If your specs pass, return to step 3.
6
+ 5. Implement your feature or bug fix.
7
+ 6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
8
+ 7. Run `open coverage/index.html`. If your changes are not completely covered
9
+ by your tests, return to step 3.
10
+ 8. Add documentation for your feature or bug fix.
11
+ 9. Run `bundle exec rake doc:yard`. If your changes are not 100% documented, go
12
+ back to step 8.
13
+ 10. Add, commit, and push your changes.
14
+ 11. [Submit a pull request.][pr]
15
+
16
+ [fork]: https://help.github.com/articles/fork-a-repo
17
+ [branch]: http://learn.github.com/p/branching.html
18
+ [pr]: https://help.github.com/articles/using-pull-requests
data/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2013 TicketingHub Ltd
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
9
+
10
+ namespace :doc do
11
+ require 'yard'
12
+ YARD::Rake::YardocTask.new do |task|
13
+ task.files = ['README.md', 'LICENSE.md', 'lib/**/*.rb']
14
+ task.options = [
15
+ '--output-dir', 'doc/yard',
16
+ '--markup', 'markdown',
17
+ ]
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'ticketing_hub/configuration'
2
+ require_relative 'ticketing_hub/client'
3
+ require_relative 'ticketing_hub/error'
4
+
5
+ module TicketingHub
6
+ extend Configuration
7
+
8
+ class << self
9
+ def new(options={})
10
+ TicketingHub::Client.new options
11
+ end
12
+
13
+ def method_missing(method, *args, &block)
14
+ return super unless new.respond_to? method
15
+ new.send method, *args, &block
16
+ end
17
+
18
+ def respond_to?(method, include_private=false)
19
+ new.respond_to?(method, include_private) || super(method, include_private)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module TicketingHub
2
+ module Authentication
3
+ def authentication
4
+ { token: token, secret: secret }
5
+ end
6
+
7
+ def authenticated?
8
+ ! authentication[:secret].nil?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'authentication'
2
+ require_relative 'connection'
3
+ require_relative 'request'
4
+ require_relative 'resource'
5
+
6
+ require_relative 'venue'
7
+ require_relative 'order'
8
+ require_relative 'consumer'
9
+ require_relative 'tier'
10
+ require_relative 'ticket'
11
+
12
+ module TicketingHub
13
+ class Client
14
+ include TicketingHub::Authentication
15
+ include TicketingHub::Connection
16
+ include TicketingHub::Request
17
+
18
+ attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
19
+
20
+ def initialize(options={})
21
+ options = TicketingHub.options.merge(options)
22
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
23
+ send("#{key}=", options[key])
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_support'
2
+
3
+ module TicketingHub
4
+ class Collection
5
+ include Enumerable
6
+
7
+ def self.from_association parent, child_class, options={}
8
+ path = [ parent.model_name.route_key, parent.id,
9
+ child_class.model_name.route_key ].join '/'
10
+ new path, parent, child_class
11
+ end
12
+
13
+ attr_accessor :elements, :parent, :child_class
14
+
15
+ def initialize(elements, parent, child_class)
16
+ self.elements = elements
17
+ self.parent = parent
18
+ self.child_class = child_class
19
+ end
20
+
21
+ def to_a
22
+ elements.dup
23
+ end
24
+
25
+ def elements
26
+ unless @elements.is_a? Array
27
+ @elements = parent.client.get(path, options)
28
+ .map { |attrs| child_class.new attrs, parent.client }
29
+ end
30
+
31
+ @elements
32
+ end
33
+
34
+ def method_missing(method, *args, &block)
35
+ return super unless [].respond_to? method
36
+ elements.send method, *args, &block
37
+ end
38
+
39
+ def build(attributes = {})
40
+ child_class.new.tap do |resource|
41
+ { parent.foreign_key => parent.id,
42
+ parent.model_name.singular_route_key => parent }.merge(attributes).each do |key, value|
43
+ resource.send "#{key}=", value if resource.respond_to? "#{key}="
44
+ end
45
+ end
46
+ end
47
+
48
+ def create(*args)
49
+ build.create *args
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,67 @@
1
+ require 'faraday'
2
+ require_relative 'version'
3
+
4
+ module TicketingHub
5
+ module Configuration
6
+
7
+ VALID_OPTIONS_KEYS = [
8
+ :adapter,
9
+ :faraday_config_block,
10
+ :api_version,
11
+ :api_endpoint,
12
+ :web_endpoint,
13
+ :status_api_endpoint,
14
+ :token,
15
+ :secret,
16
+ :proxy,
17
+ :user_agent,
18
+ :request_host,
19
+ :auto_traversal].freeze
20
+
21
+ DEFAULT_ADAPTER = Faraday.default_adapter
22
+ DEFAULT_API_VERSION = 1
23
+ DEFAULT_API_ENDPOINT = ENV['TH_API_ENDPOINT'] || 'https://api.ticketinghub.com/reseller/'
24
+ DEFAULT_USER_AGENT = "TicketingHub Ruby Gem #{TicketingHub::VERSION}".freeze
25
+ DEFAULT_AUTO_TRAVERSAL = false
26
+
27
+ attr_accessor(*VALID_OPTIONS_KEYS)
28
+
29
+ def self.extended(base)
30
+ base.reset
31
+ end
32
+
33
+ def configure
34
+ yield self
35
+ end
36
+
37
+ def options
38
+ VALID_OPTIONS_KEYS.each_with_object Hash.new do |key, memo|
39
+ memo[key] = send key
40
+ end
41
+ end
42
+
43
+ def api_endpoint=(value)
44
+ @api_endpoint = File.join value, ''
45
+ end
46
+
47
+ def web_endpoint=(value)
48
+ @web_endpoint = File.join value, ''
49
+ end
50
+
51
+ def faraday_config(&block)
52
+ @faraday_config_block = block
53
+ end
54
+
55
+ def reset
56
+ self.adapter = DEFAULT_ADAPTER
57
+ self.api_version = DEFAULT_API_VERSION
58
+ self.api_endpoint = DEFAULT_API_ENDPOINT
59
+ self.token = nil
60
+ self.secret = nil
61
+ self.proxy = nil
62
+ self.request_host = nil
63
+ self.user_agent = DEFAULT_USER_AGENT
64
+ self.auto_traversal = DEFAULT_AUTO_TRAVERSAL
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,52 @@
1
+ require 'faraday_middleware'
2
+ require_relative 'error'
3
+
4
+ module TicketingHub
5
+ class ErrorHandler < Faraday::Response::Middleware
6
+ ERROR_MAP = {
7
+ 400 => TicketingHub::BadRequest,
8
+ 401 => TicketingHub::Unauthorized,
9
+ 403 => TicketingHub::Forbidden,
10
+ 404 => TicketingHub::NotFound,
11
+ 406 => TicketingHub::NotAcceptable,
12
+ 422 => TicketingHub::UnprocessableEntity,
13
+ 500 => TicketingHub::InternalServerError,
14
+ 501 => TicketingHub::NotImplemented,
15
+ 502 => TicketingHub::BadGateway,
16
+ 503 => TicketingHub::ServiceUnavailable
17
+ }
18
+
19
+ def on_complete(response)
20
+ key = response[:status].to_i
21
+ raise ERROR_MAP[key].new(response) if ERROR_MAP.has_key? key
22
+ end
23
+ end
24
+
25
+ # @private
26
+ module Connection
27
+ private
28
+ def connection(options={})
29
+ options = {
30
+ authenticate: true,
31
+ force_urlencoded: false,
32
+ raw: false,
33
+ ssl: { verify: false }
34
+ }.merge(options)
35
+
36
+ options.merge! proxy: proxy unless proxy.nil?
37
+
38
+ # TODO: Don't build on every request
39
+ Faraday.new(options) do |builder|
40
+ builder.request options[:force_urlencoded] ? :url_encoded : :json
41
+ builder.use ErrorHandler
42
+ builder.use FaradayMiddleware::FollowRedirects
43
+ builder.use FaradayMiddleware::ParseJson, content_type: /\bjson$/
44
+ faraday_config_block.call builder if faraday_config_block
45
+ builder.adapter *adapter
46
+ end.tap do |connection|
47
+ connection.headers[:user_agent] = user_agent
48
+ connection.basic_auth authentication[:token], authentication[:secret]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ module TicketingHub
2
+ class Consumer < Resource
3
+ schema do
4
+ integer :id
5
+ string :first_name, :last_name, :email, :country
6
+ end
7
+
8
+ def self.from_fields fields
9
+ new.tap do |consumer|
10
+ consumer.instance_eval do
11
+ @schema ||= singleton_class.schema do
12
+ fields.each do |field|
13
+ type = Schema::KNOWN_ATTRIBUTE_TYPES.member?(field['type']) ? field['type'] : 'string'
14
+ send type, field['name']
15
+ end
16
+ end
17
+
18
+ fields.each do |field|
19
+ singleton_class.validates_presence_of field['name'] if field['required']
20
+ send "#{field['name']}=", field['value']
21
+ field['errors'].each { |error| errors.add field['name'], error }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,70 @@
1
+ module TicketingHub
2
+ # Custom error class for rescuing from all GitHub errors
3
+ class Error < StandardError
4
+ attr_accessor :response
5
+
6
+ def initialize(response=nil)
7
+ @response = response
8
+ super build_error_message
9
+ end
10
+
11
+ def response_body
12
+ @response_body ||=
13
+ if (body = @response[:body]) && !body.empty?
14
+ if body.is_a?(String)
15
+ MultiJson.load(body, :symbolize_keys => true)
16
+ else
17
+ body
18
+ end
19
+ else
20
+ nil
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def build_error_message
27
+ return nil if @response.nil?
28
+
29
+ message = if response_body
30
+ ": #{response_body[:error] || response_body[:message] || ''}"
31
+ else
32
+ ''
33
+ end
34
+ errors = unless message.empty?
35
+ response_body[:errors] ? ": #{response_body[:errors].map{|e|e[:message]}.join(', ')}" : ''
36
+ end
37
+ "#{@response[:method].to_s.upcase} #{@response[:url].to_s}: #{@response[:status]}#{message}#{errors}"
38
+ end
39
+ end
40
+
41
+ # Raised when GitHub returns a 400 HTTP status code
42
+ class BadRequest < Error; end
43
+
44
+ # Raised when GitHub returns a 401 HTTP status code
45
+ class Unauthorized < Error; end
46
+
47
+ # Raised when GitHub returns a 403 HTTP status code
48
+ class Forbidden < Error; end
49
+
50
+ # Raised when GitHub returns a 404 HTTP status code
51
+ class NotFound < Error; end
52
+
53
+ # Raised when GitHub returns a 406 HTTP status code
54
+ class NotAcceptable < Error; end
55
+
56
+ # Raised when GitHub returns a 422 HTTP status code
57
+ class UnprocessableEntity < Error; end
58
+
59
+ # Raised when GitHub returns a 500 HTTP status code
60
+ class InternalServerError < Error; end
61
+
62
+ # Raised when GitHub returns a 501 HTTP status code
63
+ class NotImplemented < Error; end
64
+
65
+ # Raised when GitHub returns a 502 HTTP status code
66
+ class BadGateway < Error; end
67
+
68
+ # Raised when GitHub returns a 503 HTTP status code
69
+ class ServiceUnavailable < Error; end
70
+ end
@@ -0,0 +1,67 @@
1
+ require 'money'
2
+ require 'active_support'
3
+
4
+ module TicketingHub
5
+ class Order < Resource
6
+ schema do
7
+ integer :id, :venue_id, :consumer_id
8
+ float :commission, :total, default: 0
9
+ string :currency
10
+ datetime :confirmed_at
11
+ end
12
+
13
+ attr_accessor :consumer_fields
14
+
15
+ has_many :tickets
16
+
17
+ belongs_to :venue
18
+ belongs_to :consumer
19
+
20
+ def total
21
+ attributes[:total].to_money currency
22
+ end
23
+
24
+ def commission
25
+ attributes[:commission].to_money currency
26
+ end
27
+
28
+ def consumer_fields
29
+ @consumer_fields ||= client.get("venues/#{venue_id}/orders/new")['consumer_fields'].map do |field|
30
+ HashWithIndifferentAccess.new field
31
+ end
32
+ end
33
+
34
+ def tickets=(tickets)
35
+ @tickets = tickets.map { |ticket| Ticket.new ticket, client }
36
+ end
37
+
38
+ def consumer_fields=(fields)
39
+ @consumer_fields = fields
40
+ self.consumer = Consumer.from_fields consumer_fields
41
+ end
42
+
43
+ def pdf
44
+ client.get("orders/#{id}", accept: 'application/pdf')
45
+ end
46
+
47
+ def create attributes={}
48
+ self.attributes = attributes
49
+ if tiers = attributes.delete(:tiers)
50
+ tickets = attributes[:tickets_attributes] ||= []
51
+ tiers.each do |tier_id, qty|
52
+ qty.to_i.times { tickets.push tier_id: tier_id.to_i }
53
+ end
54
+ end
55
+
56
+ if (consumer = attributes.delete(:consumer)).try :persisted?
57
+ (attributes[:consumer_attributes] ||= {})[:email] = consumer.email
58
+ end
59
+
60
+ venue.orders.build client.post("venues/#{venue_id}/orders", attributes)
61
+ rescue TicketingHub::BadRequest => error
62
+ self.tap { errors.add :tickets, error.response_body['message'] }
63
+ rescue TicketingHub::UnprocessableEntity => error
64
+ venue.orders.build error.response_body
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,80 @@
1
+ require 'multi_json'
2
+
3
+ module TicketingHub
4
+ module Request
5
+
6
+ def delete(path, options={})
7
+ request(:delete, path, options).body
8
+ end
9
+
10
+ def get(path, options={})
11
+ response = request(:get, path, options)
12
+ body = response.body
13
+
14
+ if auto_traversal && body.is_a?(Array)
15
+ while next_url = links(response)['next']
16
+ response = request(:get, next_url, options)
17
+ body += response.body
18
+ end
19
+ end
20
+
21
+ body
22
+ end
23
+
24
+ def patch(path, options={})
25
+ request(:patch, path, options).body
26
+ end
27
+
28
+ def post(path, options={})
29
+ request(:post, path, options).body
30
+ end
31
+
32
+ def put(path, options={})
33
+ request(:put, path, options).body
34
+ end
35
+
36
+ private
37
+
38
+ # Executes the request, checking if it was successful
39
+ #
40
+ # @return [Boolean] True on success, false otherwise
41
+ def boolean_from_response(method, path, options={})
42
+ request(method, path, options).status == 204
43
+ rescue TicketingHub::NotFound
44
+ false
45
+ end
46
+
47
+ def request(method, path, options={})
48
+ force_urlencoded = options.delete(:force_urlencoded) || false
49
+ url = options.delete(:endpoint) || api_endpoint
50
+ conn_options = { force_urlencoded: force_urlencoded, url: url }
51
+
52
+ connection(conn_options).send(method) do |request|
53
+ request.headers['Accept'] = options.delete(:accept) || 'application/json'
54
+
55
+ case method
56
+ when :get, :delete, :head
57
+ request.url(path, options)
58
+ when :patch, :post, :put
59
+ request.path = path
60
+ unless options.empty?
61
+ request.body = force_urlencoded ? options : MultiJson.dump(options)
62
+ end
63
+ end
64
+
65
+ if TicketingHub.request_host
66
+ request.headers['Host'] = TicketingHub.request_host
67
+ end
68
+ end
69
+ end
70
+
71
+ def links(response)
72
+ links = ( response.headers["Link"] || "" ).split(', ').map do |link|
73
+ url, type = link.match(/<(.*?)>; rel="(\w+)"/).captures
74
+ [ type, url ]
75
+ end
76
+
77
+ Hash[ *links.flatten ]
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,168 @@
1
+ require 'active_model'
2
+ require 'active_support'
3
+ require_relative 'schema'
4
+ require_relative 'collection'
5
+
6
+ module TicketingHub
7
+ class Resource
8
+ extend ActiveModel::Callbacks
9
+ extend ActiveModel::Naming
10
+
11
+ include ActiveModel::AttributeMethods
12
+ include ActiveModel::Serialization
13
+ include ActiveModel::Serializers::JSON
14
+ include ActiveModel::Validations
15
+ include ActiveModel::Dirty
16
+
17
+ class << self
18
+ def has_many key
19
+ attr_accessor key
20
+ define_method key do
21
+ klass = "TicketingHub::#{key.to_s.singularize.classify}".constantize
22
+ value = instance_variable_get "@#{key}"
23
+ value || Collection.from_association(self, klass).tap do |collection|
24
+ instance_variable_set "@#{key}", collection
25
+ end
26
+ end
27
+
28
+ define_method "#{key}=" do |values|
29
+ klass = "TicketingHub::#{key.to_s.singularize.classify}".constantize
30
+ instance_variable_set "@#{key}", Collection.new(values.map do |value|
31
+ value.is_a?(klass) ? value : send(key).build(value)
32
+ end, self, klass)
33
+ end
34
+ end
35
+
36
+ def belongs_to key
37
+ attr_accessor key
38
+
39
+ define_method "#{key}=" do |value|
40
+ klass = "TicketingHub::#{key.to_s.classify}".constantize
41
+ value = value.is_a?(Hash) ? klass.new(value.merge({
42
+ foreign_key => id,
43
+ model_name.singular_route_key => self
44
+ })) : value
45
+ send "#{klass.foreign_key}=", value.id
46
+ instance_variable_set "@#{key}", value
47
+ end
48
+
49
+ define_method key do
50
+ klass = "TicketingHub::#{key.to_s.classify}".constantize
51
+ value = instance_variable_get "@#{key}"
52
+ if value.nil? && (fk = send(klass.foreign_key)).present?
53
+ klass.find(fk).tap do |record|
54
+ instance_variable_set "@#{key}", record
55
+ end
56
+ else value end
57
+ end
58
+ end
59
+
60
+ def create attributes={}
61
+ new.create attributes
62
+ end
63
+
64
+ def model_name
65
+ @_model_name ||= ActiveModel::Name.new self, TicketingHub
66
+ end
67
+
68
+ def foreign_key
69
+ name.to_s.foreign_key
70
+ end
71
+
72
+ def default_client
73
+ TicketingHub::Client.new
74
+ end
75
+
76
+ def all
77
+ default_client.get(model_name.route_key).map { |attributes| new attributes }
78
+ end
79
+
80
+ def find id
81
+ new default_client.get("#{model_name.route_key}/#{id}")
82
+ end
83
+
84
+ def schema(&block)
85
+ if block_given?
86
+ undefine_attribute_methods @schema.keys if @schema.present?
87
+ @schema = TicketingHub::Schema.new(&block).tap do |schema|
88
+ attr_accessor *schema.keys
89
+ define_attribute_methods schema.keys
90
+ end
91
+ else
92
+ @schema ||= TicketingHub::Schema.new
93
+ end
94
+ end
95
+
96
+ def endpoint=(value)
97
+ @endpoint = value unless value.empty?
98
+ end
99
+
100
+ def endpoint
101
+ @endpoint || model_name.plural
102
+ end
103
+ end
104
+
105
+ delegate :foreign_key, :model_name, :schema, to: :class
106
+
107
+ attr_accessor :client, :errors, :attributes
108
+ define_model_callbacks :create, :save, :update, :destroy
109
+
110
+ def initialize(attributes = {}, client = self.class.default_client)
111
+ self.client = client
112
+ self.attributes = attributes
113
+ @errors = ActiveModel::Errors.new self
114
+ end
115
+
116
+ def ==(other)
117
+ other.equal?(self) ||
118
+ (other.instance_of?(self.class) && other.id == id && ! other.new_record?)
119
+ end
120
+
121
+ def ===(other)
122
+ object.is_a? self
123
+ end
124
+
125
+ def eql?(other)
126
+ self == other
127
+ end
128
+
129
+ def hash
130
+ id.hash
131
+ end
132
+
133
+ def endpoint
134
+ new_record?? model_name.plural : [model_name.singular, id].join('/')
135
+ end
136
+
137
+ def create attributes={}
138
+ throw 'Cannot create existing record.' if persisted?
139
+ self.attributes = client.post(endpoint, self.attributes.merge(attributes))
140
+ end
141
+
142
+ def new_record?
143
+ id.nil?
144
+ end
145
+
146
+ def persisted?
147
+ ! new_record?
148
+ end
149
+
150
+ def attributes
151
+ schema.keys.each_with_object Hash.new do |key, memo|
152
+ memo[key.to_sym] = instance_variable_get "@#{key}"
153
+ end
154
+ end
155
+
156
+ def attributes=(values)
157
+ values.each do |key, value|
158
+ send("#{key}=", value) if respond_to? "#{key}="
159
+ end
160
+ end
161
+
162
+ def column_for_attribute(name)
163
+ Class.new do
164
+ def type; schema[name] end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,30 @@
1
+ module TicketingHub
2
+ class Schema
3
+ KNOWN_ATTRIBUTE_TYPES = %w(string text integer float decimal datetime timestamp time date binary boolean)
4
+
5
+ def [] key
6
+ @attrs[key.to_s].to_sym
7
+ end
8
+
9
+ def initialize &block
10
+ @attrs = Hash.new
11
+ instance_eval &block if block_given?
12
+ end
13
+
14
+ def keys
15
+ @attrs.keys
16
+ end
17
+
18
+ def attribute name, type, options = {}
19
+ raise ArgumentError, "Unknown Attribute type: #{type.inspect} for key: #{name.inspect}" unless type.nil? || Schema::KNOWN_ATTRIBUTE_TYPES.include?(type.to_s)
20
+ tap { @attrs[name.to_s] = [type.to_s, options] }
21
+ end
22
+
23
+ KNOWN_ATTRIBUTE_TYPES.each do |type|
24
+ define_method type do |*args|
25
+ options = args.last.is_a?(::Hash) ? args.pop : {}
26
+ args.each { |name| attribute name, type, options }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require 'money'
2
+
3
+ module TicketingHub
4
+ class Ticket < Resource
5
+ schema do
6
+ integer :id, :tier_id, :order_id
7
+ float :commission, :price, default: 0
8
+ string :code
9
+ end
10
+
11
+ belongs_to :tier
12
+ belongs_to :order
13
+ delegate :currency, to: :order
14
+
15
+ def price
16
+ attributes[:price].to_money currency
17
+ end
18
+
19
+ def commission
20
+ attributes[:commission].to_money currency
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ require 'money'
2
+
3
+ module TicketingHub
4
+ class Tier < Resource
5
+ schema do
6
+ integer :id, :venue_id
7
+ string :name
8
+ text :description
9
+ float :commission, :price, default: 0
10
+ end
11
+
12
+ attr_accessor :venue
13
+ delegate :currency, to: :venue
14
+ belongs_to :venue
15
+
16
+ def price
17
+ attributes[:price].to_money currency
18
+ end
19
+
20
+ def commission
21
+ attributes[:commission].to_money currency
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ module TicketingHub
2
+ class Venue < Resource
3
+ attr_accessor :tiers, :orders
4
+
5
+ schema do
6
+ integer :id
7
+ string :name, :street_1, :street_2, :city, :region, :postcode, :country, :category, :currency
8
+ float :lat, :lng
9
+ end
10
+
11
+ has_many :tiers
12
+ has_many :orders
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module TicketingHub
2
+ VERSION = '0.0.2' unless defined?(TicketingHub::VERSION)
3
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,87 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
9
+
10
+ require 'ticketing_hub'
11
+ require 'rspec'
12
+ require 'webmock/rspec'
13
+
14
+ WebMock.disable_net_connect! allow: 'coveralls.io'
15
+
16
+ RSpec.configure do |config|
17
+ config.expect_with :rspec do |c|
18
+ c.syntax = :expect
19
+ end
20
+ end
21
+
22
+ def a_delete(url)
23
+ a_request(:delete, ticketinghub_url(url))
24
+ end
25
+
26
+ def a_get(url)
27
+ a_request(:get, ticketinghub_url(url))
28
+ end
29
+
30
+ def a_patch(url)
31
+ a_request(:patch, ticketinghub_url(url))
32
+ end
33
+
34
+ def a_post(url)
35
+ a_request(:post, ticketinghub_url(url))
36
+ end
37
+
38
+ def a_put(url)
39
+ a_request(:put, ticketinghub_url(url))
40
+ end
41
+
42
+ def stub_delete(url)
43
+ stub_request(:delete, ticketinghub_url(url))
44
+ end
45
+
46
+ def stub_get(url)
47
+ stub_request(:get, ticketinghub_url(url))
48
+ end
49
+
50
+ def stub_head(url)
51
+ stub_request(:head, ticketinghub_url(url))
52
+ end
53
+
54
+ def stub_patch(url)
55
+ stub_request(:patch, ticketinghub_url(url))
56
+ end
57
+
58
+ def stub_post(url)
59
+ stub_request(:post, ticketinghub_url(url))
60
+ end
61
+
62
+ def stub_put(url)
63
+ stub_request(:put, ticketinghub_url(url))
64
+ end
65
+
66
+ def fixture_path
67
+ File.expand_path("../fixtures", __FILE__)
68
+ end
69
+
70
+ def fixture(file)
71
+ File.new(fixture_path + '/' + file)
72
+ end
73
+
74
+ def json_response(file)
75
+ { body: fixture(file),
76
+ headers: { content_type: 'application/json; charset=utf-8' } }
77
+ end
78
+
79
+ def ticketinghub_url(url)
80
+ if url =~ /^http/
81
+ url
82
+ elsif @client && @client.authenticated?
83
+ "https://#{@client.token}:#{@client.secret}@api.ticketinghub.com#{url}"
84
+ else
85
+ "https://api.ticketinghub.com#{url}"
86
+ end
87
+ end
File without changes
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ticketing_hub/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.add_development_dependency 'bundler', '~> 1.0'
8
+ spec.add_dependency 'addressable', '~> 2.3.3'
9
+ spec.add_dependency 'faraday', '~> 0.8.6'
10
+ spec.add_dependency 'faraday_middleware', '~> 0.9.0'
11
+ spec.add_dependency 'multi_json', '~> 1.6.1'
12
+ spec.add_dependency 'money', '~> 5.1.1'
13
+ spec.add_dependency 'activemodel', '>= 3.2.12'
14
+ spec.authors = ['Oliver Morgan']
15
+ spec.description = %q{Wrapper for TicketingHub API}
16
+ spec.email = ['olly@ticketinghub.com']
17
+ spec.files = %w(.document CONTRIBUTING.md LICENSE.md Rakefile ticketinghub.gemspec)
18
+ spec.files += Dir['lib/**/*.rb']
19
+ spec.files += Dir['spec/**/*']
20
+ spec.homepage = 'https://github.com/ticketinghub/ruby-api'
21
+ spec.licenses = ['MIT']
22
+ spec.name = 'ticketinghub'
23
+ spec.platform = Gem::Platform::RUBY
24
+ spec.required_ruby_version = '>= 1.9.3'
25
+ spec.require_paths = ['lib']
26
+ spec.required_rubygems_version = '>= 1.3.6'
27
+ spec.summary = spec.description
28
+ spec.test_files = Dir['spec/**/*']
29
+ spec.version = TicketingHub::VERSION
30
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ticketinghub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Oliver Morgan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: addressable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.3.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: faraday_middleware
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: multi_json
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 1.6.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.6.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: money
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 5.1.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 5.1.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: activemodel
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: 3.2.12
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: 3.2.12
111
+ description: Wrapper for TicketingHub API
112
+ email:
113
+ - olly@ticketinghub.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .document
119
+ - CONTRIBUTING.md
120
+ - LICENSE.md
121
+ - Rakefile
122
+ - ticketinghub.gemspec
123
+ - lib/ticketing_hub/authentication.rb
124
+ - lib/ticketing_hub/client.rb
125
+ - lib/ticketing_hub/collection.rb
126
+ - lib/ticketing_hub/configuration.rb
127
+ - lib/ticketing_hub/connection.rb
128
+ - lib/ticketing_hub/consumer.rb
129
+ - lib/ticketing_hub/error.rb
130
+ - lib/ticketing_hub/order.rb
131
+ - lib/ticketing_hub/request.rb
132
+ - lib/ticketing_hub/resource.rb
133
+ - lib/ticketing_hub/schema.rb
134
+ - lib/ticketing_hub/ticket.rb
135
+ - lib/ticketing_hub/tier.rb
136
+ - lib/ticketing_hub/venue.rb
137
+ - lib/ticketing_hub/version.rb
138
+ - lib/ticketing_hub.rb
139
+ - spec/helper.rb
140
+ - spec/ticketing_hub/venue_spec.rb
141
+ homepage: https://github.com/ticketinghub/ruby-api
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '>='
152
+ - !ruby/object:Gem::Version
153
+ version: 1.9.3
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - '>='
157
+ - !ruby/object:Gem::Version
158
+ version: 1.3.6
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.0.0
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: Wrapper for TicketingHub API
165
+ test_files:
166
+ - spec/helper.rb
167
+ - spec/ticketing_hub/venue_spec.rb
168
+ has_rdoc: