emporium 0.0.1 → 0.0.2.alpha
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/README.md +13 -3
- data/lib/emporium/product.rb +9 -61
- data/lib/emporium/services/amazon.rb +72 -0
- data/lib/emporium/services.rb +9 -0
- data/lib/emporium/version.rb +1 -1
- data/lib/emporium.rb +1 -8
- data/spec/emporium/emporium_spec.rb +43 -25
- data/spec/spec_helper.rb +0 -1
- metadata +7 -5
data/README.md
CHANGED
@@ -12,19 +12,29 @@ Add to your Gemfile and run the `bundle` command to install it.
|
|
12
12
|
|
13
13
|
**Requires Ruby 1.9.2 or later.**
|
14
14
|
|
15
|
+
## Configuration
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
Product.configuration do |config|
|
19
|
+
config.service = :amazon
|
20
|
+
# ...
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
15
24
|
|
16
25
|
## Usage
|
17
26
|
|
18
|
-
|
27
|
+
Give it a UPC to fetch a product object. The Code only takes UPC-A digits
|
19
28
|
|
20
29
|
```ruby
|
21
30
|
require 'emporium'
|
22
31
|
|
23
32
|
product = Emporium::Product.new "066661234567"
|
24
|
-
product.use :amazon
|
25
33
|
product.fetch!
|
26
34
|
```
|
27
35
|
|
36
|
+
|
37
|
+
|
28
38
|
## Development
|
29
39
|
|
30
|
-
This gem is
|
40
|
+
This gem is under the MIT License.
|
data/lib/emporium/product.rb
CHANGED
@@ -1,36 +1,21 @@
|
|
1
1
|
module Emporium
|
2
2
|
class Product
|
3
3
|
attr_accessor :code
|
4
|
+
attr_accessor :service
|
4
5
|
|
5
|
-
def initialize(code
|
6
|
-
@code = ::Code.new(code)
|
6
|
+
def initialize(code)
|
7
|
+
@code = Emporium::Code.new(code)
|
7
8
|
raise "invalid code" unless @code.valid?
|
8
|
-
@options = options.merge! code: @code.value
|
9
9
|
end
|
10
10
|
|
11
11
|
def fetch!
|
12
|
-
|
13
|
-
create ::Nokogiri::XML(open("#{@@service_url}?#{signed_query}"))
|
14
|
-
end
|
12
|
+
create @service.response
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
|
19
|
-
class_eval(<<-EOS)
|
20
|
-
def self.#{symbol}
|
21
|
-
@@#{symbol}
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.#{symbol}=(value)
|
25
|
-
@@#{symbol} = value
|
26
|
-
end
|
27
|
-
EOS
|
28
|
-
end
|
15
|
+
def use(service)
|
16
|
+
@service = service.new(code: @code.value)
|
29
17
|
end
|
30
18
|
|
31
|
-
class_option :access_key, :secret, :associate_tag
|
32
|
-
class_option :service, :service_url
|
33
|
-
|
34
19
|
def method_missing(name, *args)
|
35
20
|
if self.instance_variables.include? :"@#{name}"
|
36
21
|
self.instance_variable_get("@#{name}")
|
@@ -40,47 +25,10 @@ module Emporium
|
|
40
25
|
end
|
41
26
|
|
42
27
|
private
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
result.search("ItemAttributes").children.each do |value|
|
47
|
-
self.instance_variable_set("@#{value.name.downcase}", value.content)
|
48
|
-
end
|
28
|
+
def create(response)
|
29
|
+
response.search("ItemAttributes").children.each do |value|
|
30
|
+
self.instance_variable_set("@#{value.name.downcase}", value.content)
|
49
31
|
end
|
50
32
|
end
|
51
|
-
|
52
|
-
def params
|
53
|
-
{
|
54
|
-
"Service" => "AWSECommerceService",
|
55
|
-
"Operation" => "ItemLookup",
|
56
|
-
"IdType" => "UPC",
|
57
|
-
"ItemId" => @code.value,
|
58
|
-
"SearchIndex" => @options[:search_index] || "All",
|
59
|
-
"ResponseGroup" => @options[:response_group] || "Medium",
|
60
|
-
"Version" => @options[:version] || "2011-08-01",
|
61
|
-
"AssociateTag" => @@associate_tag,
|
62
|
-
"Timestamp" => Time.now.iso8601,
|
63
|
-
"AWSAccessKeyId" => @@access_key
|
64
|
-
}
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_query(hash)
|
68
|
-
hash.sort.collect { |k, v| [encode(k), encode(v.to_s)].join("=") }.join("&")
|
69
|
-
end
|
70
|
-
|
71
|
-
def signed_query
|
72
|
-
digest = HMAC::SHA256.digest(@@secret, request)
|
73
|
-
signature = Base64.encode64(digest).chomp
|
74
|
-
to_query(params.merge "Signature" => signature)
|
75
|
-
end
|
76
|
-
|
77
|
-
def encode(value)
|
78
|
-
CGI.escape(value).gsub("%7E", "~").gsub("+", "%20")
|
79
|
-
end
|
80
|
-
|
81
|
-
def request
|
82
|
-
"GET\nwebservices.amazon.com\n/onca/xml\n#{to_query(params)}"
|
83
|
-
end
|
84
|
-
|
85
33
|
end
|
86
34
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Emporium
|
2
|
+
module Services
|
3
|
+
class Amazon
|
4
|
+
def initialize(options={})
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def response
|
9
|
+
res = ::Nokogiri::XML(open("http://webservices.amazon.com/onca/xml?#{signed_query}"))
|
10
|
+
message = res.search('Message')
|
11
|
+
raise message.children.first.content unless message.empty?
|
12
|
+
res
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def params
|
17
|
+
{
|
18
|
+
"Service" => "AWSECommerceService",
|
19
|
+
"Operation" => "ItemLookup",
|
20
|
+
"IdType" => "UPC",
|
21
|
+
"ItemId" => @options[:code],
|
22
|
+
"SearchIndex" => @options[:search_index] || "All",
|
23
|
+
"ResponseGroup" => @options[:response_group] || "Medium",
|
24
|
+
"Version" => @options[:version] || "2011-08-01",
|
25
|
+
"AssociateTag" => @@associate_tag,
|
26
|
+
"Timestamp" => Time.now.iso8601,
|
27
|
+
"AWSAccessKeyId" => @@access_key
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_query(hash)
|
32
|
+
hash.sort.collect { |k, v| [encode(k), encode(v.to_s)].join("=") }.join("&")
|
33
|
+
end
|
34
|
+
|
35
|
+
def signed_query
|
36
|
+
digest = HMAC::SHA256.digest(@@secret, request)
|
37
|
+
signature = Base64.encode64(digest).chomp
|
38
|
+
to_query(params.merge "Signature" => signature)
|
39
|
+
end
|
40
|
+
|
41
|
+
def encode(value)
|
42
|
+
CGI.escape(value).gsub("%7E", "~").gsub("+", "%20")
|
43
|
+
end
|
44
|
+
|
45
|
+
def request
|
46
|
+
"GET\nwebservices.amazon.com\n/onca/xml\n#{to_query(params)}"
|
47
|
+
end
|
48
|
+
class << self
|
49
|
+
|
50
|
+
def configuration
|
51
|
+
yield self
|
52
|
+
end
|
53
|
+
|
54
|
+
def class_option(*symbols)
|
55
|
+
symbols.each do |symbol|
|
56
|
+
class_eval(<<-EOS)
|
57
|
+
def self.#{symbol}
|
58
|
+
@@#{symbol}
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.#{symbol}=(value)
|
62
|
+
@@#{symbol} = value
|
63
|
+
end
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class_option :access_key, :secret, :associate_tag
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/emporium/version.rb
CHANGED
data/lib/emporium.rb
CHANGED
@@ -1,40 +1,30 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
Product.associate_tag = CONFIG["associate_tag"]
|
9
|
-
Product.secret = CONFIG["secret"]
|
10
|
-
end
|
11
|
-
|
12
|
-
it "uses the amazon service" do
|
13
|
-
Product.service.should be :amazon
|
14
|
-
end
|
3
|
+
Emporium::Services::Amazon.configuration do |config|
|
4
|
+
config.access_key = CONFIG["access_key"]
|
5
|
+
config.associate_tag = CONFIG["associate_tag"]
|
6
|
+
config.secret = CONFIG["secret"]
|
7
|
+
end
|
15
8
|
|
9
|
+
describe Emporium::Product do
|
16
10
|
describe "#new" do
|
17
11
|
it "creates an instance from a upc" do
|
18
|
-
product = Product.new("036000241457")
|
19
|
-
product.should be_an_instance_of Product
|
12
|
+
product = Emporium::Product.new("036000241457")
|
13
|
+
product.should be_an_instance_of Emporium::Product
|
20
14
|
end
|
21
15
|
|
22
16
|
it "fails to create an instance if no upc is given" do
|
23
|
-
lambda { Product.new() }.should raise_error
|
17
|
+
lambda { Emporium::Product.new() }.should raise_error
|
24
18
|
end
|
25
19
|
|
26
20
|
it "fails to create an instance if invalid upc is given" do
|
27
|
-
lambda { Product.new("036000241452") }.should raise_error
|
28
|
-
end
|
29
|
-
|
30
|
-
it "has options in options if provided" do
|
31
|
-
product = Product.new("036000241457", secret: 'secret')
|
32
|
-
product.instance_eval { @options[:secret] }.should match 'secret'
|
21
|
+
lambda { Emporium::Product.new("036000241452") }.should raise_error
|
33
22
|
end
|
34
23
|
end
|
35
24
|
|
36
25
|
describe "#fetch!" do
|
37
|
-
product = Product.new("610839331574")
|
26
|
+
product = Emporium::Product.new("610839331574")
|
27
|
+
product.use Emporium::Services::Amazon
|
38
28
|
|
39
29
|
it "should fetch product information" do
|
40
30
|
lambda { product.fetch! }.should_not raise_error
|
@@ -44,19 +34,47 @@ describe Product do
|
|
44
34
|
product.fetch!
|
45
35
|
product.brand.should match 'Asus'
|
46
36
|
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#use" do
|
40
|
+
it "tells a product what service to use" do
|
41
|
+
product = Emporium::Product.new("610839331574")
|
42
|
+
product.use Emporium::Services::Amazon
|
43
|
+
product.service.should be_an_instance_of Emporium::Services::Amazon
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
47
|
|
48
|
+
describe Emporium::Services::Amazon do
|
49
|
+
describe "#new" do
|
50
|
+
it "should initialize with options" do
|
51
|
+
options = {some: "option"}
|
52
|
+
service = Emporium::Services::Amazon.new(options)
|
53
|
+
service.instance_variable_get('@options')[:some].should match "option"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#response" do
|
58
|
+
it "should return an XML document" do
|
59
|
+
service = Emporium::Services::Amazon.new(code: "610839331574")
|
60
|
+
service.response.should be_a_kind_of ::Nokogiri::XML::Document
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should raise an error if nothing is found" do
|
64
|
+
lambda { Emporium::Services::Amazon.new(code: "036000241452").response }.should raise_error
|
65
|
+
end
|
48
66
|
end
|
49
67
|
end
|
50
68
|
|
51
|
-
describe Code do
|
69
|
+
describe Emporium::Code do
|
52
70
|
describe "#valid?" do
|
53
71
|
it "returns true for a valid UPC" do
|
54
|
-
code = Code.new("036000241457")
|
72
|
+
code = Emporium::Code.new("036000241457")
|
55
73
|
code.valid?.should be true
|
56
74
|
end
|
57
75
|
|
58
76
|
it "returns false for an invalid UPC" do
|
59
|
-
code = Code.new("036000241452")
|
77
|
+
code = Emporium::Code.new("036000241452")
|
60
78
|
code.valid?.should_not be true
|
61
79
|
end
|
62
80
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emporium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 0.0.
|
4
|
+
prerelease: 6
|
5
|
+
version: 0.0.2.alpha
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Hugo Bastien
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-12-
|
13
|
+
date: 2011-12-05 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -64,6 +64,8 @@ files:
|
|
64
64
|
- lib/emporium.rb
|
65
65
|
- lib/emporium/code.rb
|
66
66
|
- lib/emporium/product.rb
|
67
|
+
- lib/emporium/services.rb
|
68
|
+
- lib/emporium/services/amazon.rb
|
67
69
|
- lib/emporium/version.rb
|
68
70
|
- spec/emporium/emporium_spec.rb
|
69
71
|
- spec/spec_helper.rb
|
@@ -84,9 +86,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
87
|
none: false
|
86
88
|
requirements:
|
87
|
-
- - "
|
89
|
+
- - ">"
|
88
90
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
91
|
+
version: 1.3.1
|
90
92
|
requirements: []
|
91
93
|
|
92
94
|
rubyforge_project: emporium
|