mad_cart 0.0.4 → 0.0.5
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 +13 -5
- data/README.md +11 -0
- data/lib/mad_cart/store/base.rb +4 -1
- data/lib/mad_cart/store/big_commerce.rb +4 -8
- data/lib/mad_cart/store/etsy.rb +4 -5
- data/lib/mad_cart/store/spree.rb +123 -0
- data/lib/mad_cart/version.rb +1 -1
- data/lib/mad_cart.rb +1 -0
- data/spec/fixtures/vcr_cassettes/spree.yml +988 -0
- data/spec/fixtures/vcr_cassettes/spree_invalid_key.yml +53 -0
- data/spec/fixtures/vcr_cassettes/spree_no_records.yml +110 -0
- data/spec/lib/store/spree_spec.rb +112 -0
- metadata +33 -24
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MzJkMmY4NjNhZmMyZTVhZDQzNmFjMmUyOGUzYWFiN2NmODE0MDBmYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YmNmMTgyYWRmNjUyNmM2YmFmYTk1NjBkZDE3MDE1Y2Q0MjY2NDQ3Zg==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NTkyY2NkMzU2NDM5MWYwYWExOTYyYzdhZjNmYzJkNGVmMzM0YjEyNTQxN2Y5
|
10
|
+
NmU2NThjYWIwYjY2ZTU4MzIxYzZlZTQxMWRmMmVlMmNiZjg0MmY2ZmY5NjQz
|
11
|
+
YTU3MDQyZDUxNDk2YmFhNThhNDRlYzc2YjdiY2UxZmNkMWRjOWM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDlkOTlhZTg5MWEwYTcyYmYyYTczNDZlNmFhYjBmMmE0NDY4YjRhNTI0MjJl
|
14
|
+
ZGIwNzVhNDczZjgwOTA0MTIzYzlkNjY0NjdlNWIwMmNjZjgyM2NmNTY4Zjky
|
15
|
+
NDRjN2E2YTEwNzE0MjYwNTRhZmUwZDUwNDdkMjJjNTFhMGExYTk=
|
data/README.md
CHANGED
@@ -7,6 +7,7 @@ A flexible DSL allows easy CRM and store integration.
|
|
7
7
|
Currently supports the following stores:
|
8
8
|
**-Etsy**
|
9
9
|
**-Bigcommerce**
|
10
|
+
**-Spree**
|
10
11
|
|
11
12
|
## Installation
|
12
13
|
|
@@ -106,6 +107,16 @@ store = MadCart::Store::Etsy.new
|
|
106
107
|
store.products.each{|p| MyProduct.create!(p.attributes) }
|
107
108
|
```
|
108
109
|
|
110
|
+
### Exceptions
|
111
|
+
|
112
|
+
MadCart throws several types of exceptions:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
MadCart::Store::ServerError #=> when Store's API returns server error response (status code: 500).
|
116
|
+
MadCart::Store::InvalidCredentials #=> when Store's API returns unauthorized response (status code: 401).
|
117
|
+
MadCart::Store::InvalidStore #=> when there is a problem with connection to Store's API.
|
118
|
+
```
|
119
|
+
|
109
120
|
## Contributing
|
110
121
|
|
111
122
|
See the [Contributor's Guide](https://github.com/madmimi/mad_cart/wiki/Contributor's-Guide) for info on the store integration API.
|
data/lib/mad_cart/store/base.rb
CHANGED
@@ -9,7 +9,10 @@ module MadCart
|
|
9
9
|
"in your initialize method should you require it."
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
|
+
InvalidStore = Class.new(StandardError)
|
14
|
+
ServerError = Class.new(StandardError)
|
15
|
+
InvalidCredentials = Class.new(StandardError)
|
13
16
|
|
14
17
|
module Base
|
15
18
|
def self.included(base)
|
@@ -1,10 +1,6 @@
|
|
1
1
|
module MadCart
|
2
2
|
module Store
|
3
3
|
class BigCommerce
|
4
|
-
class InvalidStore < StandardError; end;
|
5
|
-
class ServerError < StandardError; end;
|
6
|
-
class InvalidCredentials < StandardError; end;
|
7
|
-
|
8
4
|
include MadCart::Store::Base
|
9
5
|
|
10
6
|
create_connection_with :create_connection, :requires => [:api_key, :store_url, :username]
|
@@ -16,7 +12,7 @@ module MadCart
|
|
16
12
|
connection.get('time.json')
|
17
13
|
end
|
18
14
|
return true
|
19
|
-
|
15
|
+
|
20
16
|
rescue InvalidCredentials => e
|
21
17
|
return false
|
22
18
|
end
|
@@ -30,11 +26,11 @@ module MadCart
|
|
30
26
|
def make_customer_request(params={:min_id => 1})
|
31
27
|
parse_response { connection.get('customers.json', params) }
|
32
28
|
end
|
33
|
-
|
29
|
+
|
34
30
|
def get_products(options={})
|
35
31
|
product_hashes = connection.get('products.json', options).try(:body)
|
36
32
|
return [] unless product_hashes
|
37
|
-
|
33
|
+
|
38
34
|
threads, images = [], []
|
39
35
|
product_hashes.each do |product|
|
40
36
|
threads << Thread.new do
|
@@ -44,7 +40,7 @@ module MadCart
|
|
44
40
|
end
|
45
41
|
end
|
46
42
|
end
|
47
|
-
threads.each { |t| t.join }
|
43
|
+
threads.each { |t| t.join }
|
48
44
|
|
49
45
|
product_hashes.map do |p|
|
50
46
|
|
data/lib/mad_cart/store/etsy.rb
CHANGED
@@ -10,7 +10,7 @@ module MadCart
|
|
10
10
|
create_connection_with :create_connection, :requires => [:store_name, :api_key]
|
11
11
|
fetch :products, :with => :get_products
|
12
12
|
format :products, :with => :format_products
|
13
|
-
|
13
|
+
|
14
14
|
def valid?
|
15
15
|
self.connection ? true : false
|
16
16
|
end
|
@@ -39,19 +39,18 @@ module MadCart
|
|
39
39
|
store = ::Etsy::Shop.find(args[:store_name])
|
40
40
|
if store.is_a? Array
|
41
41
|
return store.first
|
42
|
-
else
|
42
|
+
else
|
43
43
|
raise InvalidStore if store.nil?
|
44
44
|
return store
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def product_options(options)
|
49
49
|
prod_options = options.clone
|
50
50
|
prod_options[:page] ||= 1
|
51
|
-
|
51
|
+
|
52
52
|
return prod_options
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module MadCart
|
2
|
+
module Store
|
3
|
+
class Spree
|
4
|
+
include MadCart::Store::Base
|
5
|
+
|
6
|
+
ORDERS_PER_PAGE = 50
|
7
|
+
|
8
|
+
create_connection_with :create_connection, :requires => [:api_key, :store_url]
|
9
|
+
fetch :customers, :with => :get_customer_hashes
|
10
|
+
fetch :products, :with => :get_products
|
11
|
+
|
12
|
+
def valid?
|
13
|
+
check_for_errors do
|
14
|
+
connection.get('orders.json')
|
15
|
+
end
|
16
|
+
return true
|
17
|
+
rescue InvalidCredentials => e
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
|
21
|
+
def products_count
|
22
|
+
(parse_response { connection.get('products.json') })["count"]
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def make_order_request(params={})
|
28
|
+
params = params.deep_merge({ :page => 1, :per_page => ORDERS_PER_PAGE })
|
29
|
+
parse_response { connection.get('orders.json', params) }["orders"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_products(options={})
|
33
|
+
product_hashes = connection.get('products.json', options).try{ |c| c.body["products"] }
|
34
|
+
return [] unless product_hashes
|
35
|
+
|
36
|
+
product_hashes.map do |product|
|
37
|
+
if product["master"]["images"]
|
38
|
+
image = product["master"]["images"].first
|
39
|
+
product = product.merge({
|
40
|
+
:url => connection.build_url("/products/#{ product["slug"] }").to_s,
|
41
|
+
:image_square_url => connection.build_url(image["product_url"]).to_s,
|
42
|
+
:image_url => connection.build_url(image["large_url"]).to_s
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
product
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_customer_hashes
|
51
|
+
result = []
|
52
|
+
|
53
|
+
loop(:make_order_request) do |c|
|
54
|
+
result << {
|
55
|
+
order_number: c["number"],
|
56
|
+
user_email: c["email"]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
result.reverse.select{ |r| r[:user_email].present? }.uniq{ |r| r[:user_email] }.map do |r|
|
61
|
+
c = parse_response { connection.get("orders/#{ r[:order_number] }.json") }
|
62
|
+
if c['email']
|
63
|
+
{
|
64
|
+
first_name: c['bill_address'].try(:[], 'firstname'),
|
65
|
+
last_name: c['bill_address'].try(:[], 'lastname'),
|
66
|
+
email: c['email'],
|
67
|
+
id: c['email']
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end.compact
|
71
|
+
end
|
72
|
+
|
73
|
+
def loop(source, &block)
|
74
|
+
page = 1
|
75
|
+
items = send(source, { :page => page })
|
76
|
+
|
77
|
+
while true
|
78
|
+
items.each &block
|
79
|
+
break if items.count < ORDERS_PER_PAGE
|
80
|
+
items = send(source, { :page => page += 1 })
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_response(&block)
|
86
|
+
response = check_for_errors &block
|
87
|
+
return [] if empty_body?(response)
|
88
|
+
return response.body
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_for_errors(&block)
|
92
|
+
response = yield
|
93
|
+
|
94
|
+
case response.status
|
95
|
+
when 401
|
96
|
+
raise InvalidCredentials
|
97
|
+
when 500
|
98
|
+
raise ServerError
|
99
|
+
end
|
100
|
+
|
101
|
+
response
|
102
|
+
rescue Faraday::Error::ConnectionFailed => e
|
103
|
+
raise InvalidStore
|
104
|
+
end
|
105
|
+
|
106
|
+
def api_url_for(store_domain)
|
107
|
+
"http://#{store_domain}/api/"
|
108
|
+
end
|
109
|
+
|
110
|
+
def empty_body?(response)
|
111
|
+
true if response.status == 204 || response.body.nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_connection(args={})
|
115
|
+
Faraday.new(:url => api_url_for(args[:store_url])) do |connection|
|
116
|
+
connection.response :json
|
117
|
+
connection.adapter Faraday.default_adapter
|
118
|
+
connection.headers['X-Spree-Token'] = args[:api_key]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/lib/mad_cart/version.rb
CHANGED
data/lib/mad_cart.rb
CHANGED