shoppr 0.1.1 → 0.2.3

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