shoppr 0.1.0

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