shoppr 0.1.1 → 0.2.3
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.
- data/README.markdown +40 -0
- data/Rakefile +9 -4
- data/VERSION.yml +3 -3
- data/lib/shoppr.rb +13 -40
- data/lib/shoppr/api_exception.rb +6 -5
- data/lib/shoppr/attribute.rb +13 -7
- data/lib/shoppr/attribute_selection.rb +0 -6
- data/lib/shoppr/attribute_value.rb +5 -6
- data/lib/shoppr/category.rb +28 -10
- data/lib/shoppr/category_selection.rb +5 -7
- data/lib/shoppr/client.rb +11 -5
- data/lib/shoppr/client_tracking.rb +4 -9
- data/lib/shoppr/consumer_review.rb +9 -12
- data/lib/shoppr/dynamic_navigation_history.rb +0 -4
- data/lib/shoppr/feature.rb +13 -5
- data/lib/shoppr/feature_group.rb +11 -5
- data/lib/shoppr/feature_rating.rb +6 -5
- data/lib/shoppr/general_search_response.rb +25 -8
- data/lib/shoppr/generic_response.rb +9 -4
- data/lib/shoppr/image.rb +5 -7
- data/lib/shoppr/keyword_search.rb +0 -6
- data/lib/shoppr/offer.rb +12 -22
- data/lib/shoppr/offer_selection.rb +0 -6
- data/lib/shoppr/product.rb +22 -23
- data/lib/shoppr/product_selection.rb +0 -6
- data/lib/shoppr/search_history.rb +13 -6
- data/lib/shoppr/server_detail.rb +5 -9
- data/lib/shoppr/store.rb +10 -14
- data/test/fixtures/general_search_specs_offers_reviews.xml +1311 -1
- data/test/shoppr/general_search_response_test.rb +40 -71
- data/test/shoppr/generic_response_test.rb +1 -1
- metadata +85 -41
- data/README.rdoc +0 -17
data/README.markdown
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# shoppr
|
2
|
+
|
3
|
+
The Ruby Shopping.com API gem.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
sudo gem install shoppr
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
To use the Shopping.com API, you'll need an [API key]( http://developer.shopping.com/docs/Getting_Started)
|
12
|
+
|
13
|
+
# Set up your API key
|
14
|
+
Shoppr.api_key = 'OU812'
|
15
|
+
|
16
|
+
then just create a client
|
17
|
+
|
18
|
+
client = Shoppr::Client.new
|
19
|
+
|
20
|
+
or if you want to use the sandbox test environment you can do so without an API key:
|
21
|
+
|
22
|
+
client = Shoppr::Client.new(true)
|
23
|
+
|
24
|
+
### Searching for products by keyword
|
25
|
+
|
26
|
+
client.search(:keyword => 'nikon')
|
27
|
+
|
28
|
+
### Searching for products by keyword showing product reviews
|
29
|
+
|
30
|
+
client.search(:keyword => 'nikon', :show_product_reviews => true)
|
31
|
+
|
32
|
+
More scenario examples can be found on the [shopping.com API site](http://developer.shopping.com/docs/API_Use_Cases)
|
33
|
+
|
34
|
+
## docs
|
35
|
+
|
36
|
+
http://rdoc.info/projects/squeejee/shoppr
|
37
|
+
|
38
|
+
## Copyright
|
39
|
+
|
40
|
+
Copyright (c) 2009 Squeejee. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -6,20 +6,20 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "shoppr"
|
8
8
|
gem.summary = %Q{Ruby wrapper for the Shopping.com API}
|
9
|
-
gem.email = "
|
9
|
+
gem.email = "jim@squeejee.com"
|
10
10
|
gem.homepage = "http://github.com/squeejee/shoppr"
|
11
11
|
gem.authors = ["Wynn Netherland", "Jim Mulholland"]
|
12
12
|
gem.rubyforge_project = "shoppr"
|
13
13
|
gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
|
14
14
|
|
15
|
-
gem.add_dependency('
|
16
|
-
gem.add_dependency('httparty', '
|
15
|
+
gem.add_dependency('hashie', '0.2.0')
|
16
|
+
gem.add_dependency('httparty', '>= 0.5.0')
|
17
17
|
|
18
18
|
gem.add_development_dependency('thoughtbot-shoulda')
|
19
19
|
gem.add_development_dependency('jeremymcanally-matchy')
|
20
20
|
gem.add_development_dependency('mocha')
|
21
21
|
gem.add_development_dependency('fakeweb')
|
22
|
-
gem.add_development_dependency('
|
22
|
+
gem.add_development_dependency('hashie')
|
23
23
|
end
|
24
24
|
rescue LoadError
|
25
25
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
@@ -74,3 +74,8 @@ begin
|
|
74
74
|
rescue LoadError
|
75
75
|
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
76
76
|
end
|
77
|
+
|
78
|
+
desc "Open an irb session preloaded with this library"
|
79
|
+
task :console do
|
80
|
+
sh "irb -rubygems -I lib -r shoppr.rb"
|
81
|
+
end
|
data/VERSION.yml
CHANGED
data/lib/shoppr.rb
CHANGED
@@ -1,48 +1,9 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'rubygems'
|
3
3
|
require 'active_support'
|
4
|
-
|
5
|
-
gem 'roxml'
|
6
|
-
require 'roxml'
|
7
|
-
|
8
|
-
gem 'mash', '0.0.3'
|
9
|
-
require 'mash'
|
10
|
-
|
11
|
-
gem 'httparty', '~> 0.4.3'
|
4
|
+
require 'hashie'
|
12
5
|
require 'httparty'
|
13
6
|
|
14
|
-
module HTTParty
|
15
|
-
module ClassMethods
|
16
|
-
def parser(customer_parser)
|
17
|
-
default_options[:parser] = customer_parser
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class Request
|
22
|
-
def parse_response(body)
|
23
|
-
return nil if body.nil? or body.empty?
|
24
|
-
if options[:parser].blank?
|
25
|
-
case format
|
26
|
-
when :xml
|
27
|
-
Crack::XML.parse(body)
|
28
|
-
when :json
|
29
|
-
Crack::JSON.parse(body)
|
30
|
-
when :yaml
|
31
|
-
YAML::load(body)
|
32
|
-
else
|
33
|
-
body
|
34
|
-
end
|
35
|
-
else
|
36
|
-
if options[:parser].is_a?(Proc)
|
37
|
-
options[:parser].call(body)
|
38
|
-
else
|
39
|
-
body
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
7
|
module Shoppr
|
47
8
|
|
48
9
|
def self.api_key
|
@@ -61,6 +22,18 @@ module Shoppr
|
|
61
22
|
@tracking_id = value
|
62
23
|
end
|
63
24
|
|
25
|
+
def self.map_mash_attrs(obj, mash)
|
26
|
+
attrs = mash.map {|k,v| k.underscore}
|
27
|
+
|
28
|
+
obj.class_eval do
|
29
|
+
attr_accessor *attrs
|
30
|
+
end
|
31
|
+
|
32
|
+
mash.each do |k,v|
|
33
|
+
obj.send("#{k.underscore}=", v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
64
37
|
end
|
65
38
|
|
66
39
|
directory = File.expand_path(File.dirname(__FILE__))
|
data/lib/shoppr/api_exception.rb
CHANGED
data/lib/shoppr/attribute.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Shoppr
|
2
|
-
class Attribute
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
def initialize(cat_mash)
|
5
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
6
|
+
|
7
|
+
if self.attribute_values.attributeValue.is_a?(Array)
|
8
|
+
@attribute_values = self.attribute_values.attributeValue.map {|f| AttributeValue.new(f)}
|
9
|
+
elsif self.attribute_values.attributeValue
|
10
|
+
@attribute_values = [AttributeValue.new(self.attribute_values.attributeValue)]
|
11
|
+
else
|
12
|
+
@attribute_values = []
|
13
|
+
end
|
14
|
+
end
|
9
15
|
end
|
10
16
|
end
|
@@ -1,10 +1,4 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class AttributeSelection
|
3
|
-
include ROXML
|
4
|
-
xml_convention {|val| val.camelize(:lower) }
|
5
|
-
xml_reader :id, :from => '@id'
|
6
|
-
xml_reader :name
|
7
|
-
xml_reader :attribute_value_url, :from => 'attributeValueURL'
|
8
|
-
xml_reader :dropped?, :from => :attr
|
9
3
|
end
|
10
4
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class AttributeValue
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
xml_reader :matching_items_count, :as => Integer
|
3
|
+
|
4
|
+
def initialize(cat_mash)
|
5
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
6
|
+
end
|
7
|
+
|
9
8
|
end
|
10
9
|
end
|
data/lib/shoppr/category.rb
CHANGED
@@ -1,14 +1,32 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class Category
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
|
4
|
+
attr_accessor :attributes, :products
|
5
|
+
|
6
|
+
def initialize(cat_mash)
|
7
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
8
|
+
|
9
|
+
if self.attributes
|
10
|
+
if self.attributes.attribute
|
11
|
+
@attributes = self.attributes.attribute.map {|attribute| Attribute.new(attribute) }
|
12
|
+
else
|
13
|
+
@attributes = []
|
14
|
+
end
|
15
|
+
else
|
16
|
+
@attributes = []
|
17
|
+
end
|
18
|
+
|
19
|
+
if self.items
|
20
|
+
if self.items.product.is_a?(Array)
|
21
|
+
@products = self.items.product.map {|product| Product.new(product) }
|
22
|
+
else
|
23
|
+
@products = self.items.product ? [Product.new(self.items.product)] : []
|
24
|
+
end
|
25
|
+
else
|
26
|
+
@products = []
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
13
31
|
end
|
14
32
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module Shoppr
|
2
|
-
class CategorySelection
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
xml_reader :category_url, :from => 'categoryURL'
|
8
|
-
xml_reader :dropped?, :from => '@dropped'
|
2
|
+
class CategorySelection
|
3
|
+
|
4
|
+
def initialize(cat_mash)
|
5
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
6
|
+
end
|
9
7
|
end
|
10
8
|
end
|
data/lib/shoppr/client.rb
CHANGED
@@ -20,20 +20,26 @@ module Shoppr
|
|
20
20
|
!!@sandboxed
|
21
21
|
end
|
22
22
|
|
23
|
+
def generic_response
|
24
|
+
@generic_response ||= GenericResponse.new()
|
25
|
+
end
|
26
|
+
|
23
27
|
def api_version
|
24
|
-
self.class.parser Proc.new {|response| GenericResponse.from_xml(response)}
|
25
|
-
@api_version ||= self.class.get('/').server_detail.api_version
|
28
|
+
# self.class.parser Proc.new {|response| GenericResponse.from_xml(response)}
|
29
|
+
# @api_version ||= self.class.get('/').server_detail.api_version
|
30
|
+
@api_version ||= generic_response.server_detail.api_version
|
31
|
+
|
26
32
|
end
|
27
33
|
|
28
34
|
def search(options={})
|
29
|
-
self.class.parser Proc.new {|response| GeneralSearchResponse.
|
30
|
-
|
35
|
+
# self.class.parser Proc.new {|response| GeneralSearchResponse.parse_search_results(response)}
|
36
|
+
response = GeneralSearchResponse.new(default_options.merge(prep_query_options(options)))
|
31
37
|
end
|
32
38
|
|
33
39
|
|
34
40
|
private
|
35
41
|
def default_options
|
36
|
-
{:apiKey => self.api_key, :trackingId => self.tracking_id}
|
42
|
+
{:apiKey => self.api_key, :trackingId => self.tracking_id, :groupItemsByCategory => true}
|
37
43
|
end
|
38
44
|
|
39
45
|
def prep_query_options(options)
|
@@ -1,13 +1,8 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class ClientTracking
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
xml_reader :type, :from => '@type'
|
8
|
-
xml_reader :source_url, :from => 'sourceURL'
|
9
|
-
xml_reader :href_url, :from => 'hrefURL'
|
10
|
-
xml_reader :title_text
|
11
|
-
xml_reader :alt_text
|
3
|
+
|
4
|
+
def initialize(cat_mash)
|
5
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
6
|
+
end
|
12
7
|
end
|
13
8
|
end
|
@@ -1,16 +1,13 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class ConsumerReview
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
xml_reader :cons
|
13
|
-
xml_reader :content, :from => 'reviewContent'
|
14
|
-
xml_reader :url, :from => 'fullReviewURL'
|
3
|
+
|
4
|
+
attr_accessor :featured_ratings
|
5
|
+
|
6
|
+
def initialize(cat_mash)
|
7
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
8
|
+
|
9
|
+
@rating = self.rating.overallRating
|
10
|
+
end
|
11
|
+
|
15
12
|
end
|
16
13
|
end
|
data/lib/shoppr/feature.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class Feature
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
|
4
|
+
attr_accessor :values
|
5
|
+
def initialize(cat_mash)
|
6
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
7
|
+
|
8
|
+
if self.value.is_a?(Array)
|
9
|
+
@values = self.value.map {|value| value }
|
10
|
+
else
|
11
|
+
@values = [self.value]
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
8
16
|
end
|
9
17
|
end
|
data/lib/shoppr/feature_group.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class FeatureGroup
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
|
4
|
+
attr_accessor :features
|
5
|
+
def initialize(cat_mash)
|
6
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
7
|
+
|
8
|
+
if self.feature.is_a?(Array)
|
9
|
+
@features = self.feature.map {|f| Feature.new(f)}
|
10
|
+
else
|
11
|
+
@features = [Feature.new(self.feature)]
|
12
|
+
end
|
13
|
+
end
|
8
14
|
end
|
9
15
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Shoppr
|
2
|
-
class FeatureRating
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
class FeatureRating
|
3
|
+
|
4
|
+
def initialize(cat_mash)
|
5
|
+
Shoppr.map_mash_attrs(self, cat_mash)
|
6
|
+
end
|
7
|
+
|
7
8
|
end
|
8
9
|
end
|
@@ -1,12 +1,29 @@
|
|
1
1
|
module Shoppr
|
2
2
|
class GeneralSearchResponse
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
response = Shoppr::Client.get('/GeneralSearch', :query => options)
|
6
|
+
h = Hashie::Mash.new(response["GeneralSearchResponse"])
|
7
|
+
|
8
|
+
Shoppr.map_mash_attrs(self, h)
|
9
|
+
|
10
|
+
if self.categories.category.is_a?(Array)
|
11
|
+
@categories = self.categories.category.map {|category| Category.new(category) }
|
12
|
+
else
|
13
|
+
@categories = [Category.new(self.categories.category)]
|
14
|
+
end
|
15
|
+
|
16
|
+
if self.exceptions.exception.is_a?(Array)
|
17
|
+
@exceptions = self.exceptions.exception.map {|exception| APIException.new(exception) }
|
18
|
+
else
|
19
|
+
@exceptions = [APIException.new(self.exceptions.exception)]
|
20
|
+
end
|
21
|
+
|
22
|
+
@server_detail = ServerDetail.new(self.server_detail)
|
23
|
+
@client_tracking = ClientTracking.new(self.client_tracking)
|
24
|
+
@related_terms = self.related_terms ? self.related_terms.term : []
|
25
|
+
@search_history = SearchHistory.new(self.search_history)
|
26
|
+
end
|
27
|
+
|
11
28
|
end
|
12
29
|
end
|