ramazon_advertising 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +46 -0
  5. data/Rakefile +84 -0
  6. data/VERSION +1 -0
  7. data/features/friendly_errors.feature +15 -0
  8. data/features/generate_root_browse_nodes.feature +13 -0
  9. data/features/getting_offer_details.feature +30 -0
  10. data/features/getting_search_bins.feature +22 -0
  11. data/features/retrieve_browse_node_information.feature +16 -0
  12. data/features/retrieving_a_product.feature +32 -0
  13. data/features/searching_for_products.feature +47 -0
  14. data/features/step_definitions/auth_steps.rb +8 -0
  15. data/features/step_definitions/browse_node_steps.rb +55 -0
  16. data/features/step_definitions/error_steps.rb +14 -0
  17. data/features/step_definitions/product_collection_steps.rb +20 -0
  18. data/features/step_definitions/product_steps.rb +75 -0
  19. data/features/step_definitions/ramazon_advertising_steps.rb +0 -0
  20. data/features/support/env.rb +7 -0
  21. data/features/support/ramazon_advertising.example.yml +2 -0
  22. data/lib/ramazon/abstract_element.rb +18 -0
  23. data/lib/ramazon/browse_node.rb +69 -0
  24. data/lib/ramazon/configuration.rb +66 -0
  25. data/lib/ramazon/error.rb +12 -0
  26. data/lib/ramazon/image.rb +18 -0
  27. data/lib/ramazon/merchant.rb +21 -0
  28. data/lib/ramazon/offer.rb +27 -0
  29. data/lib/ramazon/price.rb +18 -0
  30. data/lib/ramazon/product.rb +303 -0
  31. data/lib/ramazon/product_collection.rb +30 -0
  32. data/lib/ramazon/rails_additions.rb +99 -0
  33. data/lib/ramazon/request.rb +82 -0
  34. data/lib/ramazon/search_bin.rb +11 -0
  35. data/lib/ramazon/search_bin_parameter.rb +9 -0
  36. data/lib/ramazon/search_bin_set.rb +11 -0
  37. data/lib/ramazon/signatory.rb +10 -0
  38. data/lib/ramazon_advertising.rb +41 -0
  39. data/lib/root_nodes.yml +64 -0
  40. data/lib/tasks/ramazon.rake +9 -0
  41. data/spec/ramazon/configuration_spec.rb +21 -0
  42. data/spec/spec_helper.rb +11 -0
  43. metadata +157 -0
@@ -0,0 +1,30 @@
1
+ module Ramazon
2
+ class ProductCollection < WillPaginate::Collection
3
+ include HappyMapper
4
+ has_many :search_bin_sets, Ramazon::SearchBinSet, :tag => "SearchBinSets/SearchBinSet"
5
+
6
+ def self.create_from_results(page, per_page, body)
7
+ results = Items.parse(body, {})[0]
8
+ col = create(page, 10, results.total_results || 0) do |pager|
9
+ pager.replace(results.products)
10
+ end
11
+
12
+ col.search_bin_sets = Ramazon::SearchBinSet.parse(body)
13
+ col
14
+ end
15
+
16
+ end
17
+
18
+ class Items
19
+ include HappyMapper
20
+ tag 'Items'
21
+
22
+ element :total_results, Integer, :tag => 'TotalResults'
23
+ element :total_pages, Integer, :tag => 'TotalPages'
24
+
25
+ has_many :products,
26
+ Ramazon::Product,
27
+ :tag => "Item",
28
+ :raw => true
29
+ end
30
+ end
@@ -0,0 +1,99 @@
1
+ #this code courtesy of Pat Allan and Rails Core
2
+ module Ramazon
3
+ module HashExcept
4
+ # Returns a new hash without the given keys.
5
+ def except(*keys)
6
+ rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
7
+ reject { |key,| rejected.include?(key) }
8
+ end
9
+
10
+ # Replaces the hash without only the given keys.
11
+ def except!(*keys)
12
+ replace(except(*keys))
13
+ end
14
+ end
15
+ end
16
+
17
+ Hash.send(
18
+ :include, Ramazon::HashExcept
19
+ ) unless Hash.instance_methods.include?("except")
20
+
21
+ module Ramazon
22
+ module ArrayExtractOptions
23
+ def extract_options!
24
+ last.is_a?(::Hash) ? pop : {}
25
+ end
26
+ end
27
+ end
28
+
29
+ Array.send(
30
+ :include, Ramazon::ArrayExtractOptions
31
+ ) unless Array.instance_methods.include?("extract_options!")
32
+
33
+ module Ramazon
34
+ module ClassAttributeMethods
35
+ def cattr_reader(*syms)
36
+ syms.flatten.each do |sym|
37
+ next if sym.is_a?(Hash)
38
+ class_eval(<<-EOS, __FILE__, __LINE__)
39
+ unless defined? @@#{sym}
40
+ @@#{sym} = nil
41
+ end
42
+
43
+ def self.#{sym}
44
+ @@#{sym}
45
+ end
46
+
47
+ def #{sym}
48
+ @@#{sym}
49
+ end
50
+ EOS
51
+ end
52
+ end
53
+
54
+ def cattr_writer(*syms)
55
+ options = syms.extract_options!
56
+ syms.flatten.each do |sym|
57
+ class_eval(<<-EOS, __FILE__, __LINE__)
58
+ unless defined? @@#{sym}
59
+ @@#{sym} = nil
60
+ end
61
+
62
+ def self.#{sym}=(obj)
63
+ @@#{sym} = obj
64
+ end
65
+
66
+ #{"
67
+ def #{sym}=(obj)
68
+ @@#{sym} = obj
69
+ end
70
+ " unless options[:instance_writer] == false }
71
+ EOS
72
+ end
73
+ end
74
+
75
+ def cattr_accessor(*syms)
76
+ cattr_reader(*syms)
77
+ cattr_writer(*syms)
78
+ end
79
+ end
80
+ end
81
+
82
+ Class.extend(
83
+ Ramazon::ClassAttributeMethods
84
+ ) unless Class.respond_to?(:cattr_reader)
85
+
86
+ module Ramazon
87
+ module MetaClass
88
+ def metaclass
89
+ class << self
90
+ self
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ unless Object.new.respond_to?(:metaclass)
97
+ Object.send(:include, Ramazon::MetaClass)
98
+ end
99
+
@@ -0,0 +1,82 @@
1
+ module Ramazon
2
+ #the object used to prepare and submit requests to amazon
3
+ class Request
4
+ include HTTParty
5
+ attr_accessor :options
6
+
7
+ def initialize(options = {})
8
+ self.options = options.merge(default_options)
9
+ end
10
+
11
+ def submit
12
+ @response = self.class.get(signed_url)
13
+ if valid?
14
+ @response.body
15
+ else
16
+ raise self.errors[0], "The following response errors were returned: #{self.errors.collect{|e| e.to_s}}"
17
+ end
18
+ end
19
+
20
+ # Error checking for responses (will return true if errors are present)
21
+ # @returns [boolean] whether the response yielded errors
22
+ def valid?
23
+ @response && errors.empty?
24
+ end
25
+
26
+ #errors returned from amazon
27
+ def errors
28
+ @errors ||= Ramazon::Error.parse(@response.body) || []
29
+ end
30
+
31
+ #use this if any type of caching is desired (TBD)
32
+ def unsigned_path
33
+ qs = ""
34
+
35
+ sorted_params.each do |key, value|
36
+ qs << "&#{key}=#{URI.encode(value.to_s)}"
37
+ end
38
+
39
+ qs.size > 0 ? qs[1..qs.size] : qs
40
+ end
41
+
42
+ def signed_url
43
+ self.options[:timestamp] = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S")
44
+ encoded_param_strings = []
45
+ sorted_params.each do |p|
46
+ encoded_param_strings << "#{p[0]}=#{CGI::escape(p[1].to_s)}"
47
+ end
48
+ string_to_sign =
49
+ "GET
50
+ #{Ramazon::Configuration.base_uri.gsub("http://", "")}
51
+ #{Ramazon::Configuration.path}
52
+ #{encoded_param_strings.join("&")}"
53
+
54
+ signature = Ramazon::Signatory.sign(string_to_sign)
55
+ encoded_param_strings << "Signature=" + signature
56
+
57
+ "#{Ramazon::Configuration.uri}?#{encoded_param_strings.join("&")}"
58
+ end
59
+
60
+ def sorted_params
61
+ params.sort {|a, b| a <=> b}
62
+ end
63
+
64
+ def params
65
+ formatted_params = {}
66
+ self.options.each do |key, value|
67
+ formatted_params[key.to_s.classify] = value.is_a?(Array) ? value.join(",") : value
68
+ end
69
+
70
+ formatted_params
71
+ end
72
+
73
+ private
74
+ def default_options
75
+ {
76
+ :service => "AWSECommerceService",
77
+ :version => "2009-07-01",
78
+ :AWSAccessKeyId => Ramazon::Configuration.access_key
79
+ }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,11 @@
1
+ module Ramazon
2
+ class SearchBin
3
+ include HappyMapper
4
+
5
+ tag "Bin"
6
+
7
+ has_many :parameters, Ramazon::SearchBinParameter, :tag => "BinParameter"
8
+ element :item_count, Integer, :tag => "BinItemCount"
9
+ element :name, String, :tag => "BinName"
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Ramazon
2
+ class SearchBinParameter
3
+ include HappyMapper
4
+ tag "BinParameter"
5
+
6
+ element :name, String, :tag => "Name"
7
+ element :value, String, :tag => "Value"
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Ramazon
2
+ class SearchBinSet
3
+ include HappyMapper
4
+
5
+ tag "SearchBinSet"
6
+
7
+ attribute :narrow_by, String, :tag => "NarrowBy"
8
+
9
+ has_many :search_bins, Ramazon::SearchBin, :tag => "Bin"
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Ramazon
2
+ class Signatory
3
+ def self.sign(string_to_sign)
4
+ sha1 = HMAC::SHA256.digest(Ramazon::Configuration.secret_key, string_to_sign)
5
+
6
+ #Base64 encoding adds a linefeed to the end of the string so chop the last character!
7
+ CGI.escape(Base64.encode64(sha1).chomp)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require "rubygems"
4
+
5
+ require "fileutils"
6
+ require "base64"
7
+ require "hmac-sha2"
8
+ require "digest/sha1"
9
+ require "digest/sha2"
10
+ require "cgi"
11
+
12
+ require "will_paginate"
13
+ require "httparty"
14
+ require "happymapper"
15
+ require "nokogiri"
16
+ require "configatron"
17
+ require "active_support/inflector"
18
+
19
+ require "ramazon/rails_additions"
20
+
21
+ require "ramazon/abstract_element"
22
+
23
+ require "ramazon/signatory"
24
+ require "ramazon/configuration"
25
+ require "ramazon/error"
26
+ require "ramazon/request"
27
+
28
+ require "ramazon/search_bin_parameter"
29
+ require "ramazon/search_bin"
30
+ require "ramazon/search_bin_set"
31
+
32
+ require "ramazon/image"
33
+ require "ramazon/price"
34
+ require "ramazon/merchant"
35
+ require "ramazon/offer"
36
+
37
+ require "ramazon/product"
38
+ require "ramazon/product_collection"
39
+ require "ramazon/browse_node"
40
+
41
+ configatron.ramazon.locale = :us
@@ -0,0 +1,64 @@
1
+ ---
2
+ Apparel (Kids & Baby): "1040662"
3
+ Baby: "165796011"
4
+ Gourmet Food: "3370831"
5
+ Home Appliances: "361395011"
6
+ Camera & Photo: "502394"
7
+ All Sports & Outdoors: "3375251"
8
+ Health & Personal Care: "3760901"
9
+ Cell Phones & Service: "301185"
10
+ Home Audio & Theater: "667846011"
11
+ Power & Hand Tools: "328182011"
12
+ Golf: "3410851"
13
+ Team Sports: "706809011"
14
+ Action Sports: "706812011"
15
+ Vacuums & Storage: "510080"
16
+ Office Products & Supplies: "1064954"
17
+ Magazines: "1263069011"
18
+ Industrial & Scientific: "16310091"
19
+ Jewelry: "3367581"
20
+ Pet Supplies: "12923371"
21
+ Home Improvement: "228013"
22
+ Bedding & Bath: "1057792"
23
+ TV & Video: "1266092011"
24
+ Computers & Accessories: "541966"
25
+ Books: "4"
26
+ Motorcycle & ATV: "346333011"
27
+ Outdoor Power Equipment: "551242"
28
+ Outdoor Recreation: "706814011"
29
+ Natural & Organic: "51537011"
30
+ "Furniture & D\xC3\xA9cor": "1057794"
31
+ Newspapers: "1263068011"
32
+ MP3 & Media Players: "172630"
33
+ Accessories: "1268192011"
34
+ MP3 Downloads: "163856011"
35
+ Kindle Books: "1286228011"
36
+ Toys & Games: "165793011"
37
+ Beauty: "3760911"
38
+ Grocery: "16310101"
39
+ Blogs: "401358011"
40
+ Video Games: "471306"
41
+ Cycling: "3403201"
42
+ Watches: "377110011"
43
+ Movies: "163414"
44
+ Sewing, Craft & Hobby: "12890711"
45
+ Software: "229548"
46
+ Kindle Store: "133141011"
47
+ Game Downloads: "979455011"
48
+ Video On Demand: "16261631"
49
+ Movies & TV: "130"
50
+ Textbooks: "465600"
51
+ Shoes: "672123011"
52
+ Apparel & Accessories: "1036592"
53
+ Kitchen & Dining: "284507"
54
+ Amazon Shorts: "13993911"
55
+ Blu-ray: "193640011"
56
+ Car Electronics & GPS: "1077068"
57
+ PC Games: "229575"
58
+ Computer Components: "193870011"
59
+ Music: "173425"
60
+ Automotive: "15684181"
61
+ Fan Gear: "3386071"
62
+ Exercise & Fitness: "3407731"
63
+ Patio, Lawn & Garden: "286168"
64
+ Musical Instruments: "11091801"
@@ -0,0 +1,9 @@
1
+ namespace :ramazon do
2
+ desc "Generate the yml file used for looking up root browse nodes"
3
+ task :generate_node_yml do
4
+ puts "Generating root nodes"
5
+ Ramazon::BrowseNode.generate_root_nodes
6
+ puts "Done"
7
+ end
8
+ end
9
+
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe Ramazon::Configuration do
4
+ it "should default to the us" do
5
+ Ramazon::Configuration.locale.should eql(:us)
6
+ end
7
+
8
+ it "should raise an exception if a set a locale that doesn't exist" do
9
+ lambda {Ramazon::Configuration.locale = :ffsf}.should raise_error
10
+ end
11
+
12
+ it "should derive a url of the locale" do
13
+ Ramazon::Configuration.locale = :de
14
+ Ramazon::Configuration.base_uri.should =~ /#{Ramazon::Configuration.locale.to_s}/
15
+ end
16
+
17
+ it "should use .com for a us address" do
18
+ Ramazon::Configuration.locale = :us
19
+ Ramazon::Configuration.base_uri.should =~ /\.com/
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'ramazon_advertising'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
11
+
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ramazon_advertising
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - Dan Pickett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-28 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: jnunemaker-httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: jnunemaker-happymapper
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.5
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: mislav-will_paginate
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.3.11
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: nokogiri
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.3.3
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: configatron
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 2.4.1
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: ruby-hmac
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.3.2
74
+ version:
75
+ description: " \t Amazon Advertising Wrapper - Use nokogiri to target the elements you want. An object oriented approach"
76
+ email: dpickett@enlightsolutions.com
77
+ executables: []
78
+
79
+ extensions: []
80
+
81
+ extra_rdoc_files:
82
+ - LICENSE
83
+ - README.rdoc
84
+ files:
85
+ - .document
86
+ - .gitignore
87
+ - LICENSE
88
+ - README.rdoc
89
+ - Rakefile
90
+ - VERSION
91
+ - features/friendly_errors.feature
92
+ - features/generate_root_browse_nodes.feature
93
+ - features/getting_offer_details.feature
94
+ - features/getting_search_bins.feature
95
+ - features/retrieve_browse_node_information.feature
96
+ - features/retrieving_a_product.feature
97
+ - features/searching_for_products.feature
98
+ - features/step_definitions/auth_steps.rb
99
+ - features/step_definitions/browse_node_steps.rb
100
+ - features/step_definitions/error_steps.rb
101
+ - features/step_definitions/product_collection_steps.rb
102
+ - features/step_definitions/product_steps.rb
103
+ - features/step_definitions/ramazon_advertising_steps.rb
104
+ - features/support/env.rb
105
+ - features/support/ramazon_advertising.example.yml
106
+ - lib/ramazon/abstract_element.rb
107
+ - lib/ramazon/browse_node.rb
108
+ - lib/ramazon/configuration.rb
109
+ - lib/ramazon/error.rb
110
+ - lib/ramazon/image.rb
111
+ - lib/ramazon/merchant.rb
112
+ - lib/ramazon/offer.rb
113
+ - lib/ramazon/price.rb
114
+ - lib/ramazon/product.rb
115
+ - lib/ramazon/product_collection.rb
116
+ - lib/ramazon/rails_additions.rb
117
+ - lib/ramazon/request.rb
118
+ - lib/ramazon/search_bin.rb
119
+ - lib/ramazon/search_bin_parameter.rb
120
+ - lib/ramazon/search_bin_set.rb
121
+ - lib/ramazon/signatory.rb
122
+ - lib/ramazon_advertising.rb
123
+ - lib/root_nodes.yml
124
+ - lib/tasks/ramazon.rake
125
+ - spec/ramazon/configuration_spec.rb
126
+ - spec/spec_helper.rb
127
+ has_rdoc: true
128
+ homepage: http://github.com/dpickett/ramazon_advertising
129
+ licenses: []
130
+
131
+ post_install_message:
132
+ rdoc_options:
133
+ - --charset=UTF-8
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: "0"
141
+ version:
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: "0"
147
+ version:
148
+ requirements: []
149
+
150
+ rubyforge_project:
151
+ rubygems_version: 1.3.5
152
+ signing_key:
153
+ specification_version: 3
154
+ summary: Amazon Advertising Wrapper - Use nokogiri to target the elements you want
155
+ test_files:
156
+ - spec/ramazon/configuration_spec.rb
157
+ - spec/spec_helper.rb