auchandirect-scrAPI 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +1 -1
- data/README.md +54 -2
- data/auchandirect-scrAPI.gemspec +1 -1
- data/lib/auchandirect/scrAPI/base_cart.rb +5 -3
- data/lib/auchandirect/scrAPI/cart.rb +25 -21
- data/lib/auchandirect/scrAPI/dummy_cart.rb +22 -8
- data/lib/auchandirect/scrAPI/invalid_account_error.rb +1 -0
- data/lib/auchandirect/scrAPI/items.rb +14 -0
- data/lib/auchandirect/scrAPI/version.rb +1 -1
- data/spec/lib/auchandirect/scrAPI/cart_shared_examples.rb +51 -33
- metadata +21 -21
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc35cb08d3c9467fe51c720cd6d154286627d478
|
4
|
+
data.tar.gz: f13f7199fa84e7f6093d4fac3d97772108ac52f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cec302e8fbaf7f1ad245f94cf0f8a483c2f712328e6ba512a49438cfc88be7b154e20f5d00b38dcc9b5b82e146ad264c3fd7dbf8cdc55eada15a3c8ead3e9c8b
|
7
|
+
data.tar.gz: c924a934ffda7b7b4d3040fcb123c9f5fa590e473b974c072870db8a7d8d904eb166dd50e915baa04314cab4531dd1edff533b2c90eaf1b046e31e4b6495c605
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Auchandirect::ScrAPI
|
2
2
|
|
3
|
-
A ruby gem providing, through scrapping, an API to the french www.auchandirect.
|
3
|
+
A ruby gem providing, through scrapping, an API to the french www.auchandirect.fr online grocery
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -16,9 +16,61 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install auchandirect-scrAPI
|
18
18
|
|
19
|
+
## Status
|
20
|
+
|
21
|
+
This library should be production ready.
|
22
|
+
* It is automaticaly tested through Travis[https://travis-ci.org/philou/auchandirect-scrAPI]
|
23
|
+
* It should be daily tested through TravisCron[http://traviscron.pythonanywhere.com/] to quickly detect modification at auchandirect.fr
|
24
|
+
|
19
25
|
## Usage
|
20
26
|
|
21
|
-
|
27
|
+
This API has 2 main features :
|
28
|
+
* walking the store to collect all the different items in the different subsections
|
29
|
+
* Connecting with a user account in order to fill his cart
|
30
|
+
|
31
|
+
It is not currently possible to pay and validate an order through this API. In order to do so, a user must :
|
32
|
+
1. first disconnect from the API
|
33
|
+
2. only then reconnect with his account through a browser, and order his pre-filled cart
|
34
|
+
|
35
|
+
### Sample usage
|
36
|
+
|
37
|
+
Suppose you'd want to fill your cart with all the pizzas available on the store, this is how you would do it :
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
cart = Auchandirect::ScrAPI::Cart.login('buyer@mail.org', 'password')
|
41
|
+
|
42
|
+
begin
|
43
|
+
|
44
|
+
Storexplore::Api.browse('http://www.auchandirect.fr').categories.each do |cat|
|
45
|
+
cat.categories.each do |s_cat|
|
46
|
+
s_cat.categories.each do |ss_cat|
|
47
|
+
ss_cat.items.each do |item|
|
48
|
+
|
49
|
+
if item.attributes[:name] =~ /pizza/i
|
50
|
+
|
51
|
+
cart.add_to_cart(item.attributes[:remote_id])
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
ensure
|
60
|
+
|
61
|
+
ensure cart.logout
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
```
|
66
|
+
|
67
|
+
### Client side usage
|
68
|
+
|
69
|
+
In order to make it possible for a web browser to automaticaly connect to auchandirect.fr (for example in an iframe, to pay for a cart that was previously filled with this gem on the server), the cart The Auchandirect::ScrAPI::Cart classes exposes enough information to generate the html that makes this possible. You can have a look at spec/lib/auchandirect/scrAPI/client_cart_shared_examples.rb for more details. /This whole thing remains tricky and subject to failures though./
|
70
|
+
|
71
|
+
### Testing
|
72
|
+
|
73
|
+
In order to run quicker and offline tests for the rest of your app, you can use Auchandirect::ScrAPI::DummyCart in place of a real cart. This cart is compatible with Storexplore's dummy store generators [https://github.com/philou/storexplore].
|
22
74
|
|
23
75
|
## Contributing
|
24
76
|
|
data/auchandirect-scrAPI.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Auchandirect::ScrAPI::VERSION
|
9
9
|
spec.authors = ["Philou"]
|
10
10
|
spec.email = ["philippe.bourgau@gmail.com"]
|
11
|
-
spec.description = %q{Through scrapping, an API to the french www.auchandirect.
|
11
|
+
spec.description = %q{Through scrapping, an API to the french www.auchandirect.fr online grocery}
|
12
12
|
spec.summary = %q{auchandirect.com grocery API}
|
13
13
|
spec.homepage = "https://github.com/philou/auchandirect-scrAPI"
|
14
14
|
spec.license = "LGPL v3"
|
@@ -22,19 +22,21 @@
|
|
22
22
|
module Auchandirect
|
23
23
|
module ScrAPI
|
24
24
|
|
25
|
-
#
|
25
|
+
# Base class for objects providing an api like access to third party online stores
|
26
26
|
class BaseCart
|
27
27
|
|
28
|
+
# :login is a synonym for :new
|
28
29
|
class << self
|
29
30
|
alias :login :new
|
30
31
|
end
|
31
32
|
|
32
|
-
#
|
33
|
-
# def self.url
|
33
|
+
# Main url of the store
|
34
34
|
def url
|
35
35
|
self.class.url
|
36
36
|
end
|
37
37
|
|
38
|
+
# def self.url
|
39
|
+
|
38
40
|
# url at which a client browser can login
|
39
41
|
# def self.login_url
|
40
42
|
|
@@ -24,10 +24,10 @@ require 'json'
|
|
24
24
|
module Auchandirect
|
25
25
|
module ScrAPI
|
26
26
|
|
27
|
-
#
|
27
|
+
# Cart API for AuchanDirect store
|
28
28
|
class Cart < BaseCart
|
29
29
|
|
30
|
-
#
|
30
|
+
# Main url of the store
|
31
31
|
def self.url
|
32
32
|
"http://www.auchandirect.fr"
|
33
33
|
end
|
@@ -39,11 +39,11 @@ module Auchandirect
|
|
39
39
|
raise InvalidAccountError unless logged_in?
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
42
|
+
# Url at which a client browser can login
|
43
43
|
def self.login_url
|
44
44
|
url + login_path
|
45
45
|
end
|
46
|
-
#
|
46
|
+
# Parameters for a client side login
|
47
47
|
def self.login_parameters(login, password)
|
48
48
|
default_params = post_parameters.map {|name, value| {'name' => name, 'value' => value, 'type' => 'hidden'}}
|
49
49
|
user_params = [{'name' => FORMDATA_PARAMETER, 'value' => login_form_data(Mechanize.new), 'type' => 'hidden'},
|
@@ -53,42 +53,57 @@ module Auchandirect
|
|
53
53
|
default_params + user_params
|
54
54
|
end
|
55
55
|
|
56
|
-
#
|
56
|
+
# Client side 'login' parameter name
|
57
57
|
def self.login_parameter
|
58
58
|
LOGIN_PARAMETER
|
59
59
|
end
|
60
|
+
# Client side 'password' parameter name
|
60
61
|
def self.password_parameter
|
61
62
|
PASSWORD_PARAMETER
|
62
63
|
end
|
63
64
|
|
64
|
-
#
|
65
|
+
# Url at which a client browser can logout
|
65
66
|
def self.logout_url
|
66
67
|
url + logout_path
|
67
68
|
end
|
68
69
|
|
69
|
-
#
|
70
|
+
# Logs out from the store
|
70
71
|
def logout
|
71
72
|
get(self.class.logout_path)
|
72
73
|
end
|
73
74
|
|
74
|
-
#
|
75
|
+
# Total value of the remote cart
|
75
76
|
def cart_value
|
76
77
|
cart_page = get("/monpanier")
|
77
78
|
cart_page.search("span.prix-total").first.content.gsub(/€$/,"").to_f
|
78
79
|
end
|
79
80
|
|
80
|
-
#
|
81
|
+
# Empties the cart of the current user
|
81
82
|
def empty_the_cart
|
82
83
|
post("/boutiques.blockzones.popuphandler.cleanbasketpopup.cleanbasket")
|
83
84
|
end
|
84
85
|
|
85
|
-
#
|
86
|
+
# Adds items to the cart of the current user
|
86
87
|
def add_to_cart(quantity, item_remote_id)
|
87
88
|
quantity.times do
|
88
89
|
post("/boutiques.mozaique.thumbnailproduct.addproducttobasket/#{item_remote_id}")
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
93
|
+
# Missing methods can be forwarded to the class
|
94
|
+
def method_missing(method_sym, *arguments, &block)
|
95
|
+
if delegate_to_class?(method_sym)
|
96
|
+
self.class.send(method_sym, *arguments, &block)
|
97
|
+
else
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# It can respond to messages that the class can handle
|
103
|
+
def respond_to?(method_sym)
|
104
|
+
super or delegate_to_class?(method_sym)
|
105
|
+
end
|
106
|
+
|
92
107
|
private
|
93
108
|
|
94
109
|
def do_login(login,password)
|
@@ -150,17 +165,6 @@ module Auchandirect
|
|
150
165
|
{'t:ac' => "Accueil", 't:cp' => 'gabarit/generated'}
|
151
166
|
end
|
152
167
|
|
153
|
-
def method_missing(method_sym, *arguments, &block)
|
154
|
-
if delegate_to_class?(method_sym)
|
155
|
-
self.class.send(method_sym, *arguments, &block)
|
156
|
-
else
|
157
|
-
super
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def respond_to?(method_sym)
|
162
|
-
super or delegate_to_class?(method_sym)
|
163
|
-
end
|
164
168
|
def delegate_to_class?(method_sym)
|
165
169
|
self.class.respond_to?(method_sym)
|
166
170
|
end
|
@@ -22,15 +22,18 @@
|
|
22
22
|
module Auchandirect
|
23
23
|
module ScrAPI
|
24
24
|
|
25
|
-
#
|
25
|
+
# A mock for Auchandirect::ScrAPI::Cart
|
26
|
+
# It provides a call log as a way of testing
|
26
27
|
class DummyCart < BaseCart
|
27
28
|
|
28
29
|
def self.url
|
29
30
|
"http://www.#{Storexplore::Testing::DummyStoreConstants::NAME}.com"
|
30
31
|
end
|
32
|
+
# The valid login to log into this dummy store
|
31
33
|
def self.valid_email
|
32
34
|
"valid@mail.com"
|
33
35
|
end
|
36
|
+
# The valid password to log into this dummy store
|
34
37
|
def self.valid_password
|
35
38
|
"valid-password"
|
36
39
|
end
|
@@ -53,20 +56,25 @@ module Auchandirect
|
|
53
56
|
'password'
|
54
57
|
end
|
55
58
|
|
59
|
+
# Accessors to the login and passwords used to login
|
60
|
+
# And to the received messages log
|
56
61
|
attr_reader :login, :password, :log
|
57
62
|
|
63
|
+
# As the real store, the remote cart outlives the sessions
|
64
|
+
@@content = Hash.new(0)
|
65
|
+
|
58
66
|
def initialize(login = nil, password = nil)
|
59
67
|
@log = []
|
60
68
|
@login = ""
|
61
69
|
@password = ""
|
62
70
|
@unavailable_items = {}
|
63
|
-
@content = Hash.new(0)
|
64
71
|
|
65
72
|
if !login.nil? || !password.nil?
|
66
73
|
relog(login, password)
|
67
74
|
end
|
68
75
|
end
|
69
76
|
|
77
|
+
# Resets the session as if a new one was started
|
70
78
|
def relog(login, password)
|
71
79
|
if login != DummyCart.valid_email
|
72
80
|
raise InvalidAccountError.new
|
@@ -83,18 +91,18 @@ module Auchandirect
|
|
83
91
|
|
84
92
|
def empty_the_cart
|
85
93
|
@log.push(:empty_the_cart)
|
86
|
-
|
94
|
+
@@content.clear
|
87
95
|
end
|
88
96
|
|
89
97
|
def add_to_cart(quantity, item)
|
90
98
|
if available?(item)
|
91
99
|
@log.push(:add_to_cart)
|
92
|
-
|
100
|
+
@@content[item] += quantity
|
93
101
|
end
|
94
102
|
end
|
95
103
|
|
96
104
|
def cart_value
|
97
|
-
|
105
|
+
@@content.to_a.inject(0.0) do |amount,id_and_quantity|
|
98
106
|
item = id_and_quantity.first
|
99
107
|
quantity = id_and_quantity.last
|
100
108
|
|
@@ -104,21 +112,27 @@ module Auchandirect
|
|
104
112
|
end
|
105
113
|
end
|
106
114
|
|
115
|
+
# Collection of all the different items in the cart
|
107
116
|
def content
|
108
|
-
|
117
|
+
@@content.keys
|
109
118
|
end
|
110
119
|
|
120
|
+
# Is the cart empty ?
|
111
121
|
def empty?
|
112
|
-
|
122
|
+
@@content.empty?
|
113
123
|
end
|
114
124
|
|
125
|
+
# Does the cart contain the specified quantity of this item ?
|
115
126
|
def containing?(item, quantity)
|
116
|
-
|
127
|
+
@@content[item] == quantity
|
117
128
|
end
|
118
129
|
|
130
|
+
# Makes an item temporarily unavailable
|
119
131
|
def add_unavailable_item(item)
|
120
132
|
@unavailable_items[item] = true
|
121
133
|
end
|
134
|
+
|
135
|
+
# Is the given item available at this moment ?
|
122
136
|
def available?(item)
|
123
137
|
!@unavailable_items[item]
|
124
138
|
end
|
@@ -22,6 +22,20 @@
|
|
22
22
|
module Auchandirect
|
23
23
|
module ScrAPI
|
24
24
|
|
25
|
+
# Storexplore api definition to browse all the items available
|
26
|
+
# at auchandirect.com
|
27
|
+
# See[https://github.com/philou/storexplore/blob/master/README.md]
|
28
|
+
#
|
29
|
+
# The store has 3 depths of categories.
|
30
|
+
# The only attribute the categories have is their name
|
31
|
+
# The items are all child of the bottom categories, here are
|
32
|
+
# their attributes
|
33
|
+
# * brand
|
34
|
+
# * name
|
35
|
+
# * price
|
36
|
+
# * image (url of the link to the image)
|
37
|
+
# * remote_id (the id of this item in the auchandirect database)
|
38
|
+
|
25
39
|
module Items
|
26
40
|
NAMES_SEPARATOR = ', '
|
27
41
|
end
|
@@ -24,6 +24,7 @@ require 'spec_helper'
|
|
24
24
|
shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
25
25
|
|
26
26
|
before :all do
|
27
|
+
@store_cart_class = store_cart_class
|
27
28
|
@store_url = store_url
|
28
29
|
end
|
29
30
|
|
@@ -63,7 +64,7 @@ shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
|
63
64
|
attr_reader :sample_item_id, :another_item_id, :store_cart_api
|
64
65
|
|
65
66
|
before(:all) do
|
66
|
-
@
|
67
|
+
@session = new_session
|
67
68
|
|
68
69
|
sample_items = extract_sample_items
|
69
70
|
sample_item = sample_items.next
|
@@ -71,38 +72,38 @@ shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
|
71
72
|
@another_item_id = extract_another_item_id(sample_items, sample_item)
|
72
73
|
end
|
73
74
|
before(:each) do
|
74
|
-
@
|
75
|
+
@session.empty_the_cart
|
75
76
|
end
|
76
77
|
|
77
78
|
after(:all) do
|
78
|
-
@
|
79
|
+
@session.logout
|
79
80
|
end
|
80
81
|
|
81
82
|
# Some tests are redudant with what is item extractions, but the followings
|
82
83
|
# are clearer about what is expected from the cart
|
83
84
|
|
84
85
|
it "should set the cart value to 0 when emptying the cart" do
|
85
|
-
@
|
86
|
+
@session.add_to_cart(1, sample_item_id)
|
86
87
|
|
87
|
-
@
|
88
|
-
expect(@
|
88
|
+
@session.empty_the_cart
|
89
|
+
expect(@session.cart_value).to eq 0
|
89
90
|
end
|
90
91
|
|
91
92
|
it "should set the cart value to something greater than 0 when adding items to the cart" do
|
92
|
-
@
|
93
|
+
@session.empty_the_cart
|
93
94
|
|
94
|
-
@
|
95
|
-
expect(@
|
95
|
+
@session.add_to_cart(1, sample_item_id)
|
96
|
+
expect(@session.cart_value).to be > 0
|
96
97
|
end
|
97
98
|
|
98
99
|
it "should set the cart value to 2 times that of one item when adding 2 items" do
|
99
|
-
@
|
100
|
+
@session.empty_the_cart
|
100
101
|
|
101
|
-
@
|
102
|
-
item_price = @
|
102
|
+
@session.add_to_cart(1, sample_item_id)
|
103
|
+
item_price = @session.cart_value
|
103
104
|
|
104
|
-
@
|
105
|
-
expect(@
|
105
|
+
@session.add_to_cart(1, sample_item_id)
|
106
|
+
expect(@session.cart_value).to eq 2*item_price
|
106
107
|
end
|
107
108
|
|
108
109
|
it "should set different cart values with different items" do
|
@@ -112,24 +113,41 @@ shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
|
112
113
|
expect(sample_item_cart_value).not_to eq another_item_cart_value
|
113
114
|
end
|
114
115
|
|
115
|
-
it "should
|
116
|
-
@
|
116
|
+
it "should save the cart between sessions" do
|
117
|
+
@session.add_to_cart(1, sample_item_id)
|
118
|
+
@session.logout
|
117
119
|
|
118
|
-
|
119
|
-
begin
|
120
|
-
api2.empty_the_cart
|
121
|
-
ensure
|
122
|
-
api2.logout
|
123
|
-
end
|
120
|
+
@session = new_session
|
124
121
|
|
125
|
-
@
|
126
|
-
|
122
|
+
expect(@session.cart_value).not_to eq 0
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should save the cart between sessions, even while another session" do
|
126
|
+
background_session = @session
|
127
|
+
|
128
|
+
run_session do |session|
|
129
|
+
session.add_to_cart(1, sample_item_id)
|
130
|
+
end
|
127
131
|
|
128
|
-
|
132
|
+
run_session do |session|
|
133
|
+
expect(session.cart_value).not_to eq 0
|
134
|
+
end
|
129
135
|
end
|
130
136
|
|
131
137
|
private
|
132
138
|
|
139
|
+
def run_session
|
140
|
+
session = new_session
|
141
|
+
begin
|
142
|
+
yield session
|
143
|
+
ensure
|
144
|
+
session.logout
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def new_session
|
149
|
+
@store_cart_class.login(@store_cart_class.valid_email, @store_cart_class.valid_password)
|
150
|
+
end
|
133
151
|
def extract_another_item_id(sample_items, sample_item)
|
134
152
|
another_item = sample_item
|
135
153
|
while sample_item.attributes[:price] == another_item.attributes[:price]
|
@@ -158,13 +176,13 @@ shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
|
158
176
|
end
|
159
177
|
|
160
178
|
def item_available?(item_id)
|
161
|
-
@
|
162
|
-
@
|
163
|
-
item_price = @
|
179
|
+
@session.empty_the_cart
|
180
|
+
@session.add_to_cart(1, item_id)
|
181
|
+
item_price = @session.cart_value
|
164
182
|
return false if 0 == item_price
|
165
183
|
|
166
|
-
@
|
167
|
-
return @
|
184
|
+
@session.add_to_cart(1, item_id)
|
185
|
+
return @session.cart_value == item_price * 2
|
168
186
|
end
|
169
187
|
|
170
188
|
def nationaly_available_first(elements)
|
@@ -181,9 +199,9 @@ shared_examples_for "Any Cart" do |store_cart_class, store_url|
|
|
181
199
|
end
|
182
200
|
|
183
201
|
def cart_value_with_item(item_id)
|
184
|
-
@
|
185
|
-
@
|
186
|
-
@
|
202
|
+
@session.empty_the_cart
|
203
|
+
@session.add_to_cart(1, item_id)
|
204
|
+
@session.cart_value
|
187
205
|
end
|
188
206
|
end
|
189
207
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: auchandirect-scrAPI
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philou
|
@@ -31,102 +31,102 @@ cert_chain:
|
|
31
31
|
yLcl1cmm5ALtJ/+Bkkmp0i4amXeTDMvq9r8PBsVsQwxYOYJBP+Umxz3PX6HjFHrQ
|
32
32
|
XdkXx3oZ
|
33
33
|
-----END CERTIFICATE-----
|
34
|
-
date: 2014-03-
|
34
|
+
date: 2014-03-21 00:00:00.000000000 Z
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: storexplore
|
38
38
|
requirement: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- - ~>
|
40
|
+
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '0.2'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - ~>
|
47
|
+
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '0.2'
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: bundler
|
52
52
|
requirement: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- - ~>
|
54
|
+
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '1.3'
|
57
57
|
type: :development
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- - ~>
|
61
|
+
- - "~>"
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: '1.3'
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: rake
|
66
66
|
requirement: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- - ~>
|
68
|
+
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '10.1'
|
71
71
|
type: :development
|
72
72
|
prerelease: false
|
73
73
|
version_requirements: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
|
-
- - ~>
|
75
|
+
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '10.1'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: guard-rspec
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
|
-
- - ~>
|
82
|
+
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '4.0'
|
85
85
|
type: :development
|
86
86
|
prerelease: false
|
87
87
|
version_requirements: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
|
-
- - ~>
|
89
|
+
- - "~>"
|
90
90
|
- !ruby/object:Gem::Version
|
91
91
|
version: '4.0'
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
93
|
name: net-ping
|
94
94
|
requirement: !ruby/object:Gem::Requirement
|
95
95
|
requirements:
|
96
|
-
- - ~>
|
96
|
+
- - "~>"
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: '1.7'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
101
|
version_requirements: !ruby/object:Gem::Requirement
|
102
102
|
requirements:
|
103
|
-
- - ~>
|
103
|
+
- - "~>"
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: '1.7'
|
106
106
|
- !ruby/object:Gem::Dependency
|
107
107
|
name: spec_combos
|
108
108
|
requirement: !ruby/object:Gem::Requirement
|
109
109
|
requirements:
|
110
|
-
- - ~>
|
110
|
+
- - "~>"
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0.2'
|
113
113
|
type: :development
|
114
114
|
prerelease: false
|
115
115
|
version_requirements: !ruby/object:Gem::Requirement
|
116
116
|
requirements:
|
117
|
-
- - ~>
|
117
|
+
- - "~>"
|
118
118
|
- !ruby/object:Gem::Version
|
119
119
|
version: '0.2'
|
120
|
-
description: Through scrapping, an API to the french www.auchandirect.
|
120
|
+
description: Through scrapping, an API to the french www.auchandirect.fr online grocery
|
121
121
|
email:
|
122
122
|
- philippe.bourgau@gmail.com
|
123
123
|
executables: []
|
124
124
|
extensions: []
|
125
125
|
extra_rdoc_files: []
|
126
126
|
files:
|
127
|
-
- .gitignore
|
128
|
-
- .rspec
|
129
|
-
- .travis.yml
|
127
|
+
- ".gitignore"
|
128
|
+
- ".rspec"
|
129
|
+
- ".travis.yml"
|
130
130
|
- Gemfile
|
131
131
|
- Guardfile
|
132
132
|
- LICENSE
|
@@ -161,17 +161,17 @@ require_paths:
|
|
161
161
|
- lib
|
162
162
|
required_ruby_version: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- -
|
164
|
+
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
168
|
requirements:
|
169
|
-
- -
|
169
|
+
- - ">="
|
170
170
|
- !ruby/object:Gem::Version
|
171
171
|
version: '0'
|
172
172
|
requirements: []
|
173
173
|
rubyforge_project:
|
174
|
-
rubygems_version: 2.
|
174
|
+
rubygems_version: 2.2.2
|
175
175
|
signing_key:
|
176
176
|
specification_version: 4
|
177
177
|
summary: auchandirect.com grocery API
|
metadata.gz.sig
CHANGED
Binary file
|