sevennet-api 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +111 -0
- data/Rakefile +1 -0
- data/lib/sevennet/api.rb +329 -0
- data/lib/sevennet/api/version.rb +5 -0
- data/sevennet-api.gemspec +26 -0
- data/spec/sevennet/api_spec.rb +484 -0
- data/spec/spec_helper.rb +21 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: feec2c6c92b4918ac8868c0fc2dcb091e9e4059f
|
4
|
+
data.tar.gz: 45af5f721d89164fa394017b1373afec3125af15
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b2e9b4ac974db660e07fcd66a40897279f829515b488617a66654c4bee025b874e7b6a3158f6197aec175d84f2891599da3f0a4bbe593f0a04ae5cf7b11de653
|
7
|
+
data.tar.gz: cb1c5348382a40e89b295e80db76a30eefce1727c14e561eb57241c9b1b29e9fc79fa27631e490cd7c621fd70150edba9022f87913d988bca3359e58b5f38a1b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 shoprev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# Sevennet::Api
|
2
|
+
|
3
|
+
Generic 7netshopping Ruby API using Nokogiri. Uses Response and Element wrapper classes for easy access to the REST API XML output.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'sevennet-api'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install sevennet-api
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
require 'sevennet/api'
|
22
|
+
|
23
|
+
Sevennet::Api.configure do |options|
|
24
|
+
options[:ApiUserId] = 'your api user id'
|
25
|
+
options[:APISecretKey] = 'your api secret key'
|
26
|
+
end
|
27
|
+
|
28
|
+
# GetShoppingCategory
|
29
|
+
res = Sevennet::Api.get_shopping_category('') # root category
|
30
|
+
res = Sevennet::Api.get_shopping_category('books') # books category
|
31
|
+
res.categories.each do |category|
|
32
|
+
children = category.get('ChildCategory')
|
33
|
+
children.each do |child|
|
34
|
+
code = child.get('CategoryCode')
|
35
|
+
...
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# SearchProduct
|
40
|
+
res = Sevennet::Api.search_product('ruby', {:ShoppingSortOrder => 'reviews'}) # keyword match
|
41
|
+
res = Sevennet::Api.search_product('', {:CategoryCode = 'books'}) # category match
|
42
|
+
res = Sevennet::Api.search_product('ruby', {:CategoryCode = 'books'}) # keyword and category match
|
43
|
+
res.products.each do |product|
|
44
|
+
code = product.get('ProductCode')
|
45
|
+
...
|
46
|
+
end
|
47
|
+
|
48
|
+
# SearchRanking
|
49
|
+
res = Sevennet::Api.search_ranking('books', {:GenerationCond => 10, :SexCond => 'male'})
|
50
|
+
res.products.each do |product|
|
51
|
+
code = product.get('ProductCode')
|
52
|
+
...
|
53
|
+
end
|
54
|
+
|
55
|
+
# SearchProductReview
|
56
|
+
res = Sevennet::Api.search_product_review('2110150300') # ProductCode
|
57
|
+
res = Sevennet::Api.search_product_review('21-101-503-00',:type => 'ProductStandardCode') # ISBN JAN etc
|
58
|
+
res.reviews.each do |review|
|
59
|
+
title = review.get('CommentTitle')
|
60
|
+
...
|
61
|
+
end
|
62
|
+
|
63
|
+
# GetSpcCategory
|
64
|
+
res = Sevennet::Api.get_spc_category('') # root category
|
65
|
+
res = Sevennet::Api.get_spc_category('home') # home category
|
66
|
+
res.categories.each do |category|
|
67
|
+
children = category.get('ChildCategory')
|
68
|
+
children.each do |child|
|
69
|
+
code = child.get('CategoryCode')
|
70
|
+
...
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# SearchSpcShop
|
75
|
+
res = Sevennet::Api.search_spc_shop('', {:SpcSortOrder => 'name') # all
|
76
|
+
res = Sevennet::Api.search_spc_shop('ruby', {:SpcSortOrder => 'name') # keyword match
|
77
|
+
res.shops.each do |shop|
|
78
|
+
id = shop.get('SpcShopId')
|
79
|
+
...
|
80
|
+
end
|
81
|
+
|
82
|
+
# some common response object methods
|
83
|
+
res.has_error? # return true if there is an error
|
84
|
+
res.error # return error message if there is any
|
85
|
+
res.total_amount # return total results
|
86
|
+
|
87
|
+
# Extend Sevennet::Api, replace 'other_operation' with the appropriate name
|
88
|
+
module Sevennet
|
89
|
+
class Api
|
90
|
+
def self.other_operation(item_id, opts={})
|
91
|
+
opts[:operation] = '[other valid operation supported by 7netshopping API]'
|
92
|
+
|
93
|
+
# setting default option value
|
94
|
+
opts[:item_id] = item_id
|
95
|
+
|
96
|
+
self.send_request(opts)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
Sevennet::Api.other_operation('[item_id]', :param1 => 'abc', :param2 => 'xyz')
|
102
|
+
|
103
|
+
Refer to 7netshopping API documentation for more information on other valid operations, request parameters and the XML response output: http://www.7netshopping.jp/
|
104
|
+
|
105
|
+
## Contributing
|
106
|
+
|
107
|
+
1. Fork it
|
108
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
109
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
110
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
111
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/sevennet/api.rb
ADDED
@@ -0,0 +1,329 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'net/http'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'cgi'
|
5
|
+
require 'base64'
|
6
|
+
require 'openssl'
|
7
|
+
|
8
|
+
module Sevennet
|
9
|
+
class RequestError < StandardError; end
|
10
|
+
|
11
|
+
class Api
|
12
|
+
SERVICE_URL = 'http://api.7netshopping.jp/ws/affiliate/rest'
|
13
|
+
|
14
|
+
@@options = {
|
15
|
+
:Version => "2010-08-01",
|
16
|
+
:ResponseFormat => "XML"
|
17
|
+
}
|
18
|
+
|
19
|
+
# Default search options
|
20
|
+
def self.options
|
21
|
+
@@options
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set default search options
|
25
|
+
def self.options=(opts)
|
26
|
+
@@options = opts
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.configure(&proc)
|
30
|
+
raise ArgumentError, "Block is required." unless block_given?
|
31
|
+
yield @@options
|
32
|
+
end
|
33
|
+
|
34
|
+
# Search spc categories by category code.
|
35
|
+
def self.get_spc_category(category_code, opts = {})
|
36
|
+
opts[:operation] = 'GetSpcCategory'
|
37
|
+
opts[:CategoryCode] = category_code
|
38
|
+
|
39
|
+
self.send_request(opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Search spc shops with search terms.
|
43
|
+
def self.search_spc_shop(terms, opts = {})
|
44
|
+
opts[:operation] = 'SearchSpcShop'
|
45
|
+
opts[:KeywordIn] = CGI.escape(terms.to_s)
|
46
|
+
|
47
|
+
self.send_request(opts)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Search categories by category code.
|
51
|
+
def self.get_shopping_category(category_code, opts = {})
|
52
|
+
opts[:operation] = 'GetShoppingCategory'
|
53
|
+
opts[:CategoryCode] = category_code
|
54
|
+
|
55
|
+
self.send_request(opts)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Search products with search terms.
|
59
|
+
def self.search_product(terms, opts = {})
|
60
|
+
if terms.to_s.empty? && (options[:CategoryCode].to_s.empty? && opts[:CategoryCode].to_s.empty?)
|
61
|
+
raise ArgumentError, "CategoryCode or KeywordIn is required."
|
62
|
+
end
|
63
|
+
|
64
|
+
opts[:operation] = 'SearchProduct'
|
65
|
+
opts[:KeywordIn] = CGI.escape(terms.to_s)
|
66
|
+
|
67
|
+
self.send_request(opts)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Search products by category code.
|
71
|
+
def self.search_ranking(category_code, opts = {})
|
72
|
+
opts[:operation] = 'SearchRanking'
|
73
|
+
opts[:CategoryCode] = category_code
|
74
|
+
|
75
|
+
raise ArgumentError, "CategoryCode is required." if category_code.to_s.empty?
|
76
|
+
|
77
|
+
self.send_request(opts)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Search a product reviews with product code.
|
81
|
+
# For other search type other than keywords, please specify :type => 'ProductStandardCode'.
|
82
|
+
def self.search_product_review(product_code, opts = {})
|
83
|
+
opts[:operation] = 'SearchProductReview'
|
84
|
+
|
85
|
+
type = (opts.delete(:type) || options.delete(:type))
|
86
|
+
if type
|
87
|
+
opts[type.to_sym] = product_code
|
88
|
+
else
|
89
|
+
opts[:ProductCode] = product_code
|
90
|
+
end
|
91
|
+
|
92
|
+
raise ArgumentError, "ProductCode is required." if product_code.to_s.empty?
|
93
|
+
|
94
|
+
self.send_request(opts)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Search products by contents.
|
98
|
+
def self.search_content_match_product(content, opts = {})
|
99
|
+
|
100
|
+
raise ArgumentError, "Content is required." if content.to_s.empty?
|
101
|
+
|
102
|
+
opts[:operation] = 'SearchContentMatchProduct'
|
103
|
+
opts[:Content] = CGI.escape(content)
|
104
|
+
|
105
|
+
self.send_request(opts)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Search products by category code and contents.
|
109
|
+
def self.search_content_match_ranking(category_code, content, opts = {})
|
110
|
+
|
111
|
+
raise ArgumentError, "TopCategoryCode and Content is required." if content.to_s.empty? || category_code.to_s.empty?
|
112
|
+
|
113
|
+
opts[:operation] = 'SearchContentMatchRanking'
|
114
|
+
opts[:Content] = CGI.escape(content)
|
115
|
+
opts[:TopCategoryCode] = category_code
|
116
|
+
|
117
|
+
|
118
|
+
self.send_request(opts)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Generic send request to API REST service. You have to specify the :operation parameter.
|
122
|
+
def self.send_request(opts)
|
123
|
+
opts = self.options.merge(opts) if self.options
|
124
|
+
|
125
|
+
# Include other required options
|
126
|
+
opts[:Timestamp] = Time.now.strftime('%Y-%m-%dT%XZ')
|
127
|
+
|
128
|
+
request_url = prepare_url(opts)
|
129
|
+
|
130
|
+
res = Net::HTTP.get_response(URI::parse(request_url))
|
131
|
+
unless res.kind_of? Net::HTTPSuccess
|
132
|
+
raise Sevennet::RequestError, "HTTP Response: #{res.code} #{res.message}"
|
133
|
+
end
|
134
|
+
Response.new(res.body)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Response object returned after a REST call to sevennet api.
|
138
|
+
class Response
|
139
|
+
|
140
|
+
# XML input is in string format
|
141
|
+
def initialize(xml)
|
142
|
+
@doc = Nokogiri::XML(xml, nil, 'UTF-8')
|
143
|
+
@doc.remove_namespaces!
|
144
|
+
end
|
145
|
+
|
146
|
+
# Return Nokogiri::XML::Document object.
|
147
|
+
def doc
|
148
|
+
@doc
|
149
|
+
end
|
150
|
+
|
151
|
+
# Return true if response has an error.
|
152
|
+
def has_error?
|
153
|
+
!(error.nil? || error.empty?)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Return error message.
|
157
|
+
def error
|
158
|
+
Element.get(@doc, "//ApiErrorMessage")
|
159
|
+
end
|
160
|
+
|
161
|
+
# Return error code
|
162
|
+
def error_code
|
163
|
+
Element.get(@doc, "//ApiErrorStatus")
|
164
|
+
end
|
165
|
+
|
166
|
+
# Return an array of Sevennet::Element category objects.
|
167
|
+
def categories
|
168
|
+
@categories ||= (@doc/"Category").collect { |it| Element.new(it) }
|
169
|
+
end
|
170
|
+
|
171
|
+
# Return an array of Sevennet::Element shop objects.
|
172
|
+
def shops
|
173
|
+
@shops ||= (@doc/"SpcShop").collect { |it| Element.new(it) }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Return an array of Sevennet::Element product objects.
|
177
|
+
def products
|
178
|
+
@products ||= (@doc/"Product").collect { |it| Element.new(it) }
|
179
|
+
end
|
180
|
+
|
181
|
+
# Return an array of Sevennet::Element review objects.
|
182
|
+
def reviews
|
183
|
+
@reviews ||= (@doc/"ProductReview").collect { |it| Element.new(it) }
|
184
|
+
end
|
185
|
+
|
186
|
+
# Return total results.
|
187
|
+
def total_amount
|
188
|
+
@total_amount ||= Element.get(@doc, "//TotalAmount").to_i
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
def self.prepare_url(opts)
|
194
|
+
secret_key = opts.delete(:APISecretKey)
|
195
|
+
operation = opts.delete(:operation)
|
196
|
+
request_url = "#{SERVICE_URL}/#{operation}"
|
197
|
+
|
198
|
+
qs = []
|
199
|
+
|
200
|
+
opts = opts.collect do |a,b|
|
201
|
+
[a.to_s, b.to_s]
|
202
|
+
end
|
203
|
+
|
204
|
+
opts = opts.sort do |c,d|
|
205
|
+
c[0].to_s <=> d[0].to_s
|
206
|
+
end
|
207
|
+
|
208
|
+
opts.each do |e|
|
209
|
+
next if e[1].empty? || e[1].nil?
|
210
|
+
qs << "#{e[0]}=#{e[1]}"
|
211
|
+
end
|
212
|
+
|
213
|
+
request_to_sign ="GET|#{request_url}|#{qs.join('|')}"
|
214
|
+
signature = "&Signature=#{sign_request(request_to_sign, secret_key)}"
|
215
|
+
"#{request_url}?#{qs.join('&')}#{signature}"
|
216
|
+
end
|
217
|
+
|
218
|
+
def self.sign_request(url, key)
|
219
|
+
signature = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, key, CGI.escape(url))
|
220
|
+
signature = Base64.encode64(signature).chomp
|
221
|
+
signature
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Internal wrapper class to provide convenient method to access Nokogiri element value.
|
226
|
+
class Element
|
227
|
+
class << self
|
228
|
+
# Return the text value of an element.
|
229
|
+
def get(element, path='.')
|
230
|
+
return unless element
|
231
|
+
result = element.at_xpath(path)
|
232
|
+
result = result.inner_html if result
|
233
|
+
result
|
234
|
+
end
|
235
|
+
|
236
|
+
# Return an unescaped text value of an element.
|
237
|
+
def get_unescaped(element, path='.')
|
238
|
+
result = self.get(element, path)
|
239
|
+
CGI.unescape(result) if result
|
240
|
+
end
|
241
|
+
|
242
|
+
# Return an array of values based on the given path.
|
243
|
+
def get_array(element, path='.')
|
244
|
+
return unless element
|
245
|
+
|
246
|
+
result = element/path
|
247
|
+
if (result.is_a? Nokogiri::XML::NodeSet) || (result.is_a? Array)
|
248
|
+
result.collect { |item| self.get(item) }
|
249
|
+
else
|
250
|
+
[self.get(result)]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Return child element text values of the given path.
|
255
|
+
def get_hash(element, path='.')
|
256
|
+
return unless element
|
257
|
+
|
258
|
+
result = element.at_xpath(path)
|
259
|
+
if result
|
260
|
+
hash = {}
|
261
|
+
result = result.children
|
262
|
+
result.each do |item|
|
263
|
+
hash[item.name] = item.inner_html
|
264
|
+
end
|
265
|
+
hash
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Pass Nokogiri::XML::Element object
|
271
|
+
def initialize(element)
|
272
|
+
@element = element
|
273
|
+
end
|
274
|
+
|
275
|
+
# Returns Nokogiri::XML::Element object
|
276
|
+
def elem
|
277
|
+
@element
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns a Nokogiri::XML::NodeSet of elements matching the given path. Example: element/"author".
|
281
|
+
def /(path)
|
282
|
+
elements = @element/path
|
283
|
+
return nil if elements.size == 0
|
284
|
+
elements
|
285
|
+
end
|
286
|
+
|
287
|
+
# Return an array of Sevennet::Element matching the given path
|
288
|
+
def get_elements(path)
|
289
|
+
elements = self./(path)
|
290
|
+
return unless elements
|
291
|
+
elements = elements.map{|element| Element.new(element)}
|
292
|
+
end
|
293
|
+
|
294
|
+
# Similar with search_and_convert but always return first element if more than one elements found
|
295
|
+
def get_element(path)
|
296
|
+
elements = get_elements(path)
|
297
|
+
elements[0] if elements
|
298
|
+
end
|
299
|
+
|
300
|
+
# Get the text value of the given path, leave empty to retrieve current element value.
|
301
|
+
def get(path='.')
|
302
|
+
Element.get(@element, path)
|
303
|
+
end
|
304
|
+
|
305
|
+
# Get the unescaped HTML text of the given path.
|
306
|
+
def get_unescaped(path='.')
|
307
|
+
Element.get_unescaped(@element, path)
|
308
|
+
end
|
309
|
+
|
310
|
+
# Get the array values of the given path.
|
311
|
+
def get_array(path='.')
|
312
|
+
Element.get_array(@element, path)
|
313
|
+
end
|
314
|
+
|
315
|
+
# Get the children element text values in hash format with the element names as the hash keys.
|
316
|
+
def get_hash(path='.')
|
317
|
+
Element.get_hash(@element, path)
|
318
|
+
end
|
319
|
+
|
320
|
+
def attributes
|
321
|
+
return unless self.elem
|
322
|
+
self.elem.attributes
|
323
|
+
end
|
324
|
+
|
325
|
+
def to_s
|
326
|
+
elem.to_s if elem
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sevennet/api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sevennet-api"
|
8
|
+
spec.version = Sevennet::Api::VERSION
|
9
|
+
spec.authors = ["shoprev"]
|
10
|
+
spec.email = ["admin@shoprev.net"]
|
11
|
+
spec.description = %q{Generic Ruby 7netshopping API}
|
12
|
+
spec.summary = %q{Generic Ruby 7netshopping API}
|
13
|
+
spec.homepage = "https://github.com/shoprev/sevennet-api"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "vcr"
|
25
|
+
spec.add_runtime_dependency "nokogiri"
|
26
|
+
end
|
@@ -0,0 +1,484 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
3
|
+
|
4
|
+
share_examples_for 'found products search keyword or options' do
|
5
|
+
subject { response }
|
6
|
+
its(:total_amount) { should > 0 }
|
7
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
8
|
+
it { should_not be_has_error }
|
9
|
+
context 'products.first' do
|
10
|
+
subject { response.products.first/"ProductCode" }
|
11
|
+
it { should_not be_empty }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
share_examples_for 'not found products search keyword or options' do
|
16
|
+
subject { response }
|
17
|
+
its(:total_amount) { should == 0 }
|
18
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
19
|
+
its('products') { should == [] }
|
20
|
+
it { should_not be_has_error }
|
21
|
+
end
|
22
|
+
|
23
|
+
share_examples_for 'category common test' do
|
24
|
+
subject { response }
|
25
|
+
its(:total_amount) { should == 0 }
|
26
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
27
|
+
its('categories.first') { should be_kind_of Sevennet::Element }
|
28
|
+
it { should_not be_has_error }
|
29
|
+
context 'child category' do
|
30
|
+
subject { response.categories.first/"ChildCategory" }
|
31
|
+
it { should_not be_empty }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "Sevennet::Api.search_content_match_ranking" do
|
36
|
+
let(:response) {
|
37
|
+
VCR.use_cassette('search_content_match_ranking_' + top_category_code.to_s + '_' + content.to_s + '_' + opts.to_s) do
|
38
|
+
Sevennet::Api.search_content_match_ranking(top_category_code,content)
|
39
|
+
end
|
40
|
+
}
|
41
|
+
let(:options) {
|
42
|
+
Sevennet::Api.configure do |options|
|
43
|
+
options[:StartIndex] = 1
|
44
|
+
options[:ResultAmount] = 5
|
45
|
+
end
|
46
|
+
}
|
47
|
+
let(:no_option) {
|
48
|
+
Sevennet::Api.configure do |options|
|
49
|
+
options[:StartIndex] = nil
|
50
|
+
options[:ResultAmount] = nil
|
51
|
+
end
|
52
|
+
}
|
53
|
+
|
54
|
+
# context 'search keyword and options' do
|
55
|
+
# let(:top_category_code) { 'magazine' }
|
56
|
+
# let(:content) { 'focus' }
|
57
|
+
# let(:opts) { options }
|
58
|
+
# it_should_behave_like 'found products search keyword or options'
|
59
|
+
# end
|
60
|
+
|
61
|
+
# context 'search keyword without options' do
|
62
|
+
# let(:top_category_code) { 'magazine' }
|
63
|
+
# let(:content) { 'focus' }
|
64
|
+
# let(:opts) { no_option }
|
65
|
+
# it_should_behave_like 'found products search keyword or options'
|
66
|
+
# end
|
67
|
+
|
68
|
+
context 'search options without keyword' do
|
69
|
+
let(:top_category_code) { 'magazine' }
|
70
|
+
let(:content) { nil }
|
71
|
+
let(:opts) { options }
|
72
|
+
it { lambda{ response }.should raise_error( ArgumentError, "TopCategoryCode and Content is required.") }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'search without keyword and options' do
|
76
|
+
let(:top_category_code) { 'magazine' }
|
77
|
+
let(:content) { nil }
|
78
|
+
let(:opts) { no_option }
|
79
|
+
it { lambda{ response }.should raise_error( ArgumentError, "TopCategoryCode and Content is required.") }
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'not found search keyword and options' do
|
83
|
+
let(:top_category_code) { 'magazine' }
|
84
|
+
let(:content) { 'focus friday' }
|
85
|
+
let(:opts) { options }
|
86
|
+
it_should_behave_like 'not found products search keyword or options'
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'not found search keyword without options' do
|
90
|
+
let(:top_category_code) { 'magazine' }
|
91
|
+
let(:content) { 'focus friday' }
|
92
|
+
let(:opts) { no_option }
|
93
|
+
it_should_behave_like 'not found products search keyword or options'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "Sevennet::Api.search_content_match_product" do
|
98
|
+
let(:response) {
|
99
|
+
VCR.use_cassette('search_content_match_product_' + content.to_s + '_' + opts.to_s) do
|
100
|
+
Sevennet::Api.search_content_match_product(content)
|
101
|
+
end
|
102
|
+
}
|
103
|
+
let(:options) {
|
104
|
+
Sevennet::Api.configure do |options|
|
105
|
+
options[:StartIndex] = 1
|
106
|
+
options[:ResultAmount] = 5
|
107
|
+
end
|
108
|
+
}
|
109
|
+
let(:no_option) {
|
110
|
+
Sevennet::Api.configure do |options|
|
111
|
+
options[:StartIndex] = nil
|
112
|
+
options[:ResultAmount] = nil
|
113
|
+
end
|
114
|
+
}
|
115
|
+
|
116
|
+
context 'search keyword and options' do
|
117
|
+
let(:content) { 'ruby perl javascript' }
|
118
|
+
let(:opts) { options }
|
119
|
+
it_should_behave_like 'found products search keyword or options'
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'search keyword without options' do
|
123
|
+
let(:content) { 'ruby perl javascript' }
|
124
|
+
let(:opts) { no_option }
|
125
|
+
it_should_behave_like 'found products search keyword or options'
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'search options without keyword' do
|
129
|
+
let(:content) { nil }
|
130
|
+
let(:opts) { options }
|
131
|
+
it { lambda{ response }.should raise_error( ArgumentError, "Content is required.") }
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'search without keyword and options' do
|
135
|
+
let(:content) { nil }
|
136
|
+
let(:opts) { no_option }
|
137
|
+
it { lambda{ response }.should raise_error( ArgumentError, "Content is required.") }
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'not found search keyword and options' do
|
141
|
+
let(:content) { 'titanium coffeescript' }
|
142
|
+
let(:opts) { options }
|
143
|
+
it_should_behave_like 'not found products search keyword or options'
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'not found search keyword without options' do
|
147
|
+
let(:content) { 'titanium coffeescript' }
|
148
|
+
let(:opts) { no_option }
|
149
|
+
it_should_behave_like 'not found products search keyword or options'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "Sevennet::Api.search_product_review" do
|
154
|
+
let(:response) {
|
155
|
+
VCR.use_cassette('search_product_review_' + product_code.to_s + '_' + opts.to_s) do
|
156
|
+
Sevennet::Api.search_product_review(product_code)
|
157
|
+
end
|
158
|
+
}
|
159
|
+
let(:options) {
|
160
|
+
Sevennet::Api.configure do |options|
|
161
|
+
options[:StartIndex] = 1
|
162
|
+
options[:ResultAmount] = 5
|
163
|
+
options[:type] = 'ProductStandardCode'
|
164
|
+
end
|
165
|
+
}
|
166
|
+
let(:no_option) {
|
167
|
+
Sevennet::Api.configure do |options|
|
168
|
+
options[:StartIndex] = nil
|
169
|
+
options[:ResultAmount] = nil
|
170
|
+
options[:type] = nil
|
171
|
+
end
|
172
|
+
}
|
173
|
+
|
174
|
+
share_examples_for 'found review search keyword or options' do
|
175
|
+
subject { response }
|
176
|
+
its(:total_amount) { should > 0 }
|
177
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
178
|
+
it { should_not be_has_error }
|
179
|
+
context 'reviews.first' do
|
180
|
+
subject { response.reviews.first/"CommentTitle" }
|
181
|
+
it { should_not be_empty }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
share_examples_for 'not found review search keyword or options' do
|
186
|
+
subject { response }
|
187
|
+
its(:total_amount) { should == 0 }
|
188
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
189
|
+
its('reviews') { should == [] }
|
190
|
+
it { should_not be_has_error }
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'search keyword and options' do
|
194
|
+
let(:product_code) { '4901901397298' }
|
195
|
+
let(:opts) { options }
|
196
|
+
it_should_behave_like 'found review search keyword or options'
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'search keyword without options' do
|
200
|
+
let(:product_code) { '2110150300' }
|
201
|
+
let(:opts) { no_option }
|
202
|
+
it_should_behave_like 'found review search keyword or options'
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'search options without keyword' do
|
206
|
+
let(:product_code) { nil }
|
207
|
+
let(:opts) { options }
|
208
|
+
it { lambda{ response }.should raise_error( ArgumentError, "ProductCode is required.") }
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'search without keyword and options' do
|
212
|
+
let(:product_code) { nil }
|
213
|
+
let(:opts) { no_option }
|
214
|
+
it { lambda{ response }.should raise_error( ArgumentError, "ProductCode is required.") }
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'not found search keyword and options' do
|
218
|
+
let(:product_code) { '978-4-04-110518-4' }
|
219
|
+
let(:opts) { options }
|
220
|
+
it_should_behave_like 'not found review search keyword or options'
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'not found search keyword without options' do
|
224
|
+
let(:product_code) { '1106317843' }
|
225
|
+
let(:opts) { no_option }
|
226
|
+
it_should_behave_like 'not found review search keyword or options'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "Sevennet::Api.search_ranking" do
|
231
|
+
let(:response) {
|
232
|
+
VCR.use_cassette('search_ranking_' + category_code.to_s + '_' + opts.to_s) do
|
233
|
+
Sevennet::Api.search_ranking(category_code)
|
234
|
+
end
|
235
|
+
}
|
236
|
+
let(:options) {
|
237
|
+
Sevennet::Api.configure do |options|
|
238
|
+
options[:StartIndex] = 1
|
239
|
+
options[:ResultAmount] = 5
|
240
|
+
options[:TermCond] = 'last1w'
|
241
|
+
end
|
242
|
+
}
|
243
|
+
let(:no_option) {
|
244
|
+
Sevennet::Api.configure do |options|
|
245
|
+
options[:StartIndex] = nil
|
246
|
+
options[:ResultAmount] = nil
|
247
|
+
options[:TermCond] = nil
|
248
|
+
end
|
249
|
+
}
|
250
|
+
|
251
|
+
context 'search keyword and options' do
|
252
|
+
let(:category_code) { 'cd' }
|
253
|
+
let(:opts) { options }
|
254
|
+
it_should_behave_like 'found products search keyword or options'
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'search keyword without options' do
|
258
|
+
let(:category_code) { 'cd' }
|
259
|
+
let(:opts) { no_option }
|
260
|
+
it_should_behave_like 'found products search keyword or options'
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'search options without keyword' do
|
264
|
+
let(:category_code) { nil }
|
265
|
+
let(:opts) { options }
|
266
|
+
it { lambda{ response }.should raise_error( ArgumentError, "CategoryCode is required.") }
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'search without keyword and options' do
|
270
|
+
let(:category_code) { nil }
|
271
|
+
let(:opts) { no_option }
|
272
|
+
it { lambda{ response }.should raise_error( ArgumentError, "CategoryCode is required.") }
|
273
|
+
end
|
274
|
+
|
275
|
+
context 'not found search keyword and options' do
|
276
|
+
let(:category_code) { 'rubyssssss' }
|
277
|
+
let(:opts) { options }
|
278
|
+
it_should_behave_like 'not found products search keyword or options'
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'not found search keyword without options' do
|
282
|
+
let(:category_code) { 'rubyssssss' }
|
283
|
+
let(:opts) { no_option }
|
284
|
+
it_should_behave_like 'not found products search keyword or options'
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "Sevennet::Api.search_product" do
|
289
|
+
let(:response) {
|
290
|
+
VCR.use_cassette('search_product_' + terms.to_s + '_' + opts.to_s) do
|
291
|
+
Sevennet::Api.search_product(terms)
|
292
|
+
end
|
293
|
+
}
|
294
|
+
let(:options) {
|
295
|
+
Sevennet::Api.configure do |options|
|
296
|
+
options[:StartIndex] = 1
|
297
|
+
options[:ResultAmount] = 5
|
298
|
+
options[:CategoryCode] = 'cd'
|
299
|
+
end
|
300
|
+
}
|
301
|
+
let(:no_option) {
|
302
|
+
Sevennet::Api.configure do |options|
|
303
|
+
options[:StartIndex] = nil
|
304
|
+
options[:ResultAmount] = nil
|
305
|
+
options[:CategoryCode] = nil
|
306
|
+
end
|
307
|
+
}
|
308
|
+
|
309
|
+
context 'search keyword and options' do
|
310
|
+
let(:terms) { 'au' }
|
311
|
+
let(:opts) { options }
|
312
|
+
it_should_behave_like 'found products search keyword or options'
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'search keyword without options' do
|
316
|
+
let(:terms) { 'au' }
|
317
|
+
let(:opts) { no_option }
|
318
|
+
it_should_behave_like 'found products search keyword or options'
|
319
|
+
end
|
320
|
+
|
321
|
+
context 'search options without keyword' do
|
322
|
+
let(:terms) { nil }
|
323
|
+
let(:opts) { options }
|
324
|
+
it_should_behave_like 'found products search keyword or options'
|
325
|
+
end
|
326
|
+
|
327
|
+
context 'search without keyword and options' do
|
328
|
+
let(:terms) { nil }
|
329
|
+
let(:opts) { no_option }
|
330
|
+
it { lambda{response}.should raise_error( ArgumentError, "CategoryCode or KeywordIn is required.") }
|
331
|
+
end
|
332
|
+
|
333
|
+
context 'not found search keyword and options' do
|
334
|
+
let(:terms) { 'rubyssssss' }
|
335
|
+
let(:opts) { options }
|
336
|
+
it_should_behave_like 'not found products search keyword or options'
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'not found search keyword without options' do
|
340
|
+
let(:terms) { 'rubyssssss' }
|
341
|
+
let(:opts) { no_option }
|
342
|
+
it_should_behave_like 'not found products search keyword or options'
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
describe "Sevennet::Api.search_spc_shop" do
|
347
|
+
let(:response) {
|
348
|
+
VCR.use_cassette('search_spc_shop_' + terms.to_s + '_' + opts.to_s) do
|
349
|
+
Sevennet::Api.search_spc_shop(terms)
|
350
|
+
end
|
351
|
+
}
|
352
|
+
let(:options) {
|
353
|
+
Sevennet::Api.configure do |options|
|
354
|
+
options[:StartIndex] = 1
|
355
|
+
options[:ResultAmount] = 5
|
356
|
+
options[:SpcSortOrder] = 'name'
|
357
|
+
end
|
358
|
+
}
|
359
|
+
let(:no_option) {
|
360
|
+
Sevennet::Api.configure do |options|
|
361
|
+
options[:StartIndex] = nil
|
362
|
+
options[:ResultAmount] = nil
|
363
|
+
options[:SpcSortOrder] = nil
|
364
|
+
end
|
365
|
+
}
|
366
|
+
share_examples_for 'found spc shop search keyword or options' do
|
367
|
+
subject { response }
|
368
|
+
its(:total_amount) { should > 0 }
|
369
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
370
|
+
it { should_not be_has_error }
|
371
|
+
context 'shops.first' do
|
372
|
+
subject { response.shops.first/"SpcShopId" }
|
373
|
+
it { should_not be_empty }
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
share_examples_for 'not found spc shop search keyword or options' do
|
378
|
+
subject { response }
|
379
|
+
its(:total_amount) { should == 0 }
|
380
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
381
|
+
its('shops') { should == [] }
|
382
|
+
it { should_not be_has_error }
|
383
|
+
end
|
384
|
+
|
385
|
+
context 'search keyword and options' do
|
386
|
+
let(:terms) { 'au' }
|
387
|
+
let(:opts) { options }
|
388
|
+
it_should_behave_like 'found spc shop search keyword or options'
|
389
|
+
end
|
390
|
+
|
391
|
+
context 'search keyword without options' do
|
392
|
+
let(:terms) { 'au' }
|
393
|
+
let(:opts) { no_option }
|
394
|
+
it_should_behave_like 'found spc shop search keyword or options'
|
395
|
+
end
|
396
|
+
|
397
|
+
context 'search options without keyword' do
|
398
|
+
let(:terms) { nil }
|
399
|
+
let(:opts) { options }
|
400
|
+
it_should_behave_like 'found spc shop search keyword or options'
|
401
|
+
end
|
402
|
+
|
403
|
+
context 'search without keyword and options' do
|
404
|
+
let(:terms) { nil }
|
405
|
+
let(:opts) { no_option }
|
406
|
+
it_should_behave_like 'found spc shop search keyword or options'
|
407
|
+
end
|
408
|
+
|
409
|
+
context 'not found search keyword and options' do
|
410
|
+
let(:terms) { 'ruby' }
|
411
|
+
let(:opts) { options }
|
412
|
+
it_should_behave_like 'not found spc shop search keyword or options'
|
413
|
+
end
|
414
|
+
|
415
|
+
context 'not found search keyword without options' do
|
416
|
+
let(:terms) { 'ruby' }
|
417
|
+
let(:opts) { no_option }
|
418
|
+
it_should_behave_like 'not found spc shop search keyword or options'
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
describe "Sevennet::Api.get_shopping_category" do
|
423
|
+
let(:response) {
|
424
|
+
VCR.use_cassette('get_shopping_category_' + category_code.to_s) do
|
425
|
+
Sevennet::Api.get_shopping_category(category_code)
|
426
|
+
end
|
427
|
+
}
|
428
|
+
|
429
|
+
context 'root category' do
|
430
|
+
let(:category_code) { '' }
|
431
|
+
it_should_behave_like 'category common test'
|
432
|
+
end
|
433
|
+
|
434
|
+
context 'level 1 category' do
|
435
|
+
let(:category_code) { 'books' }
|
436
|
+
it_should_behave_like 'category common test'
|
437
|
+
end
|
438
|
+
|
439
|
+
context 'level 2 category' do
|
440
|
+
let(:category_code) { 'literature' }
|
441
|
+
it_should_behave_like 'category common test'
|
442
|
+
end
|
443
|
+
|
444
|
+
context 'wrong category code' do
|
445
|
+
let(:category_code) { '9989989898989898' }
|
446
|
+
subject { response }
|
447
|
+
its(:total_amount) { should == 0 }
|
448
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
449
|
+
its('categories.first') { should be_nil }
|
450
|
+
it { should_not be_has_error }
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "Sevennet::Api.get_spc_category" do
|
455
|
+
let(:response) {
|
456
|
+
VCR.use_cassette('get_spc_category_' + category_code.to_s) do
|
457
|
+
Sevennet::Api.get_spc_category(category_code)
|
458
|
+
end
|
459
|
+
}
|
460
|
+
|
461
|
+
context 'root category' do
|
462
|
+
let(:category_code) { '' }
|
463
|
+
it_should_behave_like 'category common test'
|
464
|
+
end
|
465
|
+
|
466
|
+
context 'level 1 category' do
|
467
|
+
let(:category_code) { 'books' }
|
468
|
+
it_should_behave_like 'category common test'
|
469
|
+
end
|
470
|
+
|
471
|
+
context 'level 2 category' do
|
472
|
+
let(:category_code) { 'literature' }
|
473
|
+
it_should_behave_like 'category common test'
|
474
|
+
end
|
475
|
+
|
476
|
+
context 'wrong category code' do
|
477
|
+
let(:category_code) { '9989989898989898' }
|
478
|
+
subject { response }
|
479
|
+
its(:total_amount) { should == 0 }
|
480
|
+
its(:doc) { should be_kind_of Nokogiri::XML::Document }
|
481
|
+
its('categories.first') { should be_nil }
|
482
|
+
it { should_not be_has_error }
|
483
|
+
end
|
484
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
#require 'webmock/rspec'
|
3
|
+
#WebMock.disable_net_connect!
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
VCR.configure do |c|
|
7
|
+
c.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + '/fixtures')
|
8
|
+
c.hook_into :webmock
|
9
|
+
# c.allow_http_connections_when_no_cassette = true
|
10
|
+
c.default_cassette_options = {
|
11
|
+
:match_requests_on => [:method,
|
12
|
+
VCR.request_matchers.uri_without_param(:Timestamp,:Signature)]
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/sevennet/api')
|
17
|
+
|
18
|
+
Sevennet::Api.configure do |options|
|
19
|
+
options[:ApiUserId] = 'your api user id'
|
20
|
+
options[:APISecretKey] = 'your api secret key'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sevennet-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- shoprev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: vcr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Generic Ruby 7netshopping API
|
84
|
+
email:
|
85
|
+
- admin@shoprev.net
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/sevennet/api.rb
|
96
|
+
- lib/sevennet/api/version.rb
|
97
|
+
- sevennet-api.gemspec
|
98
|
+
- spec/sevennet/api_spec.rb
|
99
|
+
- spec/spec_helper.rb
|
100
|
+
homepage: https://github.com/shoprev/sevennet-api
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: Generic Ruby 7netshopping API
|
124
|
+
test_files:
|
125
|
+
- spec/sevennet/api_spec.rb
|
126
|
+
- spec/spec_helper.rb
|