promoqui-api-sdk 1.9.2 → 2.0.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
- data/lib/pqsdk.rb +2 -1
- data/lib/pqsdk/brand.rb +15 -23
- data/lib/pqsdk/city.rb +20 -43
- data/lib/pqsdk/leaflet.rb +27 -69
- data/lib/pqsdk/offer.rb +23 -43
- data/lib/pqsdk/remote_object.rb +89 -0
- data/lib/pqsdk/rest_layer.rb +24 -62
- data/lib/pqsdk/settings.rb +12 -24
- data/lib/pqsdk/store.rb +27 -81
- data/lib/pqsdk/token.rb +22 -11
- data/lib/pqsdk/version.rb +1 -1
- metadata +180 -6
- data/lib/pqsdk/offer_batch.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa4a1825e51bf701bea71dbdfd2e8a4372100726
|
4
|
+
data.tar.gz: 08c5aed494db52632b4727cfd55410f0cd44aab8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4335949bd0b01bf61c345fe174c2f116bd7eeede95c39087c04d5a846556d2da71a1505dbc5fbd9f049c153b9e66da1c3dc5b8cfd8c5f12c238bb9ba27a4de79
|
7
|
+
data.tar.gz: 7c4a315a71bc0207ae6e61141042575db939b3b041e20b6ce62e284154f4395f73811be891c843569ec810d4ca0b083ae03e5b8943856dd18fa0ea05e1c5755d
|
data/lib/pqsdk.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'json'
|
3
|
+
require 'faraday'
|
3
4
|
require 'time'
|
4
5
|
require 'pqsdk/brand'
|
5
6
|
require 'pqsdk/city'
|
6
7
|
require 'pqsdk/leaflet'
|
7
8
|
require 'pqsdk/offer'
|
8
|
-
require 'pqsdk/
|
9
|
+
require 'pqsdk/remote_object'
|
9
10
|
require 'pqsdk/rest_layer'
|
10
11
|
require 'pqsdk/settings'
|
11
12
|
require 'pqsdk/store'
|
data/lib/pqsdk/brand.rb
CHANGED
@@ -1,38 +1,30 @@
|
|
1
|
+
require 'pqsdk/remote_object'
|
2
|
+
|
1
3
|
module PQSDK
|
2
|
-
class
|
4
|
+
# The Brand class provides an interface for crawlers to the v1/brands api
|
5
|
+
# endpoint.
|
6
|
+
class Brand < RemoteObject
|
7
|
+
@endpoint = 'v1/brands'
|
8
|
+
|
3
9
|
attr_accessor :id, :name, :slug
|
4
10
|
|
11
|
+
def attributes
|
12
|
+
{ 'name' => nil, 'slug' => nil }
|
13
|
+
end
|
14
|
+
|
5
15
|
def self.list
|
6
|
-
|
7
|
-
if res[0] == 200
|
8
|
-
res[1].map{|brand| Brand.from_json(brand)}
|
9
|
-
elsif res[0] == 404
|
10
|
-
nil
|
11
|
-
else
|
12
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
13
|
-
end
|
16
|
+
all # aliased until all crawlers use .all
|
14
17
|
end
|
15
18
|
|
16
19
|
def self.find(name)
|
17
|
-
res = RestLayer.get(
|
20
|
+
res = RestLayer.get("#{@endpoint}/search", q: name)
|
18
21
|
if res[0] == 200
|
19
|
-
|
22
|
+
from_hash res[1]
|
20
23
|
elsif res[0] == 404
|
21
24
|
nil
|
22
25
|
else
|
23
|
-
raise
|
26
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
24
27
|
end
|
25
28
|
end
|
26
|
-
|
27
|
-
private
|
28
|
-
def self.from_json(json)
|
29
|
-
result = Brand.new
|
30
|
-
|
31
|
-
json.each do |key, val|
|
32
|
-
result.send("#{key}=", val)
|
33
|
-
end
|
34
|
-
|
35
|
-
result
|
36
|
-
end
|
37
29
|
end
|
38
30
|
end
|
data/lib/pqsdk/city.rb
CHANGED
@@ -1,65 +1,42 @@
|
|
1
|
+
require 'pqsdk/remote_object'
|
2
|
+
|
1
3
|
module PQSDK
|
2
|
-
class
|
4
|
+
# The City class provides an interface for crawlers to the v1/cities api
|
5
|
+
# endpoint.
|
6
|
+
class City < RemoteObject
|
7
|
+
@endpoint = 'v1/cities'
|
8
|
+
|
3
9
|
attr_accessor :id, :name, :inhabitants, :latitude, :longitude, :state, :country
|
4
10
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
nil
|
11
|
-
|
12
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
13
|
-
end
|
11
|
+
validates :name, presence: true
|
12
|
+
|
13
|
+
def attributes
|
14
|
+
{
|
15
|
+
'name' => nil, 'inhabitants' => nil, 'latitude' => nil,
|
16
|
+
'longitude' => nil, 'state' => nil, 'country' => nil
|
17
|
+
}
|
14
18
|
end
|
15
19
|
|
16
|
-
def self.
|
17
|
-
res = RestLayer.get(
|
20
|
+
def self.find(name)
|
21
|
+
res = RestLayer.get(@endpoint, q: name)
|
18
22
|
if res[0] == 200
|
19
|
-
|
20
|
-
res[1].each do |city|
|
21
|
-
cities << City.from_json(city)
|
22
|
-
end
|
23
|
-
return cities
|
23
|
+
from_hash res[1]
|
24
24
|
elsif res[0] == 404
|
25
25
|
nil
|
26
26
|
else
|
27
|
-
raise
|
27
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.find_or_create(name)
|
32
|
-
city =
|
32
|
+
city = find(name)
|
33
33
|
return city if city
|
34
34
|
|
35
35
|
city = City.new
|
36
36
|
city.name = name
|
37
|
-
city.
|
37
|
+
city.create!
|
38
38
|
|
39
39
|
city
|
40
40
|
end
|
41
|
-
|
42
|
-
def save
|
43
|
-
res = RestLayer.post('v1/cities', { name: name }, { 'Authorization' => "Bearer #{Token.access_token}" })
|
44
|
-
|
45
|
-
if res[0] != 201
|
46
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
47
|
-
else
|
48
|
-
self.id = res[1]['id']
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
def self.from_json(json)
|
54
|
-
result = City.new
|
55
|
-
|
56
|
-
json.each do |key, val|
|
57
|
-
unless key == 'inhabitants'
|
58
|
-
result.send("#{key}=", val)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
result
|
63
|
-
end
|
64
41
|
end
|
65
42
|
end
|
data/lib/pqsdk/leaflet.rb
CHANGED
@@ -1,85 +1,43 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'pqsdk/remote_object'
|
3
|
+
|
1
4
|
module PQSDK
|
2
|
-
class
|
3
|
-
|
5
|
+
# The Leaflet class provides an interface for crawlers to the v1/leaflets api
|
6
|
+
# endpoint.
|
7
|
+
class Leaflet < RemoteObject
|
8
|
+
@endpoint = 'v1/leaflets'
|
4
9
|
|
5
|
-
|
6
|
-
|
7
|
-
send("#{key}=", val)
|
8
|
-
end
|
10
|
+
attr_accessor :id, :name, :url, :start_date, :end_date, :pdf_data,
|
11
|
+
:image_urls, :store_ids
|
9
12
|
|
10
|
-
|
11
|
-
self.store_ids ||= []
|
12
|
-
end
|
13
|
+
validates :name, :url, presence: true
|
13
14
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
nil
|
20
|
-
else
|
21
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}")
|
22
|
-
end
|
15
|
+
def attributes
|
16
|
+
{
|
17
|
+
'name' => nil, 'url' => nil, 'start_date' => nil, 'end_date' => nil,
|
18
|
+
'pdf_data' => nil, 'image_urls' => nil, 'store_ids' => nil
|
19
|
+
}
|
23
20
|
end
|
24
21
|
|
25
|
-
def
|
26
|
-
|
27
|
-
endpoint = "v1/leaflet"
|
28
|
-
expected_status = 201
|
29
|
-
fields = {}
|
30
|
-
fields['id'] = id unless id.is_a? Integer and !id.nil?
|
22
|
+
def self.find(url)
|
23
|
+
res = RestLayer.get(@endpoint, url: url, retailer_id: Token.retailer_id)
|
31
24
|
|
32
|
-
|
25
|
+
return nil if res[0] == 404
|
26
|
+
raise "Unexpected HTTP status code #{res[0]}" unless res[0] == 200
|
33
27
|
|
34
|
-
|
35
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
36
|
-
end
|
28
|
+
from_hash res[1]
|
37
29
|
end
|
38
30
|
|
39
|
-
def
|
40
|
-
|
41
|
-
endpoint = "v1/leaflets"
|
42
|
-
expected_status = 201
|
43
|
-
|
44
|
-
fields = {}
|
45
|
-
fields['name'] = name unless name.nil?
|
46
|
-
fields['url'] = url unless url.nil?
|
47
|
-
fields['start_date'] = start_date unless start_date.nil?
|
48
|
-
fields['end_date'] = end_date unless end_date.nil?
|
49
|
-
fields['pdf_data'] = pdf_data unless pdf_data.nil?
|
50
|
-
fields['image_urls'] = image_urls.try(:to_json) || []
|
51
|
-
fields['store_ids'] = store_ids.try(:to_json) || []
|
52
|
-
|
53
|
-
res = RestLayer.send(method, endpoint, fields, {'Authorization' => "Bearer #{Token.access_token}"})
|
54
|
-
|
55
|
-
if res[0] != expected_status
|
56
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
57
|
-
else
|
58
|
-
if method == :post
|
59
|
-
self.id = res[1]['id']
|
60
|
-
end
|
61
|
-
end
|
31
|
+
def image_urls
|
32
|
+
@image_urls ||= []
|
62
33
|
end
|
63
34
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
json.each do |key, val|
|
69
|
-
if result.respond_to?("#{key}=") and key != 'retailer' and key != 'url' and key != 'pages'
|
70
|
-
result.send("#{key}=", val)
|
71
|
-
elsif key=="url" and result.respond_to?(:origin=)
|
72
|
-
result.origin=val
|
73
|
-
elsif key=="retailer" and result.respond_to?(:retailer_id=)
|
74
|
-
result.retailer_id=val['id']
|
75
|
-
elsif key=="pages" and result.respond_to?(:page)
|
76
|
-
val.each do |page|
|
77
|
-
result.page_ids << page['id']
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
35
|
+
def store_ids
|
36
|
+
@store_ids ||= []
|
37
|
+
end
|
81
38
|
|
82
|
-
|
39
|
+
def pdf_data=(data)
|
40
|
+
@pdf_data = Base64.encode64(data)
|
83
41
|
end
|
84
42
|
end
|
85
43
|
end
|
data/lib/pqsdk/offer.rb
CHANGED
@@ -1,52 +1,32 @@
|
|
1
|
-
|
2
|
-
class Offer
|
3
|
-
attr_accessor :title, :description, :price, :original_price, :discount, :start_date, :end_date, :brand, :image, :store_ids, :national, :partner_link,
|
4
|
-
:btn_other_offers_visible, :btn_partner_link_text, :btn_partner_link_visible, :btn_print_visible, :btn_stores_visible, :btn_online_offers_visible
|
5
|
-
|
6
|
-
def initialize(params = {})
|
7
|
-
params.each do |key, val|
|
8
|
-
send("#{key}=", val)
|
9
|
-
end
|
10
|
-
|
11
|
-
store_ids ||= []
|
12
|
-
end
|
13
|
-
|
14
|
-
def save
|
15
|
-
method = :post
|
16
|
-
endpoint = "v1/offers"
|
1
|
+
require 'pqsdk/remote_object'
|
17
2
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
fields[:offer]['store_ids'] = store_ids.presence || []
|
3
|
+
module PQSDK
|
4
|
+
# The Offer class provides an interface for crawlers to the v1/offers api
|
5
|
+
# endpoint.
|
6
|
+
class Offer < RemoteObject
|
7
|
+
@endpoint = 'v1/offers'
|
25
8
|
|
26
|
-
|
9
|
+
attr_accessor :id, :title, :description, :price, :original_price, :discount,
|
10
|
+
:start_date, :end_date, :brand, :image, :store_ids, :national,
|
11
|
+
:partner_link, :btn_other_offers_visible, :btn_partner_link_text,
|
12
|
+
:btn_partner_link_visible, :btn_print_visible, :btn_stores_visible,
|
13
|
+
:btn_online_offers_visible
|
27
14
|
|
28
|
-
|
29
|
-
# All right!
|
30
|
-
elsif res[0] == 400
|
31
|
-
raise Exception.new("Bad request! Error: #{res[1]['errors']}")
|
32
|
-
else
|
33
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
34
|
-
end
|
35
|
-
end
|
15
|
+
validates :title, :image, :store_ids, presence: true
|
36
16
|
|
37
|
-
def
|
17
|
+
def attributes
|
38
18
|
{
|
39
|
-
title
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end_date: end_date,
|
46
|
-
brand: brand,
|
47
|
-
image: image,
|
48
|
-
store_ids: store_ids
|
19
|
+
'title' => nil, 'description' => nil, 'price' => nil, 'original_price' => nil,
|
20
|
+
'discount' => nil, 'start_date' => nil, 'end_date' => nil, 'brand' => nil,
|
21
|
+
'image' => nil, 'store_ids' => nil, 'national' => nil, 'partner_link' => nil,
|
22
|
+
'btn_other_offers_visible' => nil, 'btn_partner_link_text' => nil,
|
23
|
+
'btn_partner_link_visible' => nil, 'btn_print_visible' => nil,
|
24
|
+
'btn_stores_visible' => nil, 'btn_online_offers_visible' => nil
|
49
25
|
}
|
50
26
|
end
|
27
|
+
|
28
|
+
def store_ids
|
29
|
+
@store_ids ||= []
|
30
|
+
end
|
51
31
|
end
|
52
32
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_model'
|
3
|
+
|
4
|
+
module PQSDK
|
5
|
+
# The RemoteObject class is an abstraction for common API utilities like .get
|
6
|
+
# and #save.
|
7
|
+
class RemoteObject
|
8
|
+
include ActiveModel::Model
|
9
|
+
include ActiveModel::Serializers::JSON
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_reader :endpoint
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
res = RestLayer.get(@endpoint)
|
17
|
+
if res[0] == 200
|
18
|
+
res[1].map { |entry| from_hash(entry) }
|
19
|
+
else
|
20
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get(id)
|
25
|
+
res = RestLayer.get("#{@endpoint}/#{id}")
|
26
|
+
if res[0] == 200
|
27
|
+
from_hash res[1]
|
28
|
+
elsif res[0] == 404
|
29
|
+
nil
|
30
|
+
else
|
31
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.from_hash(json)
|
36
|
+
result = new
|
37
|
+
json.each do |k, v|
|
38
|
+
result.send("#{k}=", v) if result.respond_to?("#{k}=")
|
39
|
+
end
|
40
|
+
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def save
|
45
|
+
if valid?
|
46
|
+
persisted? ? update! : create!
|
47
|
+
else
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def create
|
53
|
+
res = RestLayer.post(self.class.endpoint, serializable_hash, 'Authorization' => "Bearer #{Token.access_token}")
|
54
|
+
if [201, 202].include? res[0]
|
55
|
+
self.id = res[1]['id']
|
56
|
+
true
|
57
|
+
else
|
58
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
59
|
+
# false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def update
|
64
|
+
res = RestLayer.put("#{self.class.endpoint}/#{id}", serializable_hash, 'Authorization' => "Bearer #{Token.access_token}")
|
65
|
+
if res[0] == 200
|
66
|
+
true
|
67
|
+
else
|
68
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
69
|
+
# false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def save!
|
74
|
+
save || raise('Save failed')
|
75
|
+
end
|
76
|
+
|
77
|
+
def create!
|
78
|
+
create
|
79
|
+
end
|
80
|
+
|
81
|
+
def update!
|
82
|
+
update
|
83
|
+
end
|
84
|
+
|
85
|
+
def persisted?
|
86
|
+
!id.nil?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/pqsdk/rest_layer.rb
CHANGED
@@ -1,77 +1,39 @@
|
|
1
1
|
module PQSDK
|
2
|
+
# A small wrapper to the Faraday gem to make get/post/put requests to the API
|
3
|
+
# server.
|
2
4
|
class RestLayer
|
3
|
-
def self.get(endpoint, parameters, headers)
|
4
|
-
|
5
|
-
url.query = URI.encode_www_form(parameters)
|
6
|
-
req = Net::HTTP::Get.new(url.request_uri)
|
5
|
+
def self.get(endpoint, parameters = {}, headers = {})
|
6
|
+
res = connection.get endpoint, parameters, headers
|
7
7
|
|
8
|
-
|
9
|
-
req[name.to_s] = value
|
10
|
-
end
|
11
|
-
|
12
|
-
res = Net::HTTP.start(url.host, url.port) do |http|
|
13
|
-
http.request(req)
|
14
|
-
end
|
15
|
-
|
16
|
-
check_status(res.code.to_i, res.body)
|
17
|
-
|
18
|
-
[ res.code.to_i, JSON.parse(res.body), res.to_hash ]
|
8
|
+
check_result(res)
|
19
9
|
end
|
20
10
|
|
21
|
-
def self.post(endpoint, parameters, headers)
|
22
|
-
|
23
|
-
req = Net::HTTP::Post.new(url.request_uri)
|
11
|
+
def self.post(endpoint, parameters = {}, headers = {})
|
12
|
+
res = connection.post endpoint, parameters.to_json, headers.merge('Content-Type' => 'application/json')
|
24
13
|
|
25
|
-
|
26
|
-
req.body = parameters.to_json
|
27
|
-
else
|
28
|
-
req.set_form_data(parameters)
|
29
|
-
end
|
30
|
-
|
31
|
-
headers.each do |name, value|
|
32
|
-
req[name.to_s] = value
|
33
|
-
end
|
34
|
-
|
35
|
-
res = Net::HTTP.start(url.host, url.port) do |http|
|
36
|
-
http.request(req)
|
37
|
-
end
|
38
|
-
|
39
|
-
check_status(res.code.to_i, res.body)
|
40
|
-
if res.body and res.body.length > 1
|
41
|
-
[ res.code.to_i, JSON.parse(res.body), res.to_hash ]
|
42
|
-
else
|
43
|
-
[ res.code.to_i, {}, res.to_hash ]
|
44
|
-
end
|
14
|
+
check_result(res)
|
45
15
|
end
|
46
16
|
|
47
|
-
def self.put(endpoint, parameters, headers)
|
48
|
-
|
49
|
-
req = Net::HTTP::Put.new(url.request_uri)
|
17
|
+
def self.put(endpoint, parameters = {}, headers = {})
|
18
|
+
res = connection.put endpoint, parameters.to_json, headers.merge('Content-Type' => 'application/json')
|
50
19
|
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
req.set_form_data(parameters)
|
55
|
-
end
|
56
|
-
|
57
|
-
headers.each do |name, value|
|
58
|
-
req[name.to_s] = value
|
59
|
-
end
|
60
|
-
|
61
|
-
res = Net::HTTP.start(url.host, url.port) do |http|
|
62
|
-
http.request(req)
|
63
|
-
end
|
20
|
+
check_result(res)
|
21
|
+
end
|
64
22
|
|
65
|
-
|
66
|
-
|
23
|
+
def self.connection
|
24
|
+
Faraday.new(Settings.api_root)
|
67
25
|
end
|
68
26
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
27
|
+
def self.check_result(result)
|
28
|
+
status = result.status.to_i
|
29
|
+
headers = result.headers
|
30
|
+
raise "Internal Server Error: #{result.body}" if status >= 500
|
31
|
+
raise 'You are not authorized to perform that request' if status == 401
|
32
|
+
|
33
|
+
begin
|
34
|
+
[status, JSON.parse(result.body), headers]
|
35
|
+
rescue JSON::ParserError
|
36
|
+
[status, nil, headers]
|
75
37
|
end
|
76
38
|
end
|
77
39
|
end
|
data/lib/pqsdk/settings.rb
CHANGED
@@ -1,33 +1,21 @@
|
|
1
1
|
module PQSDK
|
2
|
+
# The Settings class contains the configuration for the library.
|
2
3
|
class Settings
|
3
|
-
|
4
|
+
class << self
|
5
|
+
attr_accessor :host, :app_secret, :schema
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
def schema
|
8
|
+
@schema ||= 'http'
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
def app_secret=(secret)
|
12
|
+
Token.reset!
|
13
|
+
@app_secret = secret
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
|
-
def self.
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.app_secret
|
18
|
-
@@app_secret
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.app_secret=(val)
|
22
|
-
@@app_secret = val
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.schema
|
26
|
-
@@schema
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.schema=(val)
|
30
|
-
@@schema = val
|
17
|
+
def self.api_root
|
18
|
+
"#{schema}://#{host}"
|
31
19
|
end
|
32
20
|
end
|
33
21
|
end
|
data/lib/pqsdk/store.rb
CHANGED
@@ -1,96 +1,42 @@
|
|
1
|
-
|
2
|
-
class Store
|
3
|
-
attr_accessor :id, :name, :city, :address, :zipcode, :latitude, :longitude, :phone, :city_id, :origin, :opening_hours, :opening_hours_text, :leaflet_ids
|
4
|
-
|
5
|
-
def initialize(params = {})
|
6
|
-
params.each do |key, val|
|
7
|
-
send("#{key}=", val)
|
8
|
-
end
|
1
|
+
require 'pqsdk/remote_object'
|
9
2
|
|
10
|
-
|
11
|
-
|
3
|
+
module PQSDK
|
4
|
+
# The Store class provides an interface for crawlers to the v1/stores api
|
5
|
+
# endpoint.
|
6
|
+
class Store < RemoteObject
|
7
|
+
@endpoint = 'v1/stores'
|
8
|
+
|
9
|
+
attr_accessor :id, :origin, :name, :address, :latitude, :longitude, :city,
|
10
|
+
:city_id, :zipcode, :phone, :opening_hours, :opening_hours_text
|
11
|
+
|
12
|
+
validates :origin, :name, :address, :latitude, :longitude, presence: true
|
13
|
+
validates :city_id, presence: true, if: proc { |s| s.city.nil? }
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
{
|
17
|
+
'origin' => nil, 'name' => nil, 'address' => nil, 'latitude' => nil,
|
18
|
+
'longitude' => nil, 'city' => nil, 'city_id' => nil, 'zipcode' => nil,
|
19
|
+
'phone' => nil, 'opening_hours' => nil, 'opening_hours_text' => nil
|
20
|
+
}
|
12
21
|
end
|
13
22
|
|
14
|
-
def
|
15
|
-
|
16
|
-
if res[0] == 200
|
17
|
-
Store.from_json res[1]
|
18
|
-
elsif res[0] == 404
|
19
|
-
nil
|
20
|
-
else
|
21
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
22
|
-
end
|
23
|
+
def opening_hours
|
24
|
+
@opening_hours ||= []
|
23
25
|
end
|
24
26
|
|
25
|
-
def self.
|
26
|
-
res = RestLayer.get(
|
27
|
+
def self.find(address, zipcode, retailer = nil)
|
28
|
+
res = RestLayer.get(@endpoint, { address: address, zipcode: zipcode, retailer: retailer }, 'Authorization' => "Bearer #{Token.access_token}")
|
27
29
|
if res[0] == 200
|
28
|
-
|
30
|
+
from_hash res[1]
|
29
31
|
elsif res[0] == 404
|
30
32
|
nil
|
31
33
|
else
|
32
|
-
raise
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def save
|
37
|
-
if self.id != nil
|
38
|
-
method = :put
|
39
|
-
url = "v1/stores/#{self.id}"
|
40
|
-
expected_status = 200
|
41
|
-
else
|
42
|
-
method = :post
|
43
|
-
url = "v1/stores"
|
44
|
-
expected_status = 201
|
45
|
-
end
|
46
|
-
|
47
|
-
if city.nil? and city_id.nil?
|
48
|
-
raise "city or city_id must be set"
|
49
|
-
end
|
50
|
-
|
51
|
-
fields = {}
|
52
|
-
if method != :put
|
53
|
-
[ :name, :address, :zipcode, :latitude, :longitude, :origin ].each do |field|
|
54
|
-
raise "Missing required #{field} field" if send(field).to_s == ''
|
55
|
-
fields[field.to_s] = send(field)
|
56
|
-
end
|
57
|
-
|
58
|
-
fields['city'] = city if city
|
59
|
-
fields['city_id'] = city_id if city_id
|
60
|
-
fields['phone'] = phone if phone
|
61
|
-
end
|
62
|
-
|
63
|
-
fields['opening_hours'] = opening_hours if opening_hours.try(:any?)
|
64
|
-
fields['opening_hours_text'] = opening_hours_text if opening_hours_text.present?
|
65
|
-
|
66
|
-
res = RestLayer.send(method, url, fields, { 'Authorization' => "Bearer #{Token.access_token}", 'Content-Type' => 'application/json' })
|
67
|
-
|
68
|
-
if res[0] != expected_status
|
69
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}, #{res[1]}")
|
70
|
-
else
|
71
|
-
if method == :post
|
72
|
-
self.id = res[1]['id']
|
73
|
-
end
|
34
|
+
raise "Unexpected HTTP status code #{res[0]}, #{res[1]}"
|
74
35
|
end
|
75
36
|
end
|
76
37
|
|
77
|
-
|
78
|
-
|
79
|
-
result = Store.new
|
80
|
-
|
81
|
-
json.each do |key, val|
|
82
|
-
if respond_to?("#{key}=")
|
83
|
-
if key != 'country' && key != 'city'
|
84
|
-
result.send("#{key}=", val)
|
85
|
-
end
|
86
|
-
else
|
87
|
-
if key != 'country' && key != 'city' && key != 'retailer_id'
|
88
|
-
result.send("#{key}=",val)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
result
|
38
|
+
def self.from_hash(json)
|
39
|
+
super(json.stringify_keys.except('city'))
|
94
40
|
end
|
95
41
|
end
|
96
42
|
end
|
data/lib/pqsdk/token.rb
CHANGED
@@ -1,30 +1,41 @@
|
|
1
1
|
module PQSDK
|
2
|
+
# The Token holds the random access token generated on every crawler run,
|
3
|
+
# and it is used to authenticate all following requests.
|
2
4
|
class Token
|
3
|
-
|
4
|
-
|
5
|
+
@access_token = nil
|
6
|
+
@expiration = nil
|
7
|
+
@retailer_id = nil
|
5
8
|
|
6
9
|
def self.get
|
7
|
-
res = RestLayer.get('v1/token', {},
|
10
|
+
res = RestLayer.get('v1/token', {}, 'Authentication' => "Key #{Settings.app_secret}")
|
8
11
|
|
9
12
|
if res[0] == 200
|
10
|
-
|
11
|
-
|
13
|
+
@access_token = res[1]['token']
|
14
|
+
@expiration = Time.parse(res[1]['expired_at'])
|
15
|
+
@retailer_id = res[1]['retailer_id']
|
12
16
|
end
|
13
17
|
|
14
|
-
|
18
|
+
@access_token
|
15
19
|
end
|
16
20
|
|
17
21
|
def self.access_token
|
18
|
-
if
|
19
|
-
|
22
|
+
if @access_token.nil? || @expiration <= Time.now
|
23
|
+
get
|
20
24
|
else
|
21
|
-
|
25
|
+
@access_token
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
29
|
+
def self.retailer_id
|
30
|
+
get unless @retailer_id
|
31
|
+
|
32
|
+
@retailer_id
|
33
|
+
end
|
34
|
+
|
25
35
|
def self.reset!
|
26
|
-
|
27
|
-
|
36
|
+
@access_token = nil
|
37
|
+
@expiration = nil
|
38
|
+
@retailer_id = nil
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
data/lib/pqsdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,203 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: promoqui-api-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francesco Boffa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activemodel
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.1'
|
17
48
|
- - ">="
|
18
49
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
50
|
+
version: 4.1.0
|
20
51
|
type: :runtime
|
21
52
|
prerelease: false
|
22
53
|
version_requirements: !ruby/object:Gem::Requirement
|
23
54
|
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '4.1'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 4.1.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: activesupport
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '4.1'
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 4.1.0
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '4.1'
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 4.1.0
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rspec
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '3.4'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 3.4.0
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '3.4'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 3.4.0
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: rake
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '10.5'
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 10.5.0
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '10.5'
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 10.5.0
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: guard
|
123
|
+
requirement: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - "~>"
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '2.13'
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.13.0
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '2.13'
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 2.13.0
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: guard-rspec
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - "~>"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '4.6'
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 4.6.0
|
151
|
+
type: :development
|
152
|
+
prerelease: false
|
153
|
+
version_requirements: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '4.6'
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 4.6.0
|
161
|
+
- !ruby/object:Gem::Dependency
|
162
|
+
name: webmock
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '1.22'
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: 1.22.6
|
171
|
+
type: :development
|
172
|
+
prerelease: false
|
173
|
+
version_requirements: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - "~>"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '1.22'
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 1.22.6
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: shoulda-matchers
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '3.1'
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: 3.1.0
|
191
|
+
type: :development
|
192
|
+
prerelease: false
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - "~>"
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '3.1'
|
24
198
|
- - ">="
|
25
199
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
200
|
+
version: 3.1.0
|
27
201
|
description: This gem helps Crawler Writers to interact with the PromoQui REST API
|
28
202
|
email: f.boffa@promoqui.it
|
29
203
|
executables: []
|
@@ -35,13 +209,13 @@ files:
|
|
35
209
|
- lib/pqsdk/city.rb
|
36
210
|
- lib/pqsdk/leaflet.rb
|
37
211
|
- lib/pqsdk/offer.rb
|
38
|
-
- lib/pqsdk/
|
212
|
+
- lib/pqsdk/remote_object.rb
|
39
213
|
- lib/pqsdk/rest_layer.rb
|
40
214
|
- lib/pqsdk/settings.rb
|
41
215
|
- lib/pqsdk/store.rb
|
42
216
|
- lib/pqsdk/token.rb
|
43
217
|
- lib/pqsdk/version.rb
|
44
|
-
homepage:
|
218
|
+
homepage: https://github.com/promoqui/promoqui-api-ruby
|
45
219
|
licenses:
|
46
220
|
- MIT
|
47
221
|
metadata: {}
|
data/lib/pqsdk/offer_batch.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
module PQSDK
|
2
|
-
class OfferBatch
|
3
|
-
attr_accessor :offers
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@offers = []
|
7
|
-
end
|
8
|
-
|
9
|
-
def <<(offer)
|
10
|
-
@offers << offer
|
11
|
-
end
|
12
|
-
|
13
|
-
def save
|
14
|
-
request = []
|
15
|
-
method = :post
|
16
|
-
endpoint = "v1/offers"
|
17
|
-
|
18
|
-
@offers.each do |offer|
|
19
|
-
request << offer.to_hash
|
20
|
-
end
|
21
|
-
|
22
|
-
res = RestLayer.send(method, endpoint, request, {'Authorization' => "Bearer #{Token.access_token}", 'Content-Type' => 'application/json'})
|
23
|
-
|
24
|
-
if res[0] == 200
|
25
|
-
# All right!
|
26
|
-
elsif res[0] == 400
|
27
|
-
raise Exception.new("Bad request! Error: #{res[1]['errors']}")
|
28
|
-
else
|
29
|
-
raise Exception.new("Unexpected HTTP status code #{res[0]}")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|