shoppr 0.1.0

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/History ADDED
@@ -0,0 +1 @@
1
+ 0.1.0 - 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.
@@ -0,0 +1,17 @@
1
+ = shoppr
2
+
3
+ The Ruby Shopping.com API gem.
4
+
5
+ == examples
6
+
7
+ See the examples directory.
8
+
9
+ http://github.com/squeejee/shoppr/tree/master/examples
10
+
11
+ == docs
12
+
13
+ http://rdoc.info/projects/squeejee/shoppr
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2009 Squeejee. See LICENSE for details.
@@ -0,0 +1,91 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "shoppr"
8
+ gem.summary = %Q{Ruby wrapper for the Shopping.com API}
9
+ gem.email = "wynn@squeejee.com"
10
+ gem.homepage = "http://github.com/squeejee/shoppr"
11
+ gem.authors = ["Wynn Netherland", "Jim Mulholland"]
12
+ gem.rubyforge_project = "shoppr"
13
+ gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
14
+
15
+ gem.add_dependency('mash', '0.0.3')
16
+ gem.add_dependency('httparty', '0.4.3')
17
+
18
+ gem.add_development_dependency('thoughtbot-shoulda')
19
+ gem.add_development_dependency('jeremymcanally-matchy')
20
+ gem.add_development_dependency('mocha')
21
+ gem.add_development_dependency('fakeweb')
22
+ gem.add_development_dependency('mash')
23
+ end
24
+ rescue LoadError
25
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = false
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/*_test.rb'
40
+ test.verbose = true
41
+ end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+
49
+ task :default => :test
50
+
51
+ require 'rake/rdoctask'
52
+ Rake::RDocTask.new do |rdoc|
53
+ if File.exist?('VERSION.yml')
54
+ config = YAML.load(File.read('VERSION.yml'))
55
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
56
+ else
57
+ version = ""
58
+ end
59
+
60
+ rdoc.rdoc_dir = 'rdoc'
61
+ rdoc.title = "shoppr #{version}"
62
+ rdoc.rdoc_files.include('README*')
63
+ rdoc.rdoc_files.include('lib/**/*.rb')
64
+ end
65
+
66
+ begin
67
+ require 'rake/contrib/sshpublisher'
68
+ namespace :rubyforge do
69
+
70
+ desc "Release gem and RDoc documentation to RubyForge"
71
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
72
+
73
+ namespace :release do
74
+ desc "Publish RDoc to RubyForge."
75
+ task :docs => [:rdoc] do
76
+ config = YAML.load(
77
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
78
+ )
79
+
80
+ host = "#{config['username']}@rubyforge.org"
81
+ remote_dir = "/var/www/gforge-projects/shoppr/rdoc"
82
+ local_dir = 'rdoc'
83
+
84
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
85
+ end
86
+
87
+ end
88
+ end
89
+ rescue LoadError
90
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
91
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 0
@@ -0,0 +1,92 @@
1
+ require 'forwardable'
2
+ require 'rubygems'
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'
12
+ require 'httparty'
13
+
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
+ module Shoppr
47
+
48
+ def self.api_key
49
+ @api_key ||= 'authorized-key'
50
+ end
51
+
52
+ def self.api_key=(value)
53
+ @api_key = value
54
+ end
55
+
56
+ def self.tracking_id
57
+ @tracking_id ||= '7000610'
58
+ end
59
+
60
+ def self.tracking_id=(value)
61
+ @tracking_id = value
62
+ end
63
+
64
+ end
65
+
66
+ directory = File.expand_path(File.dirname(__FILE__))
67
+
68
+
69
+ require File.join(directory, 'shoppr', 'api_exception')
70
+ require File.join(directory, 'shoppr', 'attribute_value')
71
+ require File.join(directory, 'shoppr', 'attribute')
72
+ require File.join(directory, 'shoppr', 'attribute_selection')
73
+ require File.join(directory, 'shoppr', 'image')
74
+ require File.join(directory, 'shoppr', 'feature_rating')
75
+ require File.join(directory, 'shoppr', 'consumer_review')
76
+ require File.join(directory, 'shoppr', 'store')
77
+ require File.join(directory, 'shoppr', 'offer')
78
+ require File.join(directory, 'shoppr', 'category_selection')
79
+ require File.join(directory, 'shoppr', 'client')
80
+ require File.join(directory, 'shoppr', 'client_tracking')
81
+ require File.join(directory, 'shoppr', 'keyword_search')
82
+ require File.join(directory, 'shoppr', 'dynamic_navigation_history')
83
+ require File.join(directory, 'shoppr', 'feature')
84
+ require File.join(directory, 'shoppr', 'feature_group')
85
+ require File.join(directory, 'shoppr', 'offer_selection')
86
+ require File.join(directory, 'shoppr', 'product_selection')
87
+ require File.join(directory, 'shoppr', 'search_history')
88
+ require File.join(directory, 'shoppr', 'server_detail')
89
+ require File.join(directory, 'shoppr', 'product')
90
+ require File.join(directory, 'shoppr', 'category')
91
+ require File.join(directory, 'shoppr', 'generic_response')
92
+ require File.join(directory, 'shoppr', 'general_search_response')
@@ -0,0 +1,8 @@
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
7
+ end
8
+ end
@@ -0,0 +1,10 @@
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'
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Shoppr
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
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Shoppr
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
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Shoppr
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'
13
+ end
14
+ end
@@ -0,0 +1,10 @@
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'
9
+ end
10
+ end
@@ -0,0 +1,47 @@
1
+ module Shoppr
2
+ class Client
3
+ include HTTParty
4
+ format :xml
5
+
6
+ attr_reader :api_key, :tracking_id, :sandboxed, :api_version
7
+
8
+ # Get your api_key found here http://developer.shopping.com/docs/Getting_Started
9
+ def initialize(sandboxed=false)
10
+ @api_key ||= Shoppr.api_key
11
+ @tracking_id ||= Shoppr.tracking_id
12
+
13
+ @sandboxed = sandboxed
14
+
15
+ base_uri = (self.sandboxed? ? 'sandbox.api.shopping.com/publisher/3.0/rest' : 'publisher.usb.api.shopping.com/publisher/3.0/rest')
16
+ self.class.base_uri base_uri
17
+ end
18
+
19
+ def sandboxed?
20
+ !!@sandboxed
21
+ end
22
+
23
+ def api_version
24
+ self.class.parser Proc.new {|response| GenericResponse.from_xml(response)}
25
+ @api_version ||= self.class.get('/').server_detail.api_version
26
+ end
27
+
28
+ 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)))
31
+ end
32
+
33
+
34
+ private
35
+ def default_options
36
+ {:apiKey => self.api_key, :trackingId => self.tracking_id}
37
+ end
38
+
39
+ def prep_query_options(options)
40
+ opts = {}
41
+ options.each do |key, value|
42
+ opts[key.to_s.camelize(:lower)] = value
43
+ end
44
+ opts
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
1
+ module Shoppr
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
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Shoppr
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'
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module Shoppr
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
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Shoppr
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 => []
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Shoppr
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]
8
+ end
9
+ end
@@ -0,0 +1,8 @@
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
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module Shoppr
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'
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Shoppr
2
+ class GenericResponse
3
+ include ROXML
4
+ xml_convention {|val| val.camelize(:lower) }
5
+ xml_reader :server_detail, :as => ServerDetail
6
+ xml_reader :exceptions, :as => [APIException], :in => 'exceptions'
7
+ end
8
+ end