asin 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,23 +1,35 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asin (0.0.9)
4
+ asin (0.2.0)
5
5
  crack (~> 0.1.8)
6
- hashie (~> 0.4.0)
7
- httpi (~> 0.7.6)
6
+ hashie (~> 1.0.0)
7
+ httpi (~> 0.7.9)
8
8
 
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
12
  crack (0.1.8)
13
- hashie (0.4.0)
14
- httpclient (2.1.5.2)
15
- httpi (0.7.6)
13
+ diff-lcs (1.1.2)
14
+ fuubar (0.0.3)
15
+ rspec (~> 2.0)
16
+ rspec-instafail (~> 0.1.4)
17
+ ruby-progressbar (~> 0.0.9)
18
+ hashie (1.0.0)
19
+ httpclient (2.1.6.1)
20
+ httpi (0.7.9)
16
21
  rack
17
- mocha (0.9.10)
18
- rake
19
22
  rack (1.2.1)
20
- rake (0.8.7)
23
+ rspec (2.4.0)
24
+ rspec-core (~> 2.4.0)
25
+ rspec-expectations (~> 2.4.0)
26
+ rspec-mocks (~> 2.4.0)
27
+ rspec-core (2.4.0)
28
+ rspec-expectations (2.4.0)
29
+ diff-lcs (~> 1.1.2)
30
+ rspec-instafail (0.1.5)
31
+ rspec-mocks (2.4.0)
32
+ ruby-progressbar (0.0.9)
21
33
 
22
34
  PLATFORMS
23
35
  ruby
@@ -25,7 +37,8 @@ PLATFORMS
25
37
  DEPENDENCIES
26
38
  asin!
27
39
  crack (~> 0.1.8)
28
- hashie (~> 0.4.0)
29
- httpclient (~> 2.1.5.2)
30
- httpi (~> 0.7.6)
31
- mocha (~> 0.9.10)
40
+ fuubar (~> 0.0.3)
41
+ hashie (~> 1.0.0)
42
+ httpclient (~> 2.1.6.1)
43
+ httpi (~> 0.7.9)
44
+ rspec (~> 2.4.0)
data/README.rdoc CHANGED
@@ -1,19 +1,37 @@
1
1
  == Installation
2
2
 
3
+ Status: http://stillmaintained.com/phoet/asin.png
4
+
3
5
  The gem is tested against 1.9.2, 1.9.1 and 1.8.7 (compatibility with Heroku-Bamboo-Stack[http://docs.heroku.com/stack]) and runs smoothly with Rails 3.
4
6
 
5
7
  gem install asin
6
8
 
7
- == Usage
9
+ == Configuration
10
+
11
+ Since Version 0.2.0 ASIN provides a Rails-Style configuration.
12
+
13
+ You can put this in a initializer (config/initializers/asin.rb):
14
+
15
+ ASIN::Configuration.configure do |config|
16
+ config.secret = 'your-secret'
17
+ config.key = 'your-key'
18
+ end
19
+
20
+ The old configuration syntax is still valid:
8
21
 
9
22
  require 'asin'
10
23
  include ASIN
11
24
 
12
25
  # use the configure method to setup your api credentials
13
26
  configure :secret => 'your-secret', :key => 'your-key'
14
-
27
+
28
+ == Usage
29
+
30
+ # create an ASIN client
31
+ client = ASIN.client
32
+
15
33
  # lookup an item with the amazon standard identification number (asin)
16
- item = lookup '1430218150'
34
+ item = client.lookup '1430218150'
17
35
 
18
36
  # have a look at the title of the item
19
37
  item.title
@@ -31,9 +49,10 @@ The gem is tested against 1.9.2, 1.9.1 and 1.8.7 (compatibility with Heroku-Bamb
31
49
  == HTTPI
32
50
 
33
51
  ASIN uses HTTPI[https://github.com/rubiii/httpi] as a HTTP-Client adapter.
34
- You can configure the Client you like via configure:
52
+ See the HTTPI documentation for how to configure different clients or the logger.
53
+ As a default HTTPI uses _httpclient_ so you should add that dependency to your project:
35
54
 
36
- configure :client => :curb
55
+ gem 'httpclient'
37
56
 
38
57
  == Infos
39
58
 
@@ -42,3 +61,4 @@ Have a look at the RDOC[http://rdoc.info/projects/phoet/asin] for this project,
42
61
  For more information on the REST calls, have a look at the whole Amazon E-Commerce-API[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/].
43
62
 
44
63
  The code currently runs best on Ruby-1.9 due to encoding issues with the Amazon REST output (if *YOU* know how to backport this to 1.8.7, you are welcome!).
64
+
data/asin.gemspec CHANGED
@@ -4,7 +4,7 @@ require "asin/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "asin"
7
- s.version = Asin::VERSION
7
+ s.version = ASIN::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ['Peter Schröder']
10
10
  s.email = ['phoetmail@googlemail.com']
@@ -20,9 +20,10 @@ Gem::Specification.new do |s|
20
20
  s.require_paths = ["lib"]
21
21
 
22
22
  s.add_dependency('crack', '~> 0.1.8')
23
- s.add_dependency('hashie', '~> 0.4.0')
24
- s.add_dependency('httpi', '~> 0.7.6')
23
+ s.add_dependency('hashie', '~> 1.0.0')
24
+ s.add_dependency('httpi', '~> 0.7.9')
25
25
 
26
- s.add_development_dependency('httpclient', '~> 2.1.5.2')
27
- s.add_development_dependency('mocha', '~> 0.9.10')
26
+ s.add_development_dependency('httpclient', '~> 2.1.6.1')
27
+ s.add_development_dependency('rspec', '~> 2.4.0')
28
+ s.add_development_dependency('fuubar', '~> 0.0.3')
28
29
  end
data/lib/asin.rb CHANGED
@@ -6,6 +6,7 @@ require 'logger'
6
6
 
7
7
  require 'asin/item'
8
8
  require 'asin/version'
9
+ require 'asin/configuration'
9
10
 
10
11
  # ASIN (Amazon Simple INterface) is a gem for easy access of the Amazon E-Commerce-API.
11
12
  # It is simple to configure and use. Since it's very small and flexible, it is easy to extend it to your needs.
@@ -55,6 +56,19 @@ require 'asin/version'
55
56
  # lookup(asin, :ResponseGroup => :Medium)
56
57
  #
57
58
  module ASIN
59
+
60
+ DIGEST = OpenSSL::Digest::Digest.new('sha256')
61
+ PATH = '/onca/xml'
62
+
63
+ # Convenience method to create an ASIN client.
64
+ #
65
+ # A client is not necessary though, you can simply include the ASIN module otherwise.
66
+ #
67
+ def self.client
68
+ client = Object.new
69
+ client.extend ASIN
70
+ client
71
+ end
58
72
 
59
73
  # Configures the basic request parameters for ASIN.
60
74
  #
@@ -62,25 +76,10 @@ module ASIN
62
76
  #
63
77
  # configure :secret => 'your-secret', :key => 'your-key'
64
78
  #
65
- # ==== Options:
66
- #
67
- # [secret] the API secret key
68
- # [key] the API access key
69
- # [host] the host, which defaults to 'webservices.amazon.com'
70
- # [client] the client library for http (:httpclient, :curb, :net_http) see HTTPI for more information
71
- # [logger] a different logger than logging to STDERR
79
+ # See ASIN::Configuration for more infos.
72
80
  #
73
81
  def configure(options={})
74
- @options = {
75
- :host => 'webservices.amazon.com',
76
- :path => '/onca/xml',
77
- :digest => OpenSSL::Digest::Digest.new('sha256'),
78
- :client => :httpclient,
79
- :logger => Logger.new(STDERR),
80
- :key => '',
81
- :secret => '',
82
- } if @options.nil?
83
- @options.merge! options
82
+ Configuration.configure(options)
84
83
  end
85
84
 
86
85
  # Performs an +ItemLookup+ REST call against the Amazon API.
@@ -125,20 +124,20 @@ module ASIN
125
124
 
126
125
  private
127
126
 
127
+ def credentials_valid?
128
+ !Configuration.secret.nil? && !Configuration.key.nil?
129
+ end
130
+
128
131
  def call(params)
129
- raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" if @options.nil?
132
+ raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" unless credentials_valid?
130
133
 
131
134
  log(:debug, "calling with params=#{params}")
132
135
  signed = create_signed_query_string(params)
133
136
 
134
- url = "http://#{@options[:host]}#{@options[:path]}?#{signed}"
135
- log(:info, "performing rest call to url='#{url}' with client='#{@options[:client]}'")
136
-
137
- HTTPI::Adapter.use = @options[:client]
138
- HTTPI.logger = @options[:logger] if @options[:logger]
139
- request = HTTPI::Request.new(url)
140
- response = HTTPI.get(request)
141
-
137
+ url = "http://#{Configuration.host}#{PATH}?#{signed}"
138
+ log(:info, "performing rest call to url='#{url}'")
139
+
140
+ response = HTTPI.get(url)
142
141
  if response.code == 200
143
142
  # force utf-8 chars, works only on 1.9 string
144
143
  resp = response.body
@@ -154,7 +153,7 @@ module ASIN
154
153
  def create_signed_query_string(params)
155
154
  # nice tutorial http://cloudcarpenters.com/blog/amazon_products_api_request_signing/
156
155
  params[:Service] = :AWSECommerceService
157
- params[:AWSAccessKeyId] = @options[:key]
156
+ params[:AWSAccessKeyId] = Configuration.key
158
157
  # utc timestamp needed for signing
159
158
  params[:Timestamp] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
160
159
 
@@ -162,8 +161,8 @@ module ASIN
162
161
  query = params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
163
162
 
164
163
  # yeah, you really need to sign the get-request not the query
165
- request_to_sign = "GET\n#{@options[:host]}\n#{@options[:path]}\n#{query}"
166
- hmac = OpenSSL::HMAC.digest(@options[:digest], @options[:secret], request_to_sign)
164
+ request_to_sign = "GET\n#{Configuration.host}\n#{PATH}\n#{query}"
165
+ hmac = OpenSSL::HMAC.digest(DIGEST, Configuration.secret, request_to_sign)
167
166
 
168
167
  # don't forget to remove the newline from base64
169
168
  signature = CGI.escape(Base64.encode64(hmac).chomp)
@@ -171,7 +170,8 @@ module ASIN
171
170
  end
172
171
 
173
172
  def log(severity, message)
174
- @options[:logger].send severity, message if @options[:logger]
173
+ Configuration.logger.send severity, message if Configuration.logger
175
174
  end
176
175
 
177
- end
176
+ end
177
+
@@ -0,0 +1,52 @@
1
+ module ASIN
2
+ class Configuration
3
+ class << self
4
+
5
+ attr_accessor :secret, :key, :host, :logger
6
+
7
+ # Rails initializer configuration.
8
+ #
9
+ # Expects at least +secret+ and +key+ for the API call:
10
+ #
11
+ # ASIN::Configuration.configure do |config|
12
+ # config.secret = 'your-secret'
13
+ # config.key = 'your-key'
14
+ # end
15
+ #
16
+ # You may pass options as a hash as well:
17
+ #
18
+ # ASIN::Configuration.configure(:secret => 'your-secret', :key => 'your-key')
19
+ #
20
+ # ==== Options:
21
+ #
22
+ # [secret] the API secret key
23
+ # [key] the API access key
24
+ # [host] the host, which defaults to 'webservices.amazon.com'
25
+ # [logger] a different logger than logging to STDERR (nil for no logging)
26
+ #
27
+ def configure(options={})
28
+ init_config
29
+ if block_given?
30
+ yield self
31
+ else
32
+ options.each do |key, value|
33
+ send(:"#{key}=", value)
34
+ end
35
+ end
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def init_config(force=false)
42
+ return if @init && !force
43
+ @init = true
44
+ @secret = ''
45
+ @key = ''
46
+ @host = 'webservices.amazon.com'
47
+ @logger = Logger.new(STDERR)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
data/lib/asin/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Asin
2
- VERSION = "0.1.0"
1
+ module ASIN
2
+ VERSION = "0.2.0"
3
3
  end
data/rakefile.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  require "bundler"
2
2
  require "rake/rdoctask"
3
3
  require "rake/gempackagetask"
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = ["--format Fuubar", "--color", "-r ./spec/spec_helper.rb"]
8
+ t.pattern = 'spec/**/*_spec.rb'
9
+ end
4
10
 
5
11
  Bundler::GemHelper.install_tasks
6
12
 
data/spec/asin_spec.rb ADDED
@@ -0,0 +1,58 @@
1
+ ANY_ASIN = '1430218150'
2
+ ANY_SEARCH = 'Learn Objective-C'
3
+
4
+ describe ASIN do
5
+ before do
6
+ @helper = ASIN.client
7
+ @helper.configure :logger => nil
8
+
9
+ @secret = ENV['ASIN_SECRET']
10
+ @key = ENV['ASIN_KEY']
11
+ puts "configure #{@secret} and #{@key} for this test"
12
+ end
13
+
14
+ context "configuration" do
15
+ it "should fail without secret and key" do
16
+ lambda { @helper.lookup ANY_ASIN }.should raise_error(RuntimeError)
17
+ end
18
+
19
+ it "should fail with wrong configuration key" do
20
+ lambda { @helper.configure :wrong => 'key' }.should raise_error(NoMethodError)
21
+ end
22
+
23
+ it "should not override the configuration" do
24
+ config = @helper.configure :key => 'wont get overridden'
25
+ config.key.should_not be_nil
26
+
27
+ config = @helper.configure :secret => 'is also set'
28
+ config.key.should_not be_nil
29
+ config.secret.should_not be_nil
30
+ end
31
+
32
+ it "should work with a configuration block" do
33
+ config = ASIN::Configuration.configure do |config|
34
+ config.key = 'bla'
35
+ end
36
+ config.key.should eql('bla')
37
+ end
38
+ end
39
+
40
+ context "lookup and search" do
41
+ before do
42
+ @helper.configure :secret => @secret, :key => @key
43
+ end
44
+
45
+ it "should lookup a book" do
46
+ item = @helper.lookup(ANY_ASIN)
47
+ item.title.should =~ /Learn Objective/
48
+ end
49
+
50
+ it "should search a book with fulltext" do
51
+ items = @helper.search(ANY_SEARCH)
52
+ items.should have(10).things
53
+
54
+ items.first.title.should =~ /Learn Objective/
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,7 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','..','lib')
2
+ require 'rspec'
3
+ require 'asin'
4
+
5
+ Rspec.configure do |c|
6
+ c.mock_with :rspec
7
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Peter Schr\xC3\xB6der"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-04 00:00:00 +01:00
17
+ date: 2011-01-30 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -41,10 +41,10 @@ dependencies:
41
41
  - - ~>
42
42
  - !ruby/object:Gem::Version
43
43
  segments:
44
+ - 1
44
45
  - 0
45
- - 4
46
46
  - 0
47
- version: 0.4.0
47
+ version: 1.0.0
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
50
  - !ruby/object:Gem::Dependency
@@ -58,8 +58,8 @@ dependencies:
58
58
  segments:
59
59
  - 0
60
60
  - 7
61
- - 6
62
- version: 0.7.6
61
+ - 9
62
+ version: 0.7.9
63
63
  type: :runtime
64
64
  version_requirements: *id003
65
65
  - !ruby/object:Gem::Dependency
@@ -73,13 +73,13 @@ dependencies:
73
73
  segments:
74
74
  - 2
75
75
  - 1
76
- - 5
77
- - 2
78
- version: 2.1.5.2
76
+ - 6
77
+ - 1
78
+ version: 2.1.6.1
79
79
  type: :development
80
80
  version_requirements: *id004
81
81
  - !ruby/object:Gem::Dependency
82
- name: mocha
82
+ name: rspec
83
83
  prerelease: false
84
84
  requirement: &id005 !ruby/object:Gem::Requirement
85
85
  none: false
@@ -87,12 +87,27 @@ dependencies:
87
87
  - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  segments:
90
+ - 2
91
+ - 4
90
92
  - 0
91
- - 9
92
- - 10
93
- version: 0.9.10
93
+ version: 2.4.0
94
94
  type: :development
95
95
  version_requirements: *id005
96
+ - !ruby/object:Gem::Dependency
97
+ name: fuubar
98
+ prerelease: false
99
+ requirement: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ~>
103
+ - !ruby/object:Gem::Version
104
+ segments:
105
+ - 0
106
+ - 0
107
+ - 3
108
+ version: 0.0.3
109
+ type: :development
110
+ version_requirements: *id006
96
111
  description: Amazon Simple INterface or whatever you want to call this.
97
112
  email:
98
113
  - phoetmail@googlemail.com
@@ -111,11 +126,12 @@ files:
111
126
  - README.rdoc
112
127
  - asin.gemspec
113
128
  - lib/asin.rb
129
+ - lib/asin/configuration.rb
114
130
  - lib/asin/item.rb
115
131
  - lib/asin/version.rb
116
132
  - rakefile.rb
117
- - test/test_asin.rb
118
- - test/test_helper.rb
133
+ - spec/asin_spec.rb
134
+ - spec/spec_helper.rb
119
135
  has_rdoc: true
120
136
  homepage: http://github.com/phoet/asin
121
137
  licenses: []
@@ -149,5 +165,5 @@ signing_key:
149
165
  specification_version: 3
150
166
  summary: Simple interface to Amazon Item lookup.
151
167
  test_files:
152
- - test/test_asin.rb
153
- - test/test_helper.rb
168
+ - spec/asin_spec.rb
169
+ - spec/spec_helper.rb
data/test/test_asin.rb DELETED
@@ -1,49 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestAsin < Test::Unit::TestCase
4
-
5
-
6
- ANY_ASIN = '1430218150'
7
- ANY_SEARCH = 'Learn Objective-C'
8
-
9
- def setup
10
- @helper = Object.new
11
- @helper.extend ASIN
12
- end
13
-
14
- def test_lookup_with_configured_asin
15
- secret = ENV['ASIN_SECRET']
16
- key = ENV['ASIN_KEY']
17
- puts "configure #{secret} and #{key} for this test"
18
-
19
- @helper.configure :secret => secret, :key => key
20
- item = @helper.lookup(ANY_ASIN)
21
- assert_match(/Learn Objective/, item.title)
22
- end
23
-
24
- def test_search_with_configured_string
25
- secret = ENV['ASIN_SECRET']
26
- key = ENV['ASIN_KEY']
27
- puts "configure #{secret} and #{key} for this test"
28
-
29
- @helper.configure :secret => secret, :key => key
30
- items = @helper.search(ANY_SEARCH)
31
- assert_equal(10, items.size)
32
- item = items.first
33
- assert_match(/Learn Objective/, item.title)
34
- end
35
-
36
- def test_configure_second_time_wont_get_overridden
37
- config = @helper.configure :something => 'wont get overridden'
38
- assert_not_nil(config[:something])
39
-
40
- config = @helper.configure :different => 'is also set'
41
- assert_not_nil(config[:something])
42
- assert_not_nil(config[:different])
43
- end
44
-
45
- def test_error_with_not_called_configure
46
- assert_raise(RuntimeError) { @helper.lookup ANY_ASIN }
47
- end
48
-
49
- end
data/test/test_helper.rb DELETED
@@ -1,5 +0,0 @@
1
- $:.unshift File.join(File.dirname(__FILE__),'..','..','lib')
2
-
3
- require 'test/unit'
4
- require 'mocha'
5
- require 'asin'