best_buy_ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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