asin 0.4.0.beta1 → 0.4.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/.document +2 -1
- data/CHANGELOG.rdoc +25 -0
- data/Gemfile.lock +15 -15
- data/README.rdoc +2 -0
- data/asin.gemspec +3 -3
- data/lib/asin.rb +22 -17
- data/lib/asin/cart.rb +3 -3
- data/lib/asin/configuration.rb +10 -5
- data/lib/asin/item.rb +24 -4
- data/lib/asin/version.rb +1 -1
- data/rakefile.rb +1 -1
- data/spec/cart_spec.rb +3 -3
- data/spec/search_spec.rb +29 -1
- data/spec/spec_helper.rb +1 -1
- metadata +9 -8
data/.document
CHANGED
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
== 0.4.0.beta2
|
2
|
+
|
3
|
+
* add configuration option for item/cart class
|
4
|
+
* add more functionality to item class
|
5
|
+
|
6
|
+
== 0.4.0.beta1
|
7
|
+
|
8
|
+
* added cart operations
|
9
|
+
* added yml configuration
|
10
|
+
|
11
|
+
== 0.3.0
|
12
|
+
|
13
|
+
* add search_keywords method
|
14
|
+
* open up search method to be more flexible
|
15
|
+
|
16
|
+
== 0.2.0
|
17
|
+
|
18
|
+
* rails initializer configuration
|
19
|
+
* rpsec for tests
|
20
|
+
|
21
|
+
== 0.1.0
|
22
|
+
|
23
|
+
* add logger
|
24
|
+
* use HTTPI as HTTP-adapter
|
25
|
+
* use bundler for dependencies
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
asin (0.4.0
|
4
|
+
asin (0.4.0)
|
5
5
|
crack (~> 0.1.8)
|
6
6
|
hashie (~> 1.0.0)
|
7
7
|
httpi (~> 0.9.2)
|
@@ -17,27 +17,27 @@ GEM
|
|
17
17
|
rspec (~> 2.0)
|
18
18
|
rspec-instafail (~> 0.1.4)
|
19
19
|
hashie (1.0.0)
|
20
|
-
httpclient (2.
|
21
|
-
httpi (0.9.
|
22
|
-
ntlm-http (>= 0.1.1)
|
20
|
+
httpclient (2.2.0.2)
|
21
|
+
httpi (0.9.4)
|
22
|
+
pyu-ntlm-http (>= 0.1.3.1)
|
23
23
|
rack
|
24
|
-
ntlm-http (0.1.1)
|
24
|
+
pyu-ntlm-http (0.1.3.1)
|
25
25
|
rack (1.2.2)
|
26
|
-
rspec (2.
|
27
|
-
rspec-core (~> 2.
|
28
|
-
rspec-expectations (~> 2.
|
29
|
-
rspec-mocks (~> 2.
|
30
|
-
rspec-core (2.
|
31
|
-
rspec-expectations (2.
|
26
|
+
rspec (2.6.0)
|
27
|
+
rspec-core (~> 2.6.0)
|
28
|
+
rspec-expectations (~> 2.6.0)
|
29
|
+
rspec-mocks (~> 2.6.0)
|
30
|
+
rspec-core (2.6.1)
|
31
|
+
rspec-expectations (2.6.0)
|
32
32
|
diff-lcs (~> 1.1.2)
|
33
33
|
rspec-instafail (0.1.7)
|
34
|
-
rspec-mocks (2.
|
34
|
+
rspec-mocks (2.6.0)
|
35
35
|
|
36
36
|
PLATFORMS
|
37
37
|
ruby
|
38
38
|
|
39
39
|
DEPENDENCIES
|
40
40
|
asin!
|
41
|
-
fuubar (~> 0.0.
|
42
|
-
httpclient (~> 2.
|
43
|
-
rspec (~> 2.
|
41
|
+
fuubar (~> 0.0.4)
|
42
|
+
httpclient (~> 2.2.0.2)
|
43
|
+
rspec (~> 2.6.0)
|
data/README.rdoc
CHANGED
@@ -26,6 +26,8 @@ Inline style configuration:
|
|
26
26
|
# or
|
27
27
|
client.configure :secret => 'your-secret', :key => 'your-key'
|
28
28
|
|
29
|
+
Have a look at ASIN::Configuration class for all the details.
|
30
|
+
|
29
31
|
== Usage
|
30
32
|
|
31
33
|
ASIN is designed as a module, so you can include it into any object you like:
|
data/asin.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_dependency('hashie', '~> 1.0.0')
|
24
24
|
s.add_dependency('httpi', '~> 0.9.2')
|
25
25
|
|
26
|
-
s.add_development_dependency('httpclient', '~> 2.
|
27
|
-
s.add_development_dependency('rspec', '~> 2.
|
28
|
-
s.add_development_dependency('fuubar', '~> 0.0.
|
26
|
+
s.add_development_dependency('httpclient', '~> 2.2.0.2')
|
27
|
+
s.add_development_dependency('rspec', '~> 2.6.0')
|
28
|
+
s.add_development_dependency('fuubar', '~> 0.0.4')
|
29
29
|
end
|
data/lib/asin.rb
CHANGED
@@ -32,7 +32,7 @@ require 'asin/configuration'
|
|
32
32
|
#
|
33
33
|
# == Search
|
34
34
|
#
|
35
|
-
# After configuring your environment you can call the +lookup+ method to retrieve an +
|
35
|
+
# After configuring your environment you can call the +lookup+ method to retrieve an +SimpleItem+ via the
|
36
36
|
# Amazon Standard Identification Number (ASIN):
|
37
37
|
#
|
38
38
|
# item = lookup '1430218150'
|
@@ -45,7 +45,7 @@ require 'asin/configuration'
|
|
45
45
|
# items.first.title
|
46
46
|
# => "Learn Objective-C on the Mac (Learn Series)"
|
47
47
|
#
|
48
|
-
# The +
|
48
|
+
# The +SimpleItem+ uses a Hashie::Mash as its internal data representation and you can get fetched data from it:
|
49
49
|
#
|
50
50
|
# item.raw.ItemAttributes.ListPrice.FormattedPrice
|
51
51
|
# => "$39.99"
|
@@ -117,7 +117,7 @@ module ASIN
|
|
117
117
|
|
118
118
|
# Performs an +ItemLookup+ REST call against the Amazon API.
|
119
119
|
#
|
120
|
-
# Expects an ASIN (Amazon Standard Identification Number) and returns an +
|
120
|
+
# Expects an ASIN (Amazon Standard Identification Number) and returns an +SimpleItem+:
|
121
121
|
#
|
122
122
|
# item = lookup '1430218150'
|
123
123
|
# item.title
|
@@ -129,14 +129,14 @@ module ASIN
|
|
129
129
|
#
|
130
130
|
# lookup(asin, :ResponseGroup => :Medium)
|
131
131
|
#
|
132
|
-
def lookup(asin, params={})
|
132
|
+
def lookup(asin, params={:ResponseGroup => :Medium})
|
133
133
|
response = call(params.merge(:Operation => :ItemLookup, :ItemId => asin))
|
134
|
-
|
134
|
+
handle_item(response['ItemLookupResponse']['Items']['Item'])
|
135
135
|
end
|
136
136
|
|
137
137
|
# Performs an +ItemSearch+ REST call against the Amazon API.
|
138
138
|
#
|
139
|
-
# Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +
|
139
|
+
# Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +SimpleItem+s:
|
140
140
|
#
|
141
141
|
# items = search_keywords 'Learn', 'Objective-C'
|
142
142
|
# items.first.title
|
@@ -151,14 +151,14 @@ module ASIN
|
|
151
151
|
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
152
152
|
#
|
153
153
|
def search_keywords(*keywords)
|
154
|
-
params = keywords.last.is_a?(Hash) ? keywords.pop : {:SearchIndex => :Books}
|
154
|
+
params = keywords.last.is_a?(Hash) ? keywords.pop : {:SearchIndex => :Books, :ResponseGroup => :Medium}
|
155
155
|
response = call(params.merge(:Operation => :ItemSearch, :Keywords => keywords.join(' ')))
|
156
|
-
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item|
|
156
|
+
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
157
157
|
end
|
158
158
|
|
159
159
|
# Performs an +ItemSearch+ REST call against the Amazon API.
|
160
160
|
#
|
161
|
-
# Expects a Hash of search params where and returns a list of +
|
161
|
+
# Expects a Hash of search params where and returns a list of +SimpleItem+s:
|
162
162
|
#
|
163
163
|
# items = search :SearchIndex => :Music
|
164
164
|
#
|
@@ -170,14 +170,14 @@ module ASIN
|
|
170
170
|
#
|
171
171
|
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
172
172
|
#
|
173
|
-
def search(params={:SearchIndex => :Books})
|
173
|
+
def search(params={:SearchIndex => :Books, :ResponseGroup => :Medium})
|
174
174
|
response = call(params.merge(:Operation => :ItemSearch))
|
175
|
-
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item|
|
175
|
+
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
176
176
|
end
|
177
177
|
|
178
178
|
# Performs an +CartCreate+ REST call against the Amazon API.
|
179
179
|
#
|
180
|
-
# Expects one ore more
|
180
|
+
# Expects one ore more item-hashes and returns a +SimpleCart+:
|
181
181
|
#
|
182
182
|
# cart = create_cart({:asin => '1430218150', :quantity => 1})
|
183
183
|
#
|
@@ -195,7 +195,7 @@ module ASIN
|
|
195
195
|
|
196
196
|
# Performs an +CartGet+ REST call against the Amazon API.
|
197
197
|
#
|
198
|
-
# Expects the CartId and the HMAC to identify the returning +
|
198
|
+
# Expects the CartId and the HMAC to identify the returning +SimpleCart+:
|
199
199
|
#
|
200
200
|
# cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
|
201
201
|
#
|
@@ -205,7 +205,7 @@ module ASIN
|
|
205
205
|
|
206
206
|
# Performs an +CartAdd+ REST call against the Amazon API.
|
207
207
|
#
|
208
|
-
# Expects a +
|
208
|
+
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes and returns an updated +SimpleCart+:
|
209
209
|
#
|
210
210
|
# cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
|
211
211
|
#
|
@@ -223,7 +223,7 @@ module ASIN
|
|
223
223
|
|
224
224
|
# Performs an +CartModify+ REST call against the Amazon API.
|
225
225
|
#
|
226
|
-
# Expects a +
|
226
|
+
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated +SimpleCart+:
|
227
227
|
#
|
228
228
|
# cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
229
229
|
#
|
@@ -241,7 +241,7 @@ module ASIN
|
|
241
241
|
|
242
242
|
# Performs an +CartClear+ REST call against the Amazon API.
|
243
243
|
#
|
244
|
-
# Expects a +
|
244
|
+
# Expects a +SimpleCart+ created with +create_cart+ and returns an empty +SimpleCart+:
|
245
245
|
#
|
246
246
|
# cart = clear_cart(cart)
|
247
247
|
#
|
@@ -250,6 +250,10 @@ module ASIN
|
|
250
250
|
end
|
251
251
|
|
252
252
|
private
|
253
|
+
|
254
|
+
def handle_item(item)
|
255
|
+
Configuration.item_type.is_a?(Class) ? Configuration.item_type.new(item) : item
|
256
|
+
end
|
253
257
|
|
254
258
|
def create_item_params(items)
|
255
259
|
keyword_mappings = {
|
@@ -271,7 +275,8 @@ module ASIN
|
|
271
275
|
|
272
276
|
def cart(operation, params={})
|
273
277
|
response = call(params.merge(:Operation => operation))
|
274
|
-
|
278
|
+
cart = response["#{operation}Response"]['Cart']
|
279
|
+
Configuration.cart_type.is_a?(Class) ? Configuration.cart_type.new(cart) : cart
|
275
280
|
end
|
276
281
|
|
277
282
|
|
data/lib/asin/cart.rb
CHANGED
@@ -2,13 +2,13 @@ require 'hashie'
|
|
2
2
|
|
3
3
|
module ASIN
|
4
4
|
|
5
|
-
# =
|
5
|
+
# = SimpleCart
|
6
6
|
#
|
7
|
-
# The +
|
7
|
+
# The +SimpleCart+ class is a wrapper for the Amazon XML-REST-Response.
|
8
8
|
#
|
9
9
|
# A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
|
10
10
|
#
|
11
|
-
class
|
11
|
+
class SimpleCart
|
12
12
|
|
13
13
|
attr_reader :raw
|
14
14
|
|
data/lib/asin/configuration.rb
CHANGED
@@ -5,6 +5,7 @@ module ASIN
|
|
5
5
|
class << self
|
6
6
|
|
7
7
|
attr_accessor :secret, :key, :host, :logger
|
8
|
+
attr_accessor :item_type, :cart_type
|
8
9
|
|
9
10
|
# Rails initializer configuration.
|
10
11
|
#
|
@@ -33,6 +34,8 @@ module ASIN
|
|
33
34
|
# [key] the API access key
|
34
35
|
# [host] the host, which defaults to 'webservices.amazon.com'
|
35
36
|
# [logger] a different logger than logging to STDERR (nil for no logging)
|
37
|
+
# [item_type] a different class for SimpleItem, use :raw for a plain mash
|
38
|
+
# [cart_type] a different class for SimpleCart, use :raw for a plain mash
|
36
39
|
#
|
37
40
|
def configure(options={})
|
38
41
|
init_config
|
@@ -65,11 +68,13 @@ module ASIN
|
|
65
68
|
|
66
69
|
def init_config(force=false)
|
67
70
|
return if @init && !force
|
68
|
-
@init
|
69
|
-
@secret
|
70
|
-
@key
|
71
|
-
@host
|
72
|
-
@logger
|
71
|
+
@init = true
|
72
|
+
@secret = ''
|
73
|
+
@key = ''
|
74
|
+
@host = 'webservices.amazon.com'
|
75
|
+
@logger = Logger.new(STDERR)
|
76
|
+
@item_type = SimpleItem
|
77
|
+
@cart_type = SimpleCart
|
73
78
|
end
|
74
79
|
end
|
75
80
|
end
|
data/lib/asin/item.rb
CHANGED
@@ -2,13 +2,13 @@ require 'hashie'
|
|
2
2
|
|
3
3
|
module ASIN
|
4
4
|
|
5
|
-
# =
|
5
|
+
# =SimpleItem
|
6
6
|
#
|
7
|
-
# The +
|
7
|
+
# The +SimpleItem+ class is a wrapper for the Amazon XML-REST-Response.
|
8
8
|
#
|
9
9
|
# A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
|
10
10
|
#
|
11
|
-
class
|
11
|
+
class SimpleItem
|
12
12
|
|
13
13
|
attr_reader :raw
|
14
14
|
|
@@ -16,8 +16,28 @@ module ASIN
|
|
16
16
|
@raw = Hashie::Mash.new(hash)
|
17
17
|
end
|
18
18
|
|
19
|
+
def asin
|
20
|
+
@raw.ASIN
|
21
|
+
end
|
22
|
+
|
19
23
|
def title
|
20
|
-
@raw.ItemAttributes
|
24
|
+
@raw.ItemAttributes!.Title
|
25
|
+
end
|
26
|
+
|
27
|
+
def amount
|
28
|
+
@raw.ItemAttributes!.ListPrice!.Amount.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def details_url
|
32
|
+
@raw.DetailPageURL
|
33
|
+
end
|
34
|
+
|
35
|
+
def review
|
36
|
+
@raw.EditorialReviews!.EditorialReview!.Content
|
37
|
+
end
|
38
|
+
|
39
|
+
def image_url
|
40
|
+
@raw.LargeImage!.URL
|
21
41
|
end
|
22
42
|
end
|
23
43
|
|
data/lib/asin/version.rb
CHANGED
data/rakefile.rb
CHANGED
@@ -10,7 +10,7 @@ RSpec::Core::RakeTask.new do |t|
|
|
10
10
|
end
|
11
11
|
|
12
12
|
Rake::RDocTask.new(:rdoc_dev) do |rd|
|
13
|
-
rd.rdoc_files.include(
|
13
|
+
rd.rdoc_files.include(File.readlines('.document').map(&:strip))
|
14
14
|
rd.options + ['-a', '--inline-source', '--charset=UTF-8']
|
15
15
|
end
|
16
16
|
|
data/spec/cart_spec.rb
CHANGED
@@ -62,7 +62,7 @@ module ASIN
|
|
62
62
|
|
63
63
|
end
|
64
64
|
|
65
|
-
context
|
65
|
+
context SimpleCart do
|
66
66
|
|
67
67
|
before do
|
68
68
|
@helper.configure :secret => @secret, :key => @key
|
@@ -139,7 +139,7 @@ module ASIN
|
|
139
139
|
end
|
140
140
|
|
141
141
|
it "should handle response data" do
|
142
|
-
cart =
|
142
|
+
cart = SimpleCart.new(@two_items)
|
143
143
|
cart.valid?.should be(true)
|
144
144
|
cart.cart_id.should eql('186-8702292-9782208')
|
145
145
|
cart.hmac.should eql('Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=')
|
@@ -149,7 +149,7 @@ module ASIN
|
|
149
149
|
end
|
150
150
|
|
151
151
|
it "should handle one item" do
|
152
|
-
cart =
|
152
|
+
cart = SimpleCart.new(@two_items)
|
153
153
|
cart.items.first.CartItemId eql('U3G241HVLLB8N6')
|
154
154
|
end
|
155
155
|
|
data/spec/search_spec.rb
CHANGED
@@ -65,6 +65,34 @@ module ASIN
|
|
65
65
|
item.title.should =~ /Learn Objective/
|
66
66
|
end
|
67
67
|
|
68
|
+
it "should have metadata" do
|
69
|
+
item = @helper.lookup(ANY_ASIN, :ResponseGroup => :Medium)
|
70
|
+
item.asin.should eql(ANY_ASIN)
|
71
|
+
item.title.should =~ /Learn Objective/
|
72
|
+
item.amount.should eql(3999)
|
73
|
+
item.details_url.should eql('http://www.amazon.com/Learn-Objective-C-Mac-Mark-Dalrymple/dp/1430218150%3FSubscriptionId%3DAKIAJFA5X7RTOKFNPVZQ%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1430218150')
|
74
|
+
item.image_url.should eql('http://ecx.images-amazon.com/images/I/41kq5bDvnUL.jpg')
|
75
|
+
item.review.should =~ /Learn Objective-C on the Macintosh/
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return a custom item class" do
|
79
|
+
module TEST
|
80
|
+
class TestItem
|
81
|
+
attr_accessor :testo
|
82
|
+
def initialize(hash)
|
83
|
+
@testo = hash
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
@helper.configure :item_type => TEST::TestItem
|
88
|
+
@helper.lookup(ANY_ASIN).testo.should_not be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return a raw value" do
|
92
|
+
@helper.configure :item_type => :raw
|
93
|
+
@helper.lookup(ANY_ASIN)['ItemAttributes']['Title'].should_not be_nil
|
94
|
+
end
|
95
|
+
|
68
96
|
it "should search_keywords a book with fulltext" do
|
69
97
|
items = @helper.search_keywords 'Learn', 'Objective-C'
|
70
98
|
items.should have(10).things
|
@@ -74,7 +102,7 @@ module ASIN
|
|
74
102
|
|
75
103
|
it "should search_keywords never mind music" do
|
76
104
|
items = @helper.search_keywords 'nirvana', 'never mind', :SearchIndex => :Music
|
77
|
-
items.should have(
|
105
|
+
items.should have(8).things
|
78
106
|
|
79
107
|
items.first.title.should =~ /Nevermind/
|
80
108
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 0.4.0
|
4
|
+
prerelease:
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- "Peter Schr\xC3\xB6der"
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-05-20 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
requirements:
|
55
55
|
- - ~>
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 2.
|
57
|
+
version: 2.2.0.2
|
58
58
|
type: :development
|
59
59
|
version_requirements: *id004
|
60
60
|
- !ruby/object:Gem::Dependency
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 2.
|
68
|
+
version: 2.6.0
|
69
69
|
type: :development
|
70
70
|
version_requirements: *id005
|
71
71
|
- !ruby/object:Gem::Dependency
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
requirements:
|
77
77
|
- - ~>
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: 0.0.
|
79
|
+
version: 0.0.4
|
80
80
|
type: :development
|
81
81
|
version_requirements: *id006
|
82
82
|
description: Amazon Simple INterface.
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- .document
|
93
93
|
- .gitignore
|
94
94
|
- .rvmrc
|
95
|
+
- CHANGELOG.rdoc
|
95
96
|
- Gemfile
|
96
97
|
- Gemfile.lock
|
97
98
|
- README.rdoc
|
@@ -124,9 +125,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
124
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
126
|
none: false
|
126
127
|
requirements:
|
127
|
-
- - "
|
128
|
+
- - ">="
|
128
129
|
- !ruby/object:Gem::Version
|
129
|
-
version:
|
130
|
+
version: "0"
|
130
131
|
requirements: []
|
131
132
|
|
132
133
|
rubyforge_project: asin
|