queenbee 0.0.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2e2ecbf88bab97a30dc9d76d899d83235e11bffe
4
+ data.tar.gz: 1f4d8257dcbe653e9a02dd74f280a817a6ca5df2
5
+ SHA512:
6
+ metadata.gz: 8fcc250632939434fc3decdb721606b0d9fbcbcd05481d74888ff40f160f8abf226fe54033b10cea373df6b803d8d9670a00fb2ac35cccb0de27a652443e4757
7
+ data.tar.gz: 89eab4a4c89771376015ebd335a382e0f256365dd183955a957fe8c6f31aa2376175e8139ffac678dc641ba7c64eb8af10e46cbe72c774b7c26eaa3317f8cef7
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Queenbee
2
+
3
+ [![Build Status](https://semaphoreapp.com/api/v1/projects/7959e7f9-8fcb-4d10-85fe-79bc840b028c/262003/shields_badge.svg)](https://semaphoreapp.com/olimart/queenbee-ruby)
4
+
5
+ Simple gem for communicating with external API. Heavily inspired by stripe gem.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'queenbee'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install queenbee
20
+
21
+ ## Usage
22
+
23
+ In your app
24
+
25
+ 1. Set token
26
+
27
+ ```ruby
28
+ Queenbee.token = ENV['QUEENBEE_TOKEN']
29
+ ```
30
+
31
+ 2. Send order
32
+
33
+ ```ruby
34
+ Queenbee::Order.create(
35
+ date: Time.now,
36
+ currency: 'cad',
37
+ client_email: 'client@email.com',
38
+ amount: '15',
39
+ total_price: '15',
40
+ city: 'Nancy',
41
+ country: 'France',
42
+ shipping: 0,
43
+ uid: SecureRandom.hex(4),
44
+ source: 'Stripe payment form'
45
+ )
46
+ ```
47
+
48
+ **For Sinatra app** you may need to add `require 'bundler/setup'`
49
+
50
+
51
+ ## Tests
52
+
53
+ ```ruby
54
+ rake test
55
+ ```
56
+
57
+ ## Complete list of parameters
58
+
59
+ - uid (string, must be unique per application)
60
+ - date (datetime. default to record creation timestamp. Should be used to send historic data)
61
+ - currency (string. i.e. 'CAD')
62
+ - amount (decimal)
63
+ - tax (decimal)
64
+ - shipping (decimal)
65
+ - total_price (decimal)
66
+ - gift (boolean, default false)
67
+ - coupon (boolean, default false)
68
+ - coupon_code (string)
69
+ - country (string. i.e. 'Canada')
70
+ - city (string)
71
+ - url (string)
72
+ - client_email (string)
73
+ - products_count (integer, default 1)
74
+ - subscribed_at (datetime. For recurring order)
75
+ - unsubscribed_at (datetime. For recurring order)
76
+ - fees (decimal)
@@ -0,0 +1,16 @@
1
+ module Queenbee
2
+ module APIOperations
3
+ module Create
4
+ module ClassMethods
5
+ def create(params={}, token=nil)
6
+ response, token = Queenbee.request(:post, self.url, token, params)
7
+ response
8
+ end
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Queenbee
2
+ module APIOperations
3
+ module Update
4
+ module ClassMethods
5
+ def save(params = {}, token = nil)
6
+ url = self.url + '/' + params[:uid]
7
+ response, token = Queenbee.request(:put, url, token, params)
8
+ response
9
+ end
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Queenbee
2
+ class APIResource < QueenbeeObject
3
+ def self.class_name
4
+ self.name.split('::')[-1]
5
+ end
6
+
7
+ def self.url()
8
+ if self == APIResource
9
+ raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses)')
10
+ end
11
+ "/#{CGI.escape(class_name.downcase)}s"
12
+ end
13
+
14
+ def url
15
+ unless id = self['id']
16
+ raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", 'id')
17
+ end
18
+ "#{self.class.url}/#{CGI.escape(id)}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module Queenbee
2
+ class APIConnectionError < QueenbeeError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Queenbee
2
+ class APIError < QueenbeeError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Queenbee
2
+ class AuthenticationError < QueenbeeError
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module Queenbee
2
+ class InvalidRequestError < QueenbeeError
3
+ attr_accessor :param
4
+
5
+ def initialize(message, param, http_status=nil, http_body=nil, json_body=nil)
6
+ super(message, http_status, http_body, json_body)
7
+ @param = param
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module Queenbee
2
+ class QueenbeeError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_status
5
+ attr_reader :http_body
6
+ attr_reader :json_body
7
+
8
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
+ @message = message
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ @json_body = json_body
13
+ end
14
+
15
+ def to_s
16
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
17
+ "#{status_string}#{@message}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ module Queenbee
2
+ class Order < APIResource
3
+ include Queenbee::APIOperations::Create
4
+ include Queenbee::APIOperations::Update
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Queenbee
2
+ class QueenbeeObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Queenbee
2
+ VERSION = "0.0.2"
3
+ end
data/lib/queenbee.rb ADDED
@@ -0,0 +1,143 @@
1
+ # Queenbee Ruby bindings
2
+ require "cgi"
3
+ require "set"
4
+ require "openssl"
5
+ require "json"
6
+ require "net/http"
7
+ require "uri"
8
+
9
+ # Version
10
+ require "queenbee/version"
11
+
12
+ # API operations
13
+ require "queenbee/api_operations/create"
14
+ require "queenbee/api_operations/update"
15
+
16
+ # Resources
17
+ require "queenbee/queenbee_object"
18
+ require "queenbee/api_resource"
19
+ require "queenbee/order"
20
+
21
+ # Errors
22
+ require "queenbee/errors/queenbee_error"
23
+ require "queenbee/errors/api_error"
24
+ require "queenbee/errors/api_connection_error"
25
+ require "queenbee/errors/invalid_request_error"
26
+ require "queenbee/errors/authentication_error"
27
+
28
+ module Queenbee
29
+ @api_base = "https://queenbee-yafoy.herokuapp.com/api"
30
+
31
+ class << self
32
+ attr_accessor :token, :api_base, :verify_ssl_certs, :api_version
33
+ end
34
+
35
+ def self.api_url(url="")
36
+ @api_base + url
37
+ end
38
+
39
+ def self.request(method, url, token, params={}, headers={})
40
+ unless token ||= @token
41
+ raise AuthenticationError.new("No token provided")
42
+ end
43
+
44
+ url = api_url(url)
45
+
46
+ begin
47
+ uri = URI(url)
48
+ request = Net::HTTP::Post.new(uri) if method == :post
49
+ request = Net::HTTP::Put.new(uri) if method == :put
50
+ request["User-Agent"] = "Queenbee gem"
51
+ request["Authorization"] = "Token token=\"#{token}\""
52
+ request["Content-Type"] = "application/json"
53
+ request.body = params.to_json
54
+
55
+ http = Net::HTTP.new(uri.hostname, uri.port)
56
+
57
+ # see http://www.rubyinside.com/how-to-cure-nethttps-risky-default-https-behavior-4010.html
58
+ # for info about ssl verification
59
+
60
+ http.use_ssl = true if uri.scheme == "https"
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if uri.scheme == "https"
62
+
63
+ response = http.start {|h|
64
+ h.request(request)
65
+ }
66
+
67
+ # since http.request doesn't throw such exceptions, check them by status codes
68
+ handle_api_error(response.code, response.body)
69
+
70
+ rescue SocketError => e
71
+ handle_connection_error(e)
72
+ rescue NoMethodError => e
73
+ handle_connection_error(e)
74
+ rescue OpenSSL::SSL::SSLError => e
75
+ handle_connection_error(e)
76
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
77
+ handle_connection_error(e)
78
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
79
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
80
+ handle_connection_error(e)
81
+ end
82
+
83
+ [response, token]
84
+ end
85
+
86
+ def self.retrieve(id, opts={})
87
+ instance = self.new(id, opts)
88
+ instance
89
+ end
90
+
91
+ def self.handle_connection_error(e)
92
+ case e
93
+ when SocketError
94
+ message = "Unexpected error when trying to connect to Queenbee."
95
+
96
+ when NoMethodError
97
+ message = "Unexpected HTTP response code"
98
+
99
+ else
100
+ message = "Unexpected error communicating with Queenbee."
101
+ end
102
+
103
+ raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
104
+ end
105
+
106
+ def self.handle_api_error(rcode, rbody)
107
+ begin
108
+ error_obj = JSON.parse(rbody)
109
+ rescue JSON::ParserError
110
+ raise general_api_error(rcode, rbody)
111
+ end
112
+
113
+ case rcode
114
+ when 400, 404, 422
115
+ raise invalid_request_error error, rcode, rbody, error_obj
116
+ when 401
117
+ raise authentication_error error, rcode, rbody, error_obj
118
+ when 500
119
+ raise api_error error, rcode, rbody, error_obj
120
+ else
121
+ # raise api_error error, rcode, rbody, error_obj
122
+ end
123
+
124
+ end
125
+
126
+ def self.invalid_request_error(error, rcode, rbody, error_obj)
127
+ InvalidRequestError.new(error[:message], error[:param], rcode,
128
+ rbody, error_obj)
129
+ end
130
+
131
+ def self.authentication_error(error, rcode, rbody, error_obj)
132
+ AuthenticationError.new(error[:message], rcode, rbody, error_obj)
133
+ end
134
+
135
+ def self.api_error(error, rcode, rbody, error_obj)
136
+ APIError.new(error[:message], rcode, rbody, error_obj)
137
+ end
138
+
139
+ def self.general_api_error(rcode, rbody)
140
+ APIError.new("Invalid response object from API: #{rbody.inspect} " +
141
+ "(HTTP response code was #{rcode})", rcode, rbody)
142
+ end
143
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path("../../test_helper", __FILE__)
2
+
3
+ module Queenbee
4
+ class OrderTest < Test::Unit::TestCase
5
+ should "create should return status 201" do
6
+ response = Queenbee::Order.create(
7
+ date: "2014-07-01 14:50:28",
8
+ currency: "CAD", city: "Paris",
9
+ country: "Canada", client_email: "d@email.com",
10
+ uid: SecureRandom.hex(4))
11
+ assert_equal "201", response.code
12
+ end
13
+
14
+ should "raise Queenbee::AuthenticationError if not token provided" do
15
+ Queenbee.token = nil
16
+ assert_raises(Queenbee::AuthenticationError) {Queenbee::Order.create}
17
+ end
18
+
19
+ should "raise Queenbee::InvalidRequestError if not enough parameters" do
20
+ begin
21
+ rescue JSON::ParserError
22
+ assert_raises(Queenbee::InvalidRequestError) { Queenbee::Order.create }
23
+ end
24
+ end
25
+
26
+ should "Update should return 200" do
27
+ uid = SecureRandom.hex(4)
28
+ response1 = Queenbee::Order.create(
29
+ date: "2014-07-01 14:50:28",
30
+ currency: "CAD", city: "Paris",
31
+ country: "Canada", client_email: "d@email.com",
32
+ uid: uid)
33
+ response = Queenbee::Order.save(
34
+ date: "2014-07-01 14:50:28",
35
+ currency: "CAD", city: "Paris",
36
+ country: "Canada", client_email: "kk@email.com",
37
+ uid: uid)
38
+ assert_equal "200", response.code
39
+ end
40
+
41
+ should "Update should return 404 if UID missing" do
42
+ response1 = Queenbee::Order.create(
43
+ date: "2014-07-01 14:50:28",
44
+ currency: "CAD", city: "Paris",
45
+ country: "Canada", client_email: "d@email.com",
46
+ uid: SecureRandom.hex(4))
47
+ response = Queenbee::Order.save(
48
+ date: "2014-07-01 14:50:28",
49
+ currency: "CAD", city: "Paris",
50
+ country: "Canada", client_email: "kk@email.com",
51
+ uid: "")
52
+ assert_equal "404", response.code
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,14 @@
1
+ require 'queenbee'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ class Test::Unit::TestCase
6
+ setup do
7
+ Queenbee.api_base = 'http://localhost:3024/api'
8
+ Queenbee.token = '111'
9
+ end
10
+
11
+ teardown do
12
+ Queenbee.token = nil
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: queenbee
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Olivier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-08 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.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.8.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: shoulda
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.4.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.4.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: E-commerce analytics platform
84
+ email:
85
+ - olivier@yafoy.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - lib/queenbee.rb
92
+ - lib/queenbee/api_operations/create.rb
93
+ - lib/queenbee/api_operations/update.rb
94
+ - lib/queenbee/api_resource.rb
95
+ - lib/queenbee/errors/api_connection_error.rb
96
+ - lib/queenbee/errors/api_error.rb
97
+ - lib/queenbee/errors/authentication_error.rb
98
+ - lib/queenbee/errors/invalid_request_error.rb
99
+ - lib/queenbee/errors/queenbee_error.rb
100
+ - lib/queenbee/order.rb
101
+ - lib/queenbee/queenbee_object.rb
102
+ - lib/queenbee/version.rb
103
+ - test/queenbee/order_test.rb
104
+ - test/test_helper.rb
105
+ homepage: https://github.com/olimart/queenbee-ruby
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.4.8
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Gem to send e-commerce orders to the Queenbee central app.
129
+ test_files:
130
+ - test/queenbee/order_test.rb
131
+ - test/test_helper.rb