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.
@@ -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 = "wynn@squeejee.com"
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('mash', '0.0.3')
16
- gem.add_dependency('httparty', '~> 0.4.3')
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('mash')
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
@@ -1,5 +1,5 @@
1
1
  ---
2
- :major: 0
3
- :minor: 1
4
2
  :build:
5
- :patch: 1
3
+ :major: 0
4
+ :minor: 2
5
+ :patch: 3
@@ -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__))
@@ -1,8 +1,9 @@
1
1
  module Shoppr
2
- class APIException
3
- include ROXML
4
- xml_reader :type, :from => :attr
5
- xml_reader :code, :as => Integer
6
- xml_reader :message
2
+ class APIException
3
+
4
+ def initialize(cat_mash)
5
+ Shoppr.map_mash_attrs(self, cat_mash)
6
+ end
7
+
7
8
  end
8
9
  end
@@ -1,10 +1,16 @@
1
1
  module Shoppr
2
- class Attribute
3
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :id, :from => '@id'
6
- xml_reader :name
7
- xml_reader :attribute_url, :from => 'attributeURL'
8
- xml_reader :attribute_values, :as => [AttributeValue], :from => 'attributeValues'
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
- 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 :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
@@ -1,14 +1,32 @@
1
1
  module Shoppr
2
2
  class Category
3
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :id, :from => '@id', :as => Integer
6
- xml_reader :name
7
- xml_reader :category_url, :from => 'categoryURL'
8
- xml_reader :content_type
9
- xml_reader :products, :as => [Product], :from => 'items/product'
10
- xml_reader :offers, :as => [Offer], :from => 'items/offer'
11
- xml_reader :attributes, :as => [Attribute], :in => 'attributes'
12
- xml_reader :categories, :as => [Category], :in => 'categories'
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
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :id, :from => '@id', :as => Integer
6
- xml_reader :name
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
@@ -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.from_xml(response)}
30
- self.class.get('/GeneralSearch', :query => default_options.merge(prep_query_options(options)))
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
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :height, :as => Integer, :from => '@height'
6
- xml_reader :width, :as => Integer, :from => '@width'
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
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :author_id, :from => 'authorID'
6
- xml_reader :post_date, :as => Time
7
- xml_reader :rating, :as => Float, :from => 'rating/overallRating'
8
- xml_reader :feature_ratings, :as => [FeatureRating], :from => 'rating/featureRating'
9
- xml_reader :summary
10
- xml_reader :bottom_line
11
- xml_reader :pros
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
@@ -1,8 +1,4 @@
1
1
  module Shoppr
2
2
  class DynamicNavigationHistory
3
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :keyword_search, :as => KeywordSearch
6
- xml_reader :attribute_selection, :as => AttributeSelection
7
3
  end
8
4
  end
@@ -1,9 +1,17 @@
1
1
  module Shoppr
2
2
  class Feature
3
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :name
6
- xml_reader :description
7
- xml_reader :values, :as => []
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
@@ -1,9 +1,15 @@
1
1
  module Shoppr
2
2
  class FeatureGroup
3
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :name
6
- xml_reader :description
7
- xml_reader :features, :as => [Feature]
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
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :name
6
- xml_reader :value, :as => Float
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
- include ROXML
4
- xml_convention {|val| val.camelize(:lower) }
5
- xml_reader :related_terms, :as => [], :in => 'related_terms', :from => 'term'
6
- xml_reader :server_detail, :as => ServerDetail
7
- xml_reader :exceptions, :as => [APIException], :in => 'exceptions'
8
- xml_reader :client_tracking, :as => ClientTracking
9
- xml_reader :search_history, :as => SearchHistory
10
- xml_reader :categories, :as => [Category], :in => 'categories'
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