bestbuy_api 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek.yml +3 -0
- data/.rubocop.yml +3 -1
- data/README.md +2 -0
- data/lib/bestbuy_api.rb +0 -2
- data/lib/bestbuy_api/category.rb +5 -7
- data/lib/bestbuy_api/criteria.rb +21 -15
- data/lib/bestbuy_api/model.rb +14 -1
- data/lib/bestbuy_api/params.rb +53 -0
- data/lib/bestbuy_api/product.rb +18 -17
- data/lib/bestbuy_api/request.rb +9 -66
- data/lib/bestbuy_api/response.rb +22 -0
- data/lib/bestbuy_api/store.rb +12 -11
- data/lib/bestbuy_api/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30fe2e8e4bea5f47e2b7914ab5503254caad2b44196d2f78a1ce80a141cadbaa
|
4
|
+
data.tar.gz: 1748654ec2820ffec00ad63ecb5a9e4c4cfbd4831d0c662b61a1b526e8e288cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a03f206f578e31ebf60120de11a6753aafdc78f884dd0f17dca2caaa11857ed3a125f6e68e2d098bbaf49f1a085cb8f470b3ab547c91be08f0344866b12d9c35
|
7
|
+
data.tar.gz: cb3fd58846fb529926735e7259808b12e6305f0a1f5127bbef81d91deda0fa312b1e581322b89999d82a6de674d6b43b5e913227f2256a702ef80359d21a8778
|
data/.reek.yml
ADDED
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
data/lib/bestbuy_api.rb
CHANGED
@@ -3,8 +3,6 @@ require 'bestbuy_api/product'
|
|
3
3
|
require 'bestbuy_api/store'
|
4
4
|
require 'bestbuy_api/category'
|
5
5
|
|
6
|
-
# Handles BestBuy api queries. Documentation is located at
|
7
|
-
# https://bestbuyapis.github.io/api-documentation.
|
8
6
|
module BestbuyApi
|
9
7
|
class << self
|
10
8
|
attr_accessor :api_key
|
data/lib/bestbuy_api/category.rb
CHANGED
@@ -4,13 +4,11 @@ module BestbuyApi
|
|
4
4
|
# Defines the attributes for the categories api. Documentation is
|
5
5
|
# located at https://bestbuyapis.github.io/api-documentation/#categories-api.
|
6
6
|
class Category < Model
|
7
|
-
|
7
|
+
path 'categories'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
subcategory_name: { kw: 'subCategories.name' }
|
14
|
-
}.freeze
|
9
|
+
attribute :id, search: true
|
10
|
+
attribute :name, search: true
|
11
|
+
attribute :subcategory_id, field: 'subCategories.id'
|
12
|
+
attribute :subcategory_name, field: 'subCategories.name'
|
15
13
|
end
|
16
14
|
end
|
data/lib/bestbuy_api/criteria.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
require_relative 'params'
|
2
|
+
require_relative 'request'
|
1
3
|
require 'forwardable'
|
2
4
|
|
3
5
|
module BestbuyApi
|
4
|
-
# Collect the parameters and validates the attributes
|
5
6
|
class Criteria
|
6
7
|
extend Forwardable
|
7
|
-
def_delegators :
|
8
|
+
def_delegators :response, :items, :pagination, :url
|
8
9
|
|
9
10
|
def initialize(klass)
|
10
11
|
@klass = klass
|
@@ -15,18 +16,14 @@ module BestbuyApi
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def select(args)
|
18
|
-
|
19
|
-
attributes = @klass::ATTRIBUTES.select { |_k, v| v.key?(:read) ? v[:read] : true }
|
20
|
-
args.each { |k, _v| assert_keys(attributes.keys, k) }
|
19
|
+
assert_keys(args, @klass.attributes[:read])
|
21
20
|
|
22
21
|
criteria[:attributes] = args
|
23
22
|
self
|
24
23
|
end
|
25
24
|
|
26
25
|
def where(args)
|
27
|
-
|
28
|
-
attributes = @klass::ATTRIBUTES.select { |_k, v| v.key?(:search) && v[:search] }
|
29
|
-
args.each { |k, _v| assert_keys(attributes.keys, k) }
|
26
|
+
assert_keys(args, @klass.attributes[:search])
|
30
27
|
|
31
28
|
criteria[:conditions].merge!(args)
|
32
29
|
self
|
@@ -42,17 +39,26 @@ module BestbuyApi
|
|
42
39
|
self
|
43
40
|
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@request ||= BestbuyApi::Request.new(@klass::PATH, @klass::ATTRIBUTES, criteria)
|
42
|
+
def response
|
43
|
+
params = Params.new(criteria, @klass.attributes)
|
44
|
+
request.find(params.structure)
|
49
45
|
end
|
50
46
|
|
51
|
-
|
52
|
-
return true if valid_keys.include?(key)
|
47
|
+
private
|
53
48
|
|
54
|
-
|
49
|
+
def assert_keys(args, attributes)
|
50
|
+
valid_keys = attributes.keys
|
51
|
+
args.each do |key, _v|
|
52
|
+
unless valid_keys.include?(key)
|
53
|
+
raise MissingAttributeError, "Unknown attribute: #{key.inspect}. Valid attributes are: " \
|
55
54
|
"#{valid_keys.map(&:inspect).join(', ')}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def request
|
60
|
+
api_key = BestbuyApi.config.api_key
|
61
|
+
@request ||= Request.new(api_key, @klass.attributes[:path])
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
data/lib/bestbuy_api/model.rb
CHANGED
@@ -1,8 +1,21 @@
|
|
1
1
|
require_relative 'criteria'
|
2
2
|
|
3
3
|
module BestbuyApi
|
4
|
-
# Chains method calls to build up queries
|
5
4
|
class Model
|
5
|
+
def self.attributes
|
6
|
+
@attributes ||= { path: nil, read: {}, search: {} }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.path(path = nil)
|
10
|
+
attributes[:path] = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.attribute(id, columns = { search: false, read: true })
|
14
|
+
row = { id => columns }
|
15
|
+
attributes[:read].merge!(row) unless columns[:read] == false
|
16
|
+
attributes[:search].merge!(row) unless columns[:search] == false
|
17
|
+
end
|
18
|
+
|
6
19
|
def self.select(*args)
|
7
20
|
Criteria.new(self).select(args.uniq)
|
8
21
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module BestbuyApi
|
2
|
+
class Params
|
3
|
+
def initialize(criteria, attributes)
|
4
|
+
@criteria = criteria
|
5
|
+
@attributes = attributes
|
6
|
+
end
|
7
|
+
|
8
|
+
def structure
|
9
|
+
{ slug: build_filters, query: build_response_options }
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def build_filters
|
15
|
+
collection = collect_search
|
16
|
+
collection.empty? ? '' : query_string(collection)
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_response_options
|
20
|
+
query = @criteria.slice(:limit, :page)
|
21
|
+
query[:show] = collect_read
|
22
|
+
query
|
23
|
+
end
|
24
|
+
|
25
|
+
def collect_read
|
26
|
+
Array[@criteria[:attributes].map do |key|
|
27
|
+
elements = @attributes[:read]
|
28
|
+
if elements.key?(key)
|
29
|
+
attribute = elements[key]
|
30
|
+
attribute.key?(:field) ? attribute[:field] : key
|
31
|
+
end
|
32
|
+
end].join(',')
|
33
|
+
end
|
34
|
+
|
35
|
+
def collect_search
|
36
|
+
@criteria[:conditions].map do |key, value|
|
37
|
+
elements = @attributes[:search]
|
38
|
+
if elements.key?(key)
|
39
|
+
attribute = elements[key]
|
40
|
+
attribute.key?(:field) ? { attribute[:field] => value } : { key => value }
|
41
|
+
end
|
42
|
+
end.reduce({}, :merge)
|
43
|
+
end
|
44
|
+
|
45
|
+
def query_string(props)
|
46
|
+
search = props.delete('search')
|
47
|
+
uri = URI.encode_www_form(props)
|
48
|
+
search_query = "(search=#{search})" if search
|
49
|
+
uri = format("#{search_query}%<and>s", and: "&#{uri}") if search_query && uri
|
50
|
+
"(#{uri})"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/bestbuy_api/product.rb
CHANGED
@@ -4,23 +4,24 @@ module BestbuyApi
|
|
4
4
|
# Defines the attributes for the products api. Documentation is
|
5
5
|
# located at https://bestbuyapis.github.io/api-documentation/#products-api.
|
6
6
|
class Product < Model
|
7
|
-
|
7
|
+
path 'products'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
attribute :keyword, field: 'search', search: true, read: false
|
10
|
+
attribute :sku, search: true
|
11
|
+
attribute :category_id, field: 'categoryPath.id', search: true
|
12
|
+
attribute :category_name, field: 'categoryPath.name', search: true
|
13
|
+
attribute :condition, search: true
|
14
|
+
attribute :customer_rating, field: 'customerReviewAverage', search: true
|
15
|
+
attribute :manufacturer, search: true
|
16
|
+
attribute :regular_price, field: 'regularPrice'
|
17
|
+
attribute :sale_price, field: 'salePrice'
|
18
|
+
attribute :shipping_cost, field: 'shippingCost'
|
19
|
+
attribute :reviews_count, field: 'customerReviewCount'
|
20
|
+
attribute :discount, field: 'percentSavings'
|
21
|
+
attribute :free_shipping, field: 'freeShipping'
|
22
|
+
attribute :url
|
23
|
+
attribute :name
|
24
|
+
attribute :description
|
25
|
+
attribute :image
|
25
26
|
end
|
26
27
|
end
|
data/lib/bestbuy_api/request.rb
CHANGED
@@ -1,81 +1,24 @@
|
|
1
1
|
require 'httparty'
|
2
|
+
require_relative 'response'
|
2
3
|
|
3
4
|
module BestbuyApi
|
4
|
-
# Wrap HTTParty gem to query the api
|
5
5
|
class Request
|
6
6
|
include HTTParty
|
7
7
|
base_uri 'https://api.bestbuy.com/v1'
|
8
|
-
PAGE_VARS = %w[totalPages total currentPage].freeze
|
9
8
|
|
10
|
-
def initialize(
|
11
|
-
|
12
|
-
api_key = BestbuyApi.config.api_key
|
13
|
-
raise MissingApiKeyError, 'API Key is not defined' if api_key.nil?
|
9
|
+
def initialize(api_key, path)
|
10
|
+
raise MissingApiKeyError, 'API Key is not defined' if api_key.empty?
|
14
11
|
|
15
12
|
@path = path
|
16
|
-
@
|
17
|
-
@criteria = criteria
|
18
|
-
@query = { apiKey: api_key, format: 'json' }
|
13
|
+
@options = { apiKey: api_key, format: 'json' }
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def pagination
|
26
|
-
response.select { |k| PAGE_VARS.include?(k) }
|
27
|
-
end
|
28
|
-
|
29
|
-
def url
|
30
|
-
response.request.last_uri.to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def response
|
36
|
-
@response ||= find
|
37
|
-
end
|
38
|
-
|
39
|
-
def find
|
40
|
-
response = self.class.get("/#{@path}#{slug}", query: params)
|
41
|
-
raise RequestError, "#{response.code} Request Error" if response.code != 200
|
42
|
-
|
43
|
-
response
|
44
|
-
end
|
45
|
-
|
46
|
-
# Collect attributes that are readable and substitute using kw or key
|
47
|
-
def slug
|
48
|
-
attributes = @attributes.select { |_k, v| v.key?(:search) && v[:search] }
|
49
|
-
opts = @criteria[:conditions].map do |k, v|
|
50
|
-
attributes[k].key?(:kw) ? { attributes[k][:kw] => v } : { k => v }
|
51
|
-
end
|
52
|
-
opts = opts.reduce({}, :merge)
|
53
|
-
|
54
|
-
encode_slug(opts)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Collect attributes that are searchable and substitute using kw or key
|
58
|
-
def params
|
59
|
-
attributes = @attributes.select { |_k, v| v.key?(:read) ? v[:read] : true }
|
60
|
-
opts = Array[@criteria[:attributes].map do |k|
|
61
|
-
attributes[k].key?(:kw) ? attributes[k][:kw] : k
|
62
|
-
end].join(',')
|
63
|
-
|
64
|
-
join_fields(opts)
|
65
|
-
end
|
66
|
-
|
67
|
-
def encode_slug(opts)
|
68
|
-
search = opts.delete('search') if opts.key?('search')
|
69
|
-
slug = URI.encode_www_form(opts)
|
70
|
-
slug = format("(search=#{search})%<and>s", and: ("&#{slug}" unless slug.empty?)) if search
|
71
|
-
return "(#{slug})" unless slug.empty?
|
72
|
-
end
|
16
|
+
def find(params)
|
17
|
+
result = self.class.get("/#{@path}#{params[:slug]}", query: @options.merge(params[:query]))
|
18
|
+
code = result.code
|
19
|
+
raise RequestError, "#{code} Request Error: #{result.request.last_uri}" if code != 200
|
73
20
|
|
74
|
-
|
75
|
-
params = @criteria.slice(:limit, :page)
|
76
|
-
params[:show] = opts unless opts.empty?
|
77
|
-
@query.merge!(params) unless params.empty?
|
78
|
-
@query
|
21
|
+
Response.new(result, @path)
|
79
22
|
end
|
80
23
|
end
|
81
24
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BestbuyApi
|
2
|
+
class Response
|
3
|
+
PAGE_VARS = %w[totalPages total currentPage].freeze
|
4
|
+
|
5
|
+
def initialize(result, path)
|
6
|
+
@result = result
|
7
|
+
@path = path
|
8
|
+
end
|
9
|
+
|
10
|
+
def items
|
11
|
+
@result[@path] if @result.key?(@path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def pagination
|
15
|
+
@result.select { |key| PAGE_VARS.include?(key) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def url
|
19
|
+
@result.request.last_uri.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/bestbuy_api/store.rb
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
require_relative 'model'
|
2
|
-
require_relative 'request'
|
3
2
|
|
4
3
|
module BestbuyApi
|
5
4
|
# Defines the attributes for the stores api. Documentation is
|
6
5
|
# located at https://bestbuyapis.github.io/api-documentation/#stores-api.
|
7
6
|
class Store < Model
|
8
|
-
|
7
|
+
path 'stores'
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
attribute :id, field: 'storeId', search: true
|
10
|
+
attribute :city, search: true
|
11
|
+
attribute :state, field: 'region', search: true
|
12
|
+
attribute :postal_code, field: 'fullPostalCode', search: true
|
13
|
+
attribute :store_type, field: 'storeType'
|
14
|
+
attribute :name
|
15
|
+
attribute :address
|
16
|
+
attribute :address2
|
17
|
+
attribute :country
|
18
|
+
attribute :hours
|
19
|
+
attribute :phone
|
19
20
|
end
|
20
21
|
end
|
data/lib/bestbuy_api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bestbuy_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael John Bayucot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -128,6 +128,7 @@ extensions: []
|
|
128
128
|
extra_rdoc_files: []
|
129
129
|
files:
|
130
130
|
- ".gitignore"
|
131
|
+
- ".reek.yml"
|
131
132
|
- ".rspec"
|
132
133
|
- ".rubocop.yml"
|
133
134
|
- ".travis.yml"
|
@@ -141,8 +142,10 @@ files:
|
|
141
142
|
- lib/bestbuy_api/criteria.rb
|
142
143
|
- lib/bestbuy_api/exceptions.rb
|
143
144
|
- lib/bestbuy_api/model.rb
|
145
|
+
- lib/bestbuy_api/params.rb
|
144
146
|
- lib/bestbuy_api/product.rb
|
145
147
|
- lib/bestbuy_api/request.rb
|
148
|
+
- lib/bestbuy_api/response.rb
|
146
149
|
- lib/bestbuy_api/store.rb
|
147
150
|
- lib/bestbuy_api/version.rb
|
148
151
|
homepage: https://github.com/mbayucot/bestbuy-api
|