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