remixr 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +1 -0
- data/License +20 -0
- data/Notes +0 -0
- data/README.markdown +76 -0
- data/Rakefile +103 -0
- data/VERSION.yml +4 -0
- data/examples/chaining.rb +7 -0
- data/examples/find_products.rb +13 -0
- data/examples/find_stores.rb +11 -0
- data/lib/remixr.rb +29 -0
- data/lib/remixr/client.rb +157 -0
- data/test/fixtures/product_search_digital_photo_printer.json +216 -0
- data/test/fixtures/products.json +948 -0
- data/test/fixtures/products_over_20_bucks.json +904 -0
- data/test/fixtures/products_over_3k_within_50_miles.json +776 -0
- data/test/fixtures/products_skus_only.json +42 -0
- data/test/fixtures/stores.json +162 -0
- data/test/fixtures/stores_by_zip_02184.json +27 -0
- data/test/fixtures/stores_in_list.json +57 -0
- data/test/fixtures/stores_in_texas.json +162 -0
- data/test/fixtures/stores_page_20.json +162 -0
- data/test/fixtures/stores_page_20_sort_by_store_id_desc.json +162 -0
- data/test/fixtures/stores_starting_with_zip_021.json +87 -0
- data/test/fixtures/stores_within_50_miles_products_over_3k.json +4434 -0
- data/test/fixtures/stores_within_50_of_76227.json +172 -0
- data/test/remixr/client_test.rb +143 -0
- data/test/test_helper.rb +36 -0
- metadata +155 -0
data/History
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1 - initial release
|
data/License
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Squeejee
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Notes
ADDED
File without changes
|
data/README.markdown
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# remixr
|
2
|
+
|
3
|
+
The Ruby BestBuy [Remix API](http://remix.bestbuy.com/docs) gem. Remix is an API that gives you access to BestBuy.com's product catalog data and more.
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
sudo gem install remixr
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
|
12
|
+
client = Remixr::Client.new
|
13
|
+
|
14
|
+
### Find stores
|
15
|
+
|
16
|
+
# find stores within 50 miles of ZIP 76227
|
17
|
+
stores = client.stores({:area => ['76227', 50]}).fetch.stores
|
18
|
+
|
19
|
+
stores.first
|
20
|
+
|
21
|
+
=> {"city"=>"Denton", "longName"=>"Best Buy - Denton", "name"=>"Denton", "region"=>"TX", "address"=>"1800 S Loop 288, Ste 102 Bldg 1 ", "country"=>"US", "lng"=>-97.10067, "postalCode"=>"76205", "phone"=>"940-384-9581", "hours"=>"Mon: 10-9; Tue: 10-9; Wed: 10-9; Thurs: 10-9; Fri: 10-10; Sat: 10-10; Sun: 11-8", "storeId"=>827, "fullPostalCode"=>"76205", "lat"=>33.192524, "distance"=>9.79}
|
22
|
+
|
23
|
+
|
24
|
+
### Find products
|
25
|
+
|
26
|
+
# fetch first page of products on sale below 20 bucks
|
27
|
+
products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
|
28
|
+
|
29
|
+
# fetch only SKU and salePrice
|
30
|
+
products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
|
31
|
+
|
32
|
+
### Chaining
|
33
|
+
|
34
|
+
You can also chain `stores` and `products` to return stores and nested product info or vice versa
|
35
|
+
|
36
|
+
# find stores within 50 miles of ZIP 76227 and products over three G's
|
37
|
+
|
38
|
+
stores = client.stores({:area => ['76227', 50]}).products({:salePrice => {'$gt' => 3000}}).fetch.stores
|
39
|
+
|
40
|
+
stores.first.products.first.shortDescription
|
41
|
+
|
42
|
+
#=> "ENERGY STAR Qualified 4 HDMI inputs; gray Touch of Color bezel; 16:9 aspect ratio"
|
43
|
+
|
44
|
+
### Fetching
|
45
|
+
|
46
|
+
All calls terminate in a call to `fetch` which takes the following options
|
47
|
+
|
48
|
+
:page - positive integer for page number
|
49
|
+
:show - comma delimited string or array of field names to show
|
50
|
+
:sort - hash or string of sort info {'fieldname' => 'asc|desc'}
|
51
|
+
|
52
|
+
|
53
|
+
### Conditional operators
|
54
|
+
|
55
|
+
We took a page out of [MongoDB's](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ConditionalOperators%3A%3C%2C%3C%3D%2C%3E%2C%3E%3D) playbook and mapped conditional operators to text equivalents to avoid having these be keys to hashes:
|
56
|
+
|
57
|
+
{:salePrice => {'$gte' => 300.00}}
|
58
|
+
=> salePrice > 300.00
|
59
|
+
|
60
|
+
$gte - greater than or equal to : field > value
|
61
|
+
$lte - less than or equal to : field > value
|
62
|
+
$gt - greater than : field > value
|
63
|
+
$lt - less than : field > value
|
64
|
+
$ne - not equal to : field != value
|
65
|
+
|
66
|
+
More in the examples folder:
|
67
|
+
|
68
|
+
[http://github.com/squeejee/remixr/tree/master/examples](http://github.com/squeejee/remixr/tree/master/examples)
|
69
|
+
|
70
|
+
### Documentation
|
71
|
+
|
72
|
+
[http://rdoc.info/projects/squeejee/remixr](http://rdoc.info/projects/squeejee/remixr)
|
73
|
+
|
74
|
+
#### Copyright
|
75
|
+
|
76
|
+
Copyright (c) 2009 Squeejee. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "remixr"
|
8
|
+
gem.description = %Q{wrapper for the BestBuy Remix api}
|
9
|
+
gem.summary = %Q{wrapper for the BestBuy Remix api}
|
10
|
+
gem.email = "wynn@squeejee.com"
|
11
|
+
gem.homepage = "http://github.com/squeejee/remixr"
|
12
|
+
gem.authors = ["Wynn Netherland", "Jim Mulholland"]
|
13
|
+
gem.rubyforge_project = "remixr"
|
14
|
+
gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
|
15
|
+
|
16
|
+
gem.add_dependency('mash', '0.0.3')
|
17
|
+
gem.add_dependency('httparty', '0.4.3')
|
18
|
+
|
19
|
+
gem.add_development_dependency('thoughtbot-shoulda')
|
20
|
+
gem.add_development_dependency('jeremymcanally-matchy')
|
21
|
+
gem.add_development_dependency('mocha')
|
22
|
+
gem.add_development_dependency('fakeweb')
|
23
|
+
gem.add_development_dependency('mash')
|
24
|
+
end
|
25
|
+
rescue LoadError
|
26
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
require 'rcov/rcovtask'
|
38
|
+
Rcov::RcovTask.new do |test|
|
39
|
+
test.libs << 'test'
|
40
|
+
test.pattern = 'test/**/*_test.rb'
|
41
|
+
test.verbose = true
|
42
|
+
end
|
43
|
+
rescue LoadError
|
44
|
+
task :rcov do
|
45
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
task :default => :test
|
51
|
+
|
52
|
+
require 'rake/rdoctask'
|
53
|
+
Rake::RDocTask.new do |rdoc|
|
54
|
+
if File.exist?('VERSION.yml')
|
55
|
+
config = YAML.load(File.read('VERSION.yml'))
|
56
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
57
|
+
else
|
58
|
+
version = ""
|
59
|
+
end
|
60
|
+
|
61
|
+
rdoc.rdoc_dir = 'rdoc'
|
62
|
+
rdoc.title = "remixr #{version}"
|
63
|
+
rdoc.rdoc_files.include('README*')
|
64
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
65
|
+
end
|
66
|
+
|
67
|
+
begin
|
68
|
+
require 'rake/contrib/sshpublisher'
|
69
|
+
namespace :rubyforge do
|
70
|
+
|
71
|
+
desc "Release gem and RDoc documentation to RubyForge"
|
72
|
+
task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
|
73
|
+
|
74
|
+
namespace :release do
|
75
|
+
desc "Publish RDoc to RubyForge."
|
76
|
+
task :docs => [:rdoc] do
|
77
|
+
config = YAML.load(
|
78
|
+
File.read(File.expand_path('~/.rubyforge/user-config.yml'))
|
79
|
+
)
|
80
|
+
|
81
|
+
host = "#{config['username']}@rubyforge.org"
|
82
|
+
remote_dir = "/var/www/gforge-projects/remixr/rdoc"
|
83
|
+
local_dir = 'rdoc'
|
84
|
+
|
85
|
+
Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
86
|
+
end
|
87
|
+
|
88
|
+
# task :website do
|
89
|
+
# config = YAML.load(
|
90
|
+
# File.read(File.expand_path('~/.rubyforge/user-config.yml'))
|
91
|
+
# )
|
92
|
+
#
|
93
|
+
# host = "#{config['username']}@rubyforge.org"
|
94
|
+
# remote_dir = "/var/www/gforge-projects/remixr/"
|
95
|
+
# local_dir = 'website'
|
96
|
+
#
|
97
|
+
# Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
98
|
+
# end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
rescue LoadError
|
102
|
+
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
103
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
|
2
|
+
client = Remixr::Client.new
|
3
|
+
|
4
|
+
# find stores within 50 miles of ZIP 76227 and products over three G's
|
5
|
+
stores = client.stores({:area => ['76227', 50]}).products({:salePrice => {'$gt' => 3000}}).fetch.stores
|
6
|
+
stores.first.products.first.shortDescription
|
7
|
+
#=> "ENERGY STAR Qualified 4 HDMI inputs; gray Touch of Color bezel; 16:9 aspect ratio"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
|
2
|
+
client = Remixr::Client.new
|
3
|
+
|
4
|
+
# fetch first page of products on sale below 20 bucks
|
5
|
+
products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
|
6
|
+
|
7
|
+
products.first
|
8
|
+
# => {"url"=>"http://www.bestbuy.com/site/olspage.jsp?skuId=7524468&type=product&id=1494684&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL", "inStoreAvailability"=>true, "albumLabel"=>nil, "genre"=>nil, "sku"=>7524468, "affiliateUrl"=>nil, "cjAffiliateAddToCartUrl"=>nil, "salesRankLongTerm"=>2451, "addToCartUrl"=>"http://www.bestbuy.com/site/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=7524468", "remoteControlImage"=>nil, "affiliateAddToCartUrl"=>nil, "largeImage"=>nil, "new"=>false, "salePrice"=>15.99, "artistId"=>"BYPart1061717", "inStoreAvailabilityUpdateDate"=>"2007-07-27T20:20:50", "largeFrontImage"=>nil, "department"=>"VIDEO/COMPACT DISC", "artistName"=>"Purple City", "accessoriesImage"=>nil, "format"=>"CD", "customerReviewCount"=>nil, "regularPrice"=>15.99, "amgId"=>nil, "freeShipping"=>false, "salesRankShortTerm"=>250, "shortDescription"=>nil, "specialOrder"=>false, "nationalFeatured"=>false, "manufacturer"=>nil, "salesRankMediumTerm"=>570, "energyGuideImage"=>nil, "inStoreAvailabilityText"=>"Store Pickup: Limited Availability", "alternateViewsImage"=>nil, "mobileUrl"=>"http://m.bestbuy.com/r/1494684/7524468/", "subclass"=>"RAP", "name"=>"\"Paris to Purple City\"", "cjAffiliateUrl"=>nil, "image"=>"http://images.bestbuy.com/BestBuy_US/images/products/7524/7524468.jpg", "shippingCost"=>1.59, "subclassId"=>1009, "upc"=>"823979901426", "onlineAvailabilityText"=>"Shipping: Usually leaves our warehouse in 1 business day", "onlineAvailabilityUpdateDate"=>"2007-07-27T20:20:50", "topViewImage"=>nil, "class"=>"COMPACT DISC", "active"=>true, "classId"=>77, "parentalAdvisory"=>false, "thumbnailImage"=>"http://images.bestbuy.com/BestBuy_US/images/products/7524/7524468s.jpg", "leftViewImage"=>nil, "rightViewImage"=>nil, "productId"=>1494684, "source"=>"bestbuy", "customerReviewAverage"=>nil, "activeUpdateDate"=>"2007-07-27T20:20:50", "mediumImage"=>nil, "startDate"=>#<Date: 4906945/2,0,2299161>, "departmentId"=>8, "angleImage"=>nil, "albumVersion"=>nil, "spin360Url"=>nil, "priceUpdateDate"=>"2008-02-09T00:10:37", "categoryPath"=>[<Mash id="cat00000" name="Best Buy">, <Mash id="abcat0600000" name="Music & Movies">, <Mash id="cat02001" name="Music">, <Mash id="cat02012" name="Rap & Hip-Hop">, <Mash id="cat02719" name="Rap">], "printOnly"=>false, "releaseDate"=>#<Date: 4907365/2,0,2299161>, "search"=>nil, "copyright"=>nil, "onSale"=>false, "itemUpdateDate"=>"2009-02-03T03:50:13", "albumTitle"=>"\"Paris to Purple City\"", "type"=>"Music", "originalReleaseDat
|
9
|
+
|
10
|
+
|
11
|
+
# fetch only SKU and salePrice
|
12
|
+
products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
|
13
|
+
# => [{"salePrice"=>10.99, "sku"=>7000032}, {"salePrice"=>10.99, "sku"=>11467058}, {"salePrice"=>13.99, "sku"=>7873884}, {"salePrice"=>11.99, "sku"=>15444798}, {"salePrice"=>13.99, "sku"=>9113256}, {"salePrice"=>13.99, "sku"=>5797649}, {"salePrice"=>13.99, "sku"=>8890961}, {"salePrice"=>14.99, "sku"=>17338506}, {"salePrice"=>11.99, "sku"=>9242642}, {"salePrice"=>13.99, "sku"=>9171353}]
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
|
2
|
+
client = Remixr::Client.new
|
3
|
+
|
4
|
+
# find stores within 50 miles of ZIP 76227
|
5
|
+
stores = client.stores({:area => ['76227', 50]}).fetch.stores
|
6
|
+
|
7
|
+
stores.first
|
8
|
+
# => {"city"=>"Denton", "longName"=>"Best Buy - Denton", "name"=>"Denton", "region"=>"TX", "address"=>"1800 S Loop 288, Ste 102 Bldg 1 ", "country"=>"US", "lng"=>-97.10067, "postalCode"=>"76205", "phone"=>"940-384-9581", "hours"=>"Mon: 10-9; Tue: 10-9; Wed: 10-9; Thurs: 10-9; Fri: 10-10; Sat: 10-10; Sun: 11-8", "storeId"=>827, "fullPostalCode"=>"76205", "lat"=>33.192524, "distance"=>9.79}
|
9
|
+
|
10
|
+
|
11
|
+
|
data/lib/remixr.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
gem 'mash', '0.0.3'
|
5
|
+
require 'mash'
|
6
|
+
|
7
|
+
gem 'httparty', '0.4.3'
|
8
|
+
require 'httparty'
|
9
|
+
|
10
|
+
class APIKeyNotSet < StandardError; end
|
11
|
+
|
12
|
+
module Remixr
|
13
|
+
|
14
|
+
# Get your API key from http://remix.bestbuy.com/apps/register
|
15
|
+
def self.api_key
|
16
|
+
raise APIKeyNotSet if @api_key.nil?
|
17
|
+
|
18
|
+
@api_key
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.api_key=(api_key)
|
22
|
+
@api_key = api_key
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
directory = File.expand_path(File.dirname(__FILE__))
|
28
|
+
|
29
|
+
require File.join(directory, 'remixr', 'client')
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Remixr
|
2
|
+
class Client
|
3
|
+
include HTTParty
|
4
|
+
base_uri 'api.remix.bestbuy.com/v1'
|
5
|
+
format :json
|
6
|
+
|
7
|
+
attr_reader :api_key, :store_filters, :product_filters
|
8
|
+
|
9
|
+
# Get your api_key found here http://remix.bestbuy.com/apps/register
|
10
|
+
def initialize(api_key=nil)
|
11
|
+
@api_key = api_key
|
12
|
+
@api_key ||= Remixr.api_key
|
13
|
+
|
14
|
+
@api_path = ''
|
15
|
+
@store_filters = {}
|
16
|
+
@product_filters = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Example filters:
|
20
|
+
# Stores within 50 miles of ZIP 76227
|
21
|
+
# stores({:area => [76227,50]})
|
22
|
+
# GET /v1/stores(area(76227,50))
|
23
|
+
#
|
24
|
+
# Stores west of the Pecos
|
25
|
+
# stores({:lng => {'$lt' => -104.304199}})
|
26
|
+
# GET /v1/stores(lng>-104.304199)
|
27
|
+
#
|
28
|
+
def stores(filters={})
|
29
|
+
unless @api_path.include?('stores()')
|
30
|
+
@api_path += '+' unless @api_path.blank?
|
31
|
+
@api_path += "stores()"
|
32
|
+
end
|
33
|
+
@store_filters.merge!(filters)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
# Convenience method for finding a store by zip
|
38
|
+
# stores.in_zip(76227)
|
39
|
+
# GET /v1/stores(postalCode=76227)
|
40
|
+
def in_zip(zip)
|
41
|
+
self.stores({'postalCode' => zip})
|
42
|
+
end
|
43
|
+
|
44
|
+
# Convenience method for finding a store by region
|
45
|
+
# stores.in_region('TX')
|
46
|
+
# GET /v1/stores(region=TX)
|
47
|
+
def in_region(region)
|
48
|
+
self.stores({'region' => region})
|
49
|
+
end
|
50
|
+
|
51
|
+
# Example filters:
|
52
|
+
# Products under 20 bucks
|
53
|
+
# products({:salePrice => {'$lt' => 20.00}})
|
54
|
+
# GET /v1/products(salePrice<20.00)
|
55
|
+
def products(filters={})
|
56
|
+
unless @api_path.include?('products()')
|
57
|
+
@api_path += '+' unless @api_path.blank?
|
58
|
+
@api_path += "products()"
|
59
|
+
end
|
60
|
+
@product_filters.merge!(filters)
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Executes the search
|
66
|
+
# Possible options:
|
67
|
+
# :page - positive integer for page number
|
68
|
+
# :show - comma delimited string or array of field names to show
|
69
|
+
# :sort - hash or string of sort info {'fieldname' => 'asc|desc'}
|
70
|
+
def fetch(options={})
|
71
|
+
opts = {:apiKey => @api_key, :format => 'json'}
|
72
|
+
opts.merge!(scrub_options(options))
|
73
|
+
|
74
|
+
apply_store_filters
|
75
|
+
apply_product_filters
|
76
|
+
@api_path = URI.escape(@api_path)
|
77
|
+
response = self.class.get("/" + @api_path, :query => opts)
|
78
|
+
@api_path = ''
|
79
|
+
Mash.new response
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def apply_store_filters
|
84
|
+
if @store_filters.keys.blank?
|
85
|
+
@api_path.gsub!("stores()", "stores")
|
86
|
+
else
|
87
|
+
@api_path.gsub!("stores()", "stores(#{filter_params_string(@store_filters)})")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def apply_product_filters
|
92
|
+
if @product_filters.keys.blank?
|
93
|
+
@api_path.gsub!("products()", "products")
|
94
|
+
else
|
95
|
+
@api_path.gsub!("products()", "products(#{filter_params_string(@product_filters)})")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def filter_params_string(filters)
|
100
|
+
return "" unless filters.is_a?(Hash)
|
101
|
+
|
102
|
+
filters = Mash.new filters.to_hash # calling Mash.new on a mash is bad mmmm k?
|
103
|
+
params = []
|
104
|
+
filters.each do |key, value|
|
105
|
+
if value.is_a?(Hash)
|
106
|
+
inner_hash = value
|
107
|
+
case inner_hash.keys.first
|
108
|
+
when "$gt"
|
109
|
+
params << "#{key}>#{inner_hash.values.first}"
|
110
|
+
when "$lt"
|
111
|
+
params << "#{key}<#{inner_hash.values.first}"
|
112
|
+
when "$gte"
|
113
|
+
params << "#{key}>=#{inner_hash.values.first}"
|
114
|
+
when "$lte"
|
115
|
+
params << "#{key}<=#{inner_hash.values.first}"
|
116
|
+
when "$ne"
|
117
|
+
params << "#{key}!=#{inner_hash.values.first}"
|
118
|
+
when "$in"
|
119
|
+
params << "#{key} in(#{inner_hash.values.first.join(',')})"
|
120
|
+
end
|
121
|
+
elsif value.is_a?(Array)
|
122
|
+
params << "#{key}(#{value.join(',')})"
|
123
|
+
else
|
124
|
+
params << "#{key}=#{value}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
if params.blank?
|
129
|
+
""
|
130
|
+
else
|
131
|
+
"#{params.join('&')}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def scrub_options(options)
|
136
|
+
options = Mash.new(options.to_hash)
|
137
|
+
show = options.delete('show')
|
138
|
+
unless show.blank?
|
139
|
+
if show.is_a?(String)
|
140
|
+
options['show'] = show
|
141
|
+
elsif show.is_a?(Array)
|
142
|
+
options['show'] = show.join(',')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
sort = options.delete('sort')
|
146
|
+
unless sort.blank?
|
147
|
+
if sort.is_a?(Hash)
|
148
|
+
options['sort'] = "#{sort.keys.first}.#{sort.values.first}"
|
149
|
+
else
|
150
|
+
options['sort'] = sort
|
151
|
+
end
|
152
|
+
end
|
153
|
+
options
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
{
|
2
|
+
"totalPages": 1,
|
3
|
+
"currentPage": 1,
|
4
|
+
"queryTime": "0.346",
|
5
|
+
"from": 1,
|
6
|
+
"products": [
|
7
|
+
{
|
8
|
+
"shippingWeight": ".2208",
|
9
|
+
"printOnly": false,
|
10
|
+
"description": null,
|
11
|
+
"url": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?skuId=4660432&type=product&id=1051806199755&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL",
|
12
|
+
"inStoreAvailability": true,
|
13
|
+
"sku": 4660432,
|
14
|
+
"cjAffiliateAddToCartUrl": null,
|
15
|
+
"search": null,
|
16
|
+
"addToCartUrl": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=4660432",
|
17
|
+
"affiliateAddToCartUrl": null,
|
18
|
+
"new": false,
|
19
|
+
"accessoriesImage": null,
|
20
|
+
"weight": null,
|
21
|
+
"salePrice": 28.99,
|
22
|
+
"dollarSavings": 0.0,
|
23
|
+
"inStoreAvailabilityUpdateDate": "2009-01-21T01:34:16",
|
24
|
+
"largeFrontImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sa.jpg",
|
25
|
+
"freeShipping": true,
|
26
|
+
"navigability": true,
|
27
|
+
"height": null,
|
28
|
+
"color": "Photo Multicolor",
|
29
|
+
"remoteControlImage": null,
|
30
|
+
"largeImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sb.jpg",
|
31
|
+
"format": null,
|
32
|
+
"salesRankLongTerm": 1156,
|
33
|
+
"inStoreAvailabilityText": "Store Pickup: Available at most stores",
|
34
|
+
"regularPrice": 28.99,
|
35
|
+
"salesRankShortTerm": 244,
|
36
|
+
"nationalFeatured": false,
|
37
|
+
"manufacturer": "HP",
|
38
|
+
"onlineAvailabilityText": "Shipping: Usually leaves our warehouse in 1 business day",
|
39
|
+
"salesRankMediumTerm": 473,
|
40
|
+
"department": "PHOTO\/COMMODITIES",
|
41
|
+
"energyGuideImage": null,
|
42
|
+
"customerReviewCount": null,
|
43
|
+
"mobileUrl": "http:\/\/m.bestbuy.com\/r\/1051806199755\/4660432\/",
|
44
|
+
"name": "HP 58 Photo Inkjet Cartridge - Photo Multicolor",
|
45
|
+
"image": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sc.jpg",
|
46
|
+
"shippingCost": 0.0,
|
47
|
+
"shortDescription": "Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
|
48
|
+
"specialOrder": false,
|
49
|
+
"customerReviewAverage": null,
|
50
|
+
"warrantyParts": null,
|
51
|
+
"depth": null,
|
52
|
+
"topViewImage": null,
|
53
|
+
"upc": "808736183857",
|
54
|
+
"class": "PAPER\/OFFICE SUPPLIE",
|
55
|
+
"departmentId": 5,
|
56
|
+
"active": true,
|
57
|
+
"classId": 117,
|
58
|
+
"subclass": "INK\/TONER SUPPLIES",
|
59
|
+
"rightViewImage": null,
|
60
|
+
"cjAffiliateUrl": null,
|
61
|
+
"priceUpdateDate": "2009-03-10T06:13:56",
|
62
|
+
"alternateViewsImage": null,
|
63
|
+
"warrantyLabor": null,
|
64
|
+
"source": "bestbuy",
|
65
|
+
"releaseDate": null,
|
66
|
+
"modelNumber": "C6658AN",
|
67
|
+
"longDescription": "Multicolor photo ink cartridge compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers. Fade-resistant.",
|
68
|
+
"onlineAvailabilityUpdateDate": "2009-01-21T01:34:16",
|
69
|
+
"startDate": "2002-08-04",
|
70
|
+
"subclassId": 402,
|
71
|
+
"angleImage": null,
|
72
|
+
"thumbnailImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_s.gif",
|
73
|
+
"leftViewImage": null,
|
74
|
+
"type": "HardGood",
|
75
|
+
"productId": 1051806199755,
|
76
|
+
"orderable": "Available",
|
77
|
+
"categoryPath": [
|
78
|
+
{
|
79
|
+
"name": "Best Buy",
|
80
|
+
"id": "cat00000"
|
81
|
+
},
|
82
|
+
{
|
83
|
+
"name": "Cell Phones & Office",
|
84
|
+
"id": "abcat0800000"
|
85
|
+
},
|
86
|
+
{
|
87
|
+
"name": "Ink & Toner",
|
88
|
+
"id": "abcat0807000"
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"name": "Ink",
|
92
|
+
"id": "abcat0807001"
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"name": "Hewlett-Packard",
|
96
|
+
"id": "abcat0807005"
|
97
|
+
}
|
98
|
+
],
|
99
|
+
"mediumImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432fp.gif",
|
100
|
+
"onSale": false,
|
101
|
+
"itemUpdateDate": "2009-07-28T19:23:43",
|
102
|
+
"affiliateUrl": null,
|
103
|
+
"activeUpdateDate": "2009-01-21T01:34:16",
|
104
|
+
"width": null,
|
105
|
+
"spin360Url": null,
|
106
|
+
"backViewImage": null,
|
107
|
+
"onlineAvailability": true
|
108
|
+
},
|
109
|
+
{
|
110
|
+
"shippingWeight": ".225",
|
111
|
+
"printOnly": false,
|
112
|
+
"description": null,
|
113
|
+
"url": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?skuId=4312746&type=product&id=1051806147888&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL",
|
114
|
+
"inStoreAvailability": true,
|
115
|
+
"sku": 4312746,
|
116
|
+
"cjAffiliateAddToCartUrl": null,
|
117
|
+
"search": null,
|
118
|
+
"addToCartUrl": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=4312746",
|
119
|
+
"affiliateAddToCartUrl": null,
|
120
|
+
"new": false,
|
121
|
+
"accessoriesImage": null,
|
122
|
+
"weight": null,
|
123
|
+
"salePrice": 39.99,
|
124
|
+
"dollarSavings": 0.0,
|
125
|
+
"inStoreAvailabilityUpdateDate": "2009-06-27T01:43:54",
|
126
|
+
"largeFrontImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sa.jpg",
|
127
|
+
"freeShipping": true,
|
128
|
+
"navigability": true,
|
129
|
+
"height": null,
|
130
|
+
"color": "Multicolor",
|
131
|
+
"remoteControlImage": null,
|
132
|
+
"largeImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sb.jpg",
|
133
|
+
"format": null,
|
134
|
+
"salesRankLongTerm": 599,
|
135
|
+
"inStoreAvailabilityText": "Store Pickup: Available at most stores",
|
136
|
+
"regularPrice": 39.99,
|
137
|
+
"salesRankShortTerm": 243,
|
138
|
+
"nationalFeatured": false,
|
139
|
+
"manufacturer": "HP",
|
140
|
+
"onlineAvailabilityText": "Shipping: Usually leaves our warehouse in 1 business day",
|
141
|
+
"salesRankMediumTerm": 473,
|
142
|
+
"department": "PHOTO\/COMMODITIES",
|
143
|
+
"energyGuideImage": null,
|
144
|
+
"customerReviewCount": 1,
|
145
|
+
"mobileUrl": "http:\/\/m.bestbuy.com\/r\/1051806147888\/4312746\/",
|
146
|
+
"name": "HP 57 Inkjet Cartridge - Multicolor",
|
147
|
+
"image": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sc.jpg",
|
148
|
+
"shippingCost": 0.0,
|
149
|
+
"shortDescription": "Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
|
150
|
+
"specialOrder": false,
|
151
|
+
"customerReviewAverage": 5.0,
|
152
|
+
"warrantyParts": null,
|
153
|
+
"depth": null,
|
154
|
+
"topViewImage": null,
|
155
|
+
"upc": "725184712340",
|
156
|
+
"class": "PAPER\/OFFICE SUPPLIE",
|
157
|
+
"departmentId": 5,
|
158
|
+
"active": true,
|
159
|
+
"classId": 117,
|
160
|
+
"subclass": "INK\/TONER SUPPLIES",
|
161
|
+
"rightViewImage": null,
|
162
|
+
"cjAffiliateUrl": null,
|
163
|
+
"priceUpdateDate": "2009-03-10T00:13:56",
|
164
|
+
"alternateViewsImage": null,
|
165
|
+
"warrantyLabor": null,
|
166
|
+
"source": "bestbuy",
|
167
|
+
"releaseDate": null,
|
168
|
+
"modelNumber": "C6657AN",
|
169
|
+
"longDescription": "Tricolor ink cartridge creates bright, photo-quality color. Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
|
170
|
+
"onlineAvailabilityUpdateDate": "2009-06-27T01:43:54",
|
171
|
+
"startDate": "2002-08-15",
|
172
|
+
"subclassId": 402,
|
173
|
+
"angleImage": null,
|
174
|
+
"thumbnailImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_s.gif",
|
175
|
+
"leftViewImage": null,
|
176
|
+
"type": "HardGood",
|
177
|
+
"productId": 1051806147888,
|
178
|
+
"orderable": "Available",
|
179
|
+
"categoryPath": [
|
180
|
+
{
|
181
|
+
"name": "Best Buy",
|
182
|
+
"id": "cat00000"
|
183
|
+
},
|
184
|
+
{
|
185
|
+
"name": "Cell Phones & Office",
|
186
|
+
"id": "abcat0800000"
|
187
|
+
},
|
188
|
+
{
|
189
|
+
"name": "Ink & Toner",
|
190
|
+
"id": "abcat0807000"
|
191
|
+
},
|
192
|
+
{
|
193
|
+
"name": "Ink",
|
194
|
+
"id": "abcat0807001"
|
195
|
+
},
|
196
|
+
{
|
197
|
+
"name": "Hewlett-Packard",
|
198
|
+
"id": "abcat0807005"
|
199
|
+
}
|
200
|
+
],
|
201
|
+
"mediumImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746fp.gif",
|
202
|
+
"onSale": false,
|
203
|
+
"itemUpdateDate": "2009-07-28T19:21:16",
|
204
|
+
"affiliateUrl": null,
|
205
|
+
"activeUpdateDate": "2009-06-27T01:43:54",
|
206
|
+
"width": null,
|
207
|
+
"spin360Url": null,
|
208
|
+
"backViewImage": null,
|
209
|
+
"onlineAvailability": true
|
210
|
+
}
|
211
|
+
],
|
212
|
+
"total": 2,
|
213
|
+
"to": 2,
|
214
|
+
"canonicalUrl": "\/v1\/products(|)?format=json&apiKey=OU812",
|
215
|
+
"totalTime": "0.351"
|
216
|
+
}
|