best_buy_ruby 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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.reek.yml +127 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +74 -0
  6. data/.travis.yml +33 -0
  7. data/CHANGELOG.md +10 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/CONTRIBUTING.md +42 -0
  10. data/Gemfile +5 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +83 -0
  13. data/Rakefile +6 -0
  14. data/best_buy_ruby.gemspec +42 -0
  15. data/bin/console +15 -0
  16. data/bin/setup +8 -0
  17. data/docs/categories_api.md +25 -0
  18. data/docs/general_overview.md +67 -0
  19. data/docs/products_api.md +85 -0
  20. data/docs/stores_api.md +68 -0
  21. data/lib/best_buy.rb +34 -0
  22. data/lib/best_buy/base.rb +13 -0
  23. data/lib/best_buy/base/version.rb +7 -0
  24. data/lib/best_buy/base_api.rb +46 -0
  25. data/lib/best_buy/categories.rb +23 -0
  26. data/lib/best_buy/config.rb +17 -0
  27. data/lib/best_buy/helpers/api_helper.rb +13 -0
  28. data/lib/best_buy/helpers/conditions/category_condition.rb +19 -0
  29. data/lib/best_buy/helpers/conditions/max_price_condition.rb +19 -0
  30. data/lib/best_buy/helpers/conditions/min_price_condition.rb +19 -0
  31. data/lib/best_buy/helpers/conditions/new_condition.rb +19 -0
  32. data/lib/best_buy/helpers/conditions/pre_owned_condition.rb +19 -0
  33. data/lib/best_buy/helpers/conditions/refurbished_condition.rb +19 -0
  34. data/lib/best_buy/models/address.rb +23 -0
  35. data/lib/best_buy/models/base_category.rb +12 -0
  36. data/lib/best_buy/models/category.rb +20 -0
  37. data/lib/best_buy/models/collection_header.rb +20 -0
  38. data/lib/best_buy/models/collections_response.rb +19 -0
  39. data/lib/best_buy/models/image.rb +16 -0
  40. data/lib/best_buy/models/offer.rb +18 -0
  41. data/lib/best_buy/models/product.rb +39 -0
  42. data/lib/best_buy/models/shipping_level_of_service.rb +13 -0
  43. data/lib/best_buy/models/store.rb +26 -0
  44. data/lib/best_buy/products.rb +53 -0
  45. data/lib/best_buy/search_query_builder.rb +21 -0
  46. data/lib/best_buy/stores.rb +30 -0
  47. data/lib/generators/best_buy/config/config_generator.rb +13 -0
  48. data/lib/generators/best_buy/config/templates/config.rb +5 -0
  49. metadata +234 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class << self
5
+ def configure
6
+ yield config
7
+ end
8
+
9
+ def config
10
+ @config ||= Config.new
11
+ end
12
+ end
13
+
14
+ class Config
15
+ attr_accessor :api_key
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'best_buy'
4
+
5
+ module BestBuy
6
+ class APIHelper
7
+ def parse_response(response)
8
+ JSON.parse(response).deep_transform_keys do |key|
9
+ key.to_s.underscore.to_sym
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class CategoryCondition
6
+ def initialize(condition_hash)
7
+ @category_id = condition_hash[:category_id]
8
+ end
9
+
10
+ def valid?
11
+ @category_id.present?
12
+ end
13
+
14
+ def search_query
15
+ "categoryPath.id=#{@category_id}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class MaxPriceCondition
6
+ def initialize(condition_hash)
7
+ @max_price = condition_hash[:max_price]
8
+ end
9
+
10
+ def valid?
11
+ @max_price.present?
12
+ end
13
+
14
+ def search_query
15
+ "((regularPrice<=#{@max_price}&onSale=false)|(salePrice<=#{@max_price}&onSale=true))"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class MinPriceCondition
6
+ def initialize(condition_hash)
7
+ @min_price = condition_hash[:min_price]
8
+ end
9
+
10
+ def valid?
11
+ @min_price.present?
12
+ end
13
+
14
+ def search_query
15
+ "((regularPrice>=#{@min_price}&onSale=false)|(salePrice>=#{@min_price}&onSale=true))"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class NewCondition
6
+ def initialize(condition_hash)
7
+ @item_condition = condition_hash[:item_condition]&.downcase
8
+ end
9
+
10
+ def valid?
11
+ @item_condition.present? && @item_condition == 'new'
12
+ end
13
+
14
+ def search_query
15
+ '(condition=new|new=true)'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class PreOwnedCondition
6
+ def initialize(condition_hash)
7
+ @item_condition = condition_hash[:item_condition]&.downcase
8
+ end
9
+
10
+ def valid?
11
+ @item_condition.present? && @item_condition == 'pre-owned'
12
+ end
13
+
14
+ def search_query
15
+ '(condition=pre-owned|preowned=true)'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ module Conditions
5
+ class RefurbishedCondition
6
+ def initialize(condition_hash)
7
+ @item_condition = condition_hash[:item_condition]&.downcase
8
+ end
9
+
10
+ def valid?
11
+ @item_condition.present? && @item_condition == 'refurbished'
12
+ end
13
+
14
+ def search_query
15
+ 'condition=refurbished'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ # :reek:TooManyInstanceVariables
5
+ # :reek:UncommunicativeVariableName
6
+ class Address
7
+ attr_reader :address, :address2, :city, :country, :full_postal_code, :gmt_offset,
8
+ :lat, :lng, :postal_code, :region
9
+
10
+ def initialize(init_params)
11
+ @address = init_params[:address]
12
+ @address2 = init_params[:address2]
13
+ @city = init_params[:city]
14
+ @country = init_params[:country]
15
+ @full_postal_code = init_params[:full_postal_code]
16
+ @gmt_offset = init_params[:gmt_offset]
17
+ @lat = init_params[:lat]
18
+ @lng = init_params[:lng]
19
+ @postal_code = init_params[:postal_code]
20
+ @region = init_params[:region]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class BaseCategory
5
+ attr_reader :id, :name
6
+
7
+ def initialize(init_params)
8
+ @id = init_params[:id]
9
+ @name = init_params[:name]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'best_buy'
4
+
5
+ module BestBuy
6
+ class Category < BaseCategory
7
+ attr_reader :url, :active, :path, :sub_categories
8
+
9
+ def initialize(init_params)
10
+ @url = init_params[:url]
11
+ @active = init_params[:active]
12
+ @path = init_params[:path]
13
+ @sub_categories = init_params[:sub_categories].map do |sub_category|
14
+ BaseCategory.new(sub_category)
15
+ end
16
+
17
+ super(init_params)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class CollectionHeader
5
+ attr_reader :canonical_url, :current_page, :from, :partial,
6
+ :query_time, :to, :total, :total_pages, :total_time
7
+
8
+ def initialize(init_params)
9
+ @canonical_url = init_params[:canonical_url]
10
+ @current_page = init_params[:current_page]
11
+ @from = init_params[:from]
12
+ @partial = init_params[:partial]
13
+ @query_time = init_params[:query_time]
14
+ @to = init_params[:to]
15
+ @total = init_params[:total]
16
+ @total_pages = init_params[:total_pages]
17
+ @total_time = init_params[:total_time]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'best_buy'
4
+
5
+ module BestBuy
6
+ class CollectionsResponse
7
+ attr_reader :header, :collection
8
+
9
+ def initialize(response:, collection_name:, collection_type:)
10
+ header_hash = response.except(collection_name)
11
+ collection_hash = response[collection_name]
12
+
13
+ @header = CollectionHeader.new(header_hash)
14
+ @collection = collection_hash.map do |collection_item|
15
+ collection_type.new(collection_item)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class Image
5
+ attr_reader :height, :href, :primary, :rel, :unit_of_measure, :width
6
+
7
+ def initialize(init_params)
8
+ @height = init_params[:height]
9
+ @href = init_params[:href]
10
+ @primary = init_params[:primary]
11
+ @rel = init_params[:rel]
12
+ @unit_of_measure = init_params[:unit_of_measure]
13
+ @width = init_params[:width]
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class Offer
5
+ attr_reader :content_notes, :end_date, :id, :offer_name, :start_date, :text, :type, :url
6
+
7
+ def initialize(init_params)
8
+ @content_notes = init_params[:content_notes]
9
+ @end_date = init_params[:end_date]
10
+ @id = init_params[:id]
11
+ @offer_name = init_params[:offer_name]
12
+ @start_date = init_params[:start_date]
13
+ @text = init_params[:text]
14
+ @type = init_params[:type]
15
+ @url = init_params[:url]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'best_buy'
4
+
5
+ module BestBuy
6
+ # :reek:TooManyInstanceVariables
7
+ class Product
8
+ attr_reader :active, :alternate_categories, :category_path, :images, :name, :offers,
9
+ :raw_attributes, :regular_price, :sale_price, :shipping_cost,
10
+ :shipping_levels_of_service, :sku, :type, :upc, :url
11
+
12
+ # rubocop:disable Metrics/AbcSize
13
+ def initialize(init_params)
14
+ @active = init_params[:active]
15
+ @alternate_categories = init_params[:alternate_categories]
16
+ @category_path = init_params[:category_path]
17
+ @images = init_params[:images]&.map do |image_params|
18
+ Image.new(image_params)
19
+ end
20
+ @name = init_params[:name]
21
+ @offers = init_params[:offers]&.map do |offer_params|
22
+ Offer.new(offer_params)
23
+ end
24
+ @regular_price = init_params[:regular_price]
25
+ @sale_price = init_params[:sale_price]
26
+ @shipping_cost = init_params[:shipping_cost]
27
+ @shipping_levels_of_service = init_params[:shipping_levels_of_service]&.map do |slos_params|
28
+ ShippingLevelOfService.new(slos_params)
29
+ end
30
+ @sku = init_params[:sku]
31
+ @type = init_params[:type]
32
+ @upc = init_params[:upc]
33
+ @url = init_params[:url]
34
+
35
+ @raw_attributes = init_params
36
+ end
37
+ # rubocop:enable Metrics/AbcSize
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class ShippingLevelOfService
5
+ attr_reader :service_level_id, :service_level_name, :unit_shipping_price
6
+
7
+ def initialize(init_params)
8
+ @service_level_id = init_params[:service_level_id]
9
+ @service_level_name = init_params[:service_level_name]
10
+ @unit_shipping_price = init_params[:unit_shipping_price]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'best_buy'
4
+
5
+ module BestBuy
6
+ class Store
7
+ attr_reader :location_type, :long_name, :name, :opening_time, :phone,
8
+ :services, :store_id, :store_type, :store_address
9
+
10
+ delegate :address, :address2, :city, :country, :full_postal_code, :gmt_offset,
11
+ :lat, :lng, :postal_code, :region, to: :store_address
12
+
13
+ def initialize(init_params)
14
+ @location_type = init_params[:location_type]
15
+ @long_name = init_params[:long_name]
16
+ @name = init_params[:name]
17
+ @opening_time = init_params[:detailed_hours]
18
+ @phone = init_params[:phone]
19
+ @services = init_params[:services]&.map { |service_hash| service_hash[:service] }
20
+ @store_id = init_params[:store_id]
21
+ @store_type = init_params[:store_type]
22
+
23
+ @store_address = Address.new(init_params)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class Products < BaseAPI
5
+ include Conditions
6
+
7
+ PRODUCTS_API = '/v1/products'
8
+ CONDITIONS = [
9
+ CategoryCondition,
10
+ MinPriceCondition,
11
+ MaxPriceCondition,
12
+ NewCondition,
13
+ PreOwnedCondition,
14
+ RefurbishedCondition
15
+ ].freeze
16
+
17
+ def get_by(conditions)
18
+ add_search_conditions_to_query(conditions.except(:pagination))
19
+
20
+ pagination = conditions[:pagination] || {}
21
+
22
+ get_all(search_query: search_query_builder.build, pagination: pagination)
23
+ end
24
+
25
+ protected
26
+
27
+ def model_class
28
+ Product
29
+ end
30
+
31
+ def collection_name
32
+ :products
33
+ end
34
+
35
+ def api_url
36
+ PRODUCTS_API
37
+ end
38
+
39
+ def search_query_builder
40
+ @search_query_builder ||= SearchQueryBuilder.new
41
+ end
42
+
43
+ def add_search_conditions_to_query(conditions)
44
+ applying_conditions = CONDITIONS.map do |condition|
45
+ condition.new(conditions)
46
+ end.select(&:valid?)
47
+
48
+ applying_conditions.each do |applying_condition|
49
+ search_query_builder.add(applying_condition.search_query)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BestBuy
4
+ class SearchQueryBuilder
5
+ def add(condition)
6
+ conditions << condition
7
+ end
8
+
9
+ def build
10
+ return '' unless conditions.any?
11
+
12
+ "(#{conditions.join('&')})"
13
+ end
14
+
15
+ private
16
+
17
+ def conditions
18
+ @conditions ||= []
19
+ end
20
+ end
21
+ end