rakuten_web_service 1.9.1 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +6 -9
  3. data/.github/FUNDING.yml +12 -0
  4. data/.travis.yml +10 -22
  5. data/CHANGELOG.md +102 -44
  6. data/Gemfile +3 -4
  7. data/README.ja.md +118 -48
  8. data/README.md +44 -17
  9. data/Rakefile +13 -0
  10. data/examples/ichiba_item_search.rb +1 -1
  11. data/examples/recipe_search.rb +16 -0
  12. data/examples/travel_apis.rb +19 -0
  13. data/lib/rakuten_web_service.rb +18 -1
  14. data/lib/rakuten_web_service/all_proxy.rb +2 -1
  15. data/lib/rakuten_web_service/books/genre.rb +1 -1
  16. data/lib/rakuten_web_service/books/resource.rb +1 -1
  17. data/lib/rakuten_web_service/books/total.rb +1 -1
  18. data/lib/rakuten_web_service/client.rb +9 -9
  19. data/lib/rakuten_web_service/configuration.rb +5 -17
  20. data/lib/rakuten_web_service/error.rb +5 -0
  21. data/lib/rakuten_web_service/genre.rb +3 -1
  22. data/lib/rakuten_web_service/gora/course.rb +1 -1
  23. data/lib/rakuten_web_service/gora/course_detail.rb +1 -1
  24. data/lib/rakuten_web_service/gora/plan.rb +1 -1
  25. data/lib/rakuten_web_service/ichiba.rb +2 -0
  26. data/lib/rakuten_web_service/ichiba/item.rb +2 -2
  27. data/lib/rakuten_web_service/ichiba/product.rb +1 -1
  28. data/lib/rakuten_web_service/ichiba/ranking.rb +1 -1
  29. data/lib/rakuten_web_service/ichiba/tag.rb +16 -0
  30. data/lib/rakuten_web_service/ichiba/tag_group.rb +23 -0
  31. data/lib/rakuten_web_service/kobo/ebook.rb +1 -1
  32. data/lib/rakuten_web_service/kobo/genre.rb +1 -1
  33. data/lib/rakuten_web_service/recipe.rb +1 -1
  34. data/lib/rakuten_web_service/recipe/category.rb +3 -1
  35. data/lib/rakuten_web_service/resource.rb +46 -26
  36. data/lib/rakuten_web_service/response.rb +10 -5
  37. data/lib/rakuten_web_service/search_result.rb +22 -23
  38. data/lib/rakuten_web_service/string_support.rb +18 -0
  39. data/lib/rakuten_web_service/travel.rb +2 -0
  40. data/lib/rakuten_web_service/travel/area_class.rb +129 -0
  41. data/lib/rakuten_web_service/travel/hotel.rb +30 -0
  42. data/lib/rakuten_web_service/travel/open_struct.rb +19 -0
  43. data/lib/rakuten_web_service/travel/resource.rb +12 -0
  44. data/lib/rakuten_web_service/travel/search_result.rb +34 -0
  45. data/lib/rakuten_web_service/version.rb +1 -1
  46. data/rakuten_web_service.gemspec +8 -5
  47. data/spec/fixtures/ichiba/tag_search.json +15 -0
  48. data/spec/fixtures/travel/area_class.json +1 -0
  49. data/spec/fixtures/travel/simple_hotel_search.json +1 -0
  50. data/spec/rakuten_web_service/configuration_spec.rb +0 -52
  51. data/spec/rakuten_web_service/genre_spec.rb +1 -1
  52. data/spec/rakuten_web_service/ichiba/tag_group_spec.rb +68 -0
  53. data/spec/rakuten_web_service/ichiba/tag_spec.rb +35 -0
  54. data/spec/rakuten_web_service/resource_spec.rb +31 -1
  55. data/spec/rakuten_web_service/response_spec.rb +7 -7
  56. data/spec/rakuten_web_service/travel/area_class_spec.rb +117 -0
  57. data/spec/rakuten_web_service/travel/open_struct_spec.rb +53 -0
  58. data/spec/rakuten_web_service/travel/search_result_spec.rb +71 -0
  59. data/spec/rakuten_web_service/travel/simple_hotel_search_spec.rb +65 -0
  60. data/spec/rakuten_web_service_spec.rb +48 -0
  61. metadata +90 -19
  62. data/spec/integration/integration_spec.rb +0 -78
data/README.md CHANGED
@@ -8,7 +8,9 @@
8
8
 
9
9
  This gem provides a client for easily accessing [Rakuten Web Service APIs](https://webservice.rakuten.co.jp/).
10
10
 
11
- # Table of Contents
11
+ 日本語のドキュメントは[こちら](http://github.com/rakuten-ws/rws-ruby-sdk/blob/master/README.ja.md)。
12
+
13
+ ## Table of Contents
12
14
 
13
15
  * [Prerequisite](#prerequisite)
14
16
  * [Installation](#installation)
@@ -25,53 +27,56 @@ This gem provides a client for easily accessing [Rakuten Web Service APIs](https
25
27
  * [Rakuten Kobo APIs](#rakuten-kobo-apis)
26
28
  * [Rakuten Recipe APIs](#rakuten-recipe-apis)
27
29
  * [Rakuten GORA APIs](#rakuten-gora-apis)
30
+ * [Rakuten Travel APIs](#rakuten-travel-apis)
28
31
  * [Contributing](#contributing)
29
32
 
30
-
31
33
  ## Prerequisite
32
34
 
33
- * Ruby 2.2 or later
35
+ * Ruby 2.5 or later
34
36
 
35
37
  ## Installation
36
38
 
37
39
  Add this line to your application's Gemfile:
38
40
 
39
41
  ```ruby
40
- gem 'rakuten_web_service'
42
+ gem 'rakuten_web_service'
41
43
  ```
42
44
 
43
45
  And then execute:
44
46
 
45
- $ bundle
47
+ ```sh
48
+ bundle
49
+ ```
46
50
 
47
51
  Or install it yourself as:
48
52
 
49
- $ gem install rakuten_web_service
50
-
53
+ ```sh
54
+ gem install rakuten_web_service
55
+ ```
51
56
 
52
57
  ## Usage
53
58
 
54
59
  ### Prerequisite: Getting Application ID
55
60
 
56
- You need to get Application ID for your application to access to Rakuten Web Service APIs.
57
- If you have not got it, register your application [here](https://webservice.rakuten.co.jp/app/create).
61
+ You need to get Application ID for your application to access to Rakuten Web Service APIs.
62
+ If you have not got it, register your application [here](https://webservice.rakuten.co.jp/app/create).
58
63
 
59
64
  ### Configuration
60
65
 
61
- At first, you have to specify your application's key. And you can tell the client your afiiliate id with `RakutenWebService.configuration`.
66
+ At first, you have to specify your application's key. And you can tell the client your afiiliate id with `RakutenWebService.configure`.
62
67
 
63
68
  #### In Your Code
64
69
 
65
70
  ```ruby
66
- RakutenWebService.configuration do |c|
71
+ RakutenWebService.configure do |c|
67
72
  # (Required) Appliction ID for your application.
68
73
  c.application_id = 'YOUR_APPLICATION_ID'
69
74
 
70
75
  # (Optional) Affiliate ID for your Rakuten account.
71
76
  c.affiliate_id = 'YOUR_AFFILIATE_ID' # default: nil
72
77
 
73
- # (Optional) # of retries to send requests when the client receives
74
- # When the number of requests in some period overcomes the limit, the endpoints will return
78
+ # (Optional) # of retries to send requests when the client receives
79
+ # When the number of requests in some period overcomes the limit, the endpoints will return
75
80
  # too many requests error. Then the client tries to retry to send the same request after a
76
81
  # while.
77
82
  c.max_retries = 3 # default: 5
@@ -88,7 +93,6 @@ Please note that you need to replace `'YOUR_APPLICATION_ID'` and `'YOUR_AFFILIAT
88
93
 
89
94
  You can configure `application_id` and `affiliate_id` by defining environment variables `RWS_APPLICATION_ID` and `RWS_AFFILIATION_ID`.
90
95
 
91
-
92
96
  ### Search Ichiba Items
93
97
 
94
98
  ```ruby
@@ -139,19 +143,36 @@ Genre class provides an interface to traverse sub genres.
139
143
  RakutenWebService::Ichiba::Genre[100316].name # => "水・ソフトドリンク"
140
144
  ```
141
145
 
142
-
143
146
  ### Ichiba Item Ranking
144
147
 
145
148
  ```ruby
146
149
  ranking_by_age = RakutenWebService::Ichiba::Item.ranking(age: 30, sex: 1) # returns the TOP 30 items for Male in 30s
147
150
  # For attributes other than 'itemName', see: http://webservice.rakuten.co.jp/api/ichibaitemsearch/#outputParameter
148
151
  ranking_by_age.each do |ranking|
149
- puts ranking['itemName']
152
+ puts item.name
150
153
  end
151
154
 
152
155
  ranking_by_genre = RakutenWebService::Ichiba::Genre[200162].ranking # the TOP 30 items in "水・ソフトドリンク" genre
153
156
  ranking_by_genre.each do |ranking|
154
- puts ranking['itemName']
157
+ puts item.name
158
+ end
159
+ ```
160
+
161
+ ### Recipe
162
+
163
+ ```ruby
164
+ categories = RakutenWebService::Recipe.small_categories
165
+
166
+ # Search all small recipe categories.
167
+ categories.each do |category|
168
+ category.name
169
+ end
170
+
171
+ recipes = categories.first.ranking
172
+
173
+ # Search category recipes.
174
+ recipes.each do |recipe|
175
+ recipe.title
155
176
  end
156
177
  ```
157
178
 
@@ -165,6 +186,7 @@ Now rakuten\_web\_service is supporting the following APIs:
165
186
  * [Rakuten Ichiba Genre Search API](http://webservice.rakuten.co.jp/api/ichibagenresearch/)
166
187
  * [Rakuten Ichiba Ranking API](http://webservice.rakuten.co.jp/api/ichibaitemranking/)
167
188
  * [Rakuten Product API](http://webservice.rakuten.co.jp/api/productsearch/)
189
+ * [Rakuten Ichiba Tag Search API](https://webservice.rakuten.co.jp/api/ichibatagsearch/)
168
190
 
169
191
  ### Rakuten Books APIs
170
192
 
@@ -194,6 +216,11 @@ Now rakuten\_web\_service is supporting the following APIs:
194
216
  * [Rakuten GORA Golf Course Detail Search API](https://webservice.rakuten.co.jp/api/goragolfcoursedetail/)
195
217
  * [Rakuten GORA Plan Search API](https://webservice.rakuten.co.jp/api/goraplansearch/)
196
218
 
219
+ ### Rakuten Travel APIs
220
+
221
+ * [Rakuten Travel Simple Hotel API](https://webservice.rakuten.co.jp/api/simplehotelsearch/)
222
+ * [Rakuten Travel Get Area Class API](https://webservice.rakuten.co.jp/api/getareaclass/)
223
+
197
224
  ## Contributing
198
225
 
199
226
  1. Fork it
data/Rakefile CHANGED
@@ -1,6 +1,19 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
+ task :endpoints do
5
+ require 'rakuten_web_service'
6
+ require 'terminal-table'
7
+
8
+ table = Terminal::Table.new(headings: %w[Resource Endpoint]) do |t|
9
+ RakutenWebService::Resource.subclasses.each do |resource|
10
+ t << [resource.name, resource.endpoint] unless resource.endpoint.nil?
11
+ end
12
+ end
13
+
14
+ puts table
15
+ end
16
+
4
17
  RSpec::Core::RakeTask.new do |t|
5
18
  t.pattern = 'spec/**/*_spec.rb'
6
19
  t.rspec_opts = '-c -fd'
@@ -10,5 +10,5 @@ end
10
10
  items = RakutenWebService::Ichiba::Item.search(keyword: keyword)
11
11
 
12
12
  items.first(10).each do |item|
13
- puts "#{item['itemName']}, #{item['itemPrice']} yen"
13
+ puts "#{item.name}, #{item.price} yen"
14
14
  end
@@ -0,0 +1,16 @@
1
+ require 'rakuten_web_service'
2
+
3
+ application_id = ARGV.shift
4
+ keyword = ARGV[0..-1].join(' ')
5
+
6
+ RakutenWebService.configure do |c|
7
+ c.application_id = application_id
8
+ end
9
+
10
+ category = RakutenWebService::Recipe.small_categories.find { |c| c.name.match(keyword) }
11
+
12
+ recipes = category.ranking
13
+
14
+ recipes.first(10).each do |recipe|
15
+ puts "#{recipe.title} is made by #{recipe.nickname}"
16
+ end
@@ -0,0 +1,19 @@
1
+ require 'rakuten_web_service'
2
+
3
+ application_id = ARGV.shift
4
+
5
+ RakutenWebService.configure do |c|
6
+ c.application_id = application_id
7
+ end
8
+
9
+ tokyo = RakutenWebService::Travel::AreaClass::SmallClass['tokyo']
10
+
11
+ nikotama = tokyo.children.find do |detail_area|
12
+ detail_area.class_name =~ /二子玉川/
13
+ end
14
+
15
+ puts "#{nikotama.class_code}: #{nikotama.class_name}"
16
+
17
+ nikotama.search(responseType: 'large').first(3).each do |hotel|
18
+ puts "#{hotel.basic_info['hotelName']} \n\t#{hotel.basic_info['address1']} #{hotel.basic_info['address2']}"
19
+ end
@@ -1,10 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RakutenWebService; end
3
+ require 'rakuten_web_service/configuration'
4
+
5
+ module RakutenWebService
6
+ def configure(&block)
7
+ raise ArgumentError, 'Block is required' unless block
8
+ raise ArgumentError, 'Block is required to have one argument' if block.arity != 1
9
+ yield configuration
10
+
11
+ configuration
12
+ end
13
+
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ module_function :configure, :configuration
19
+ end
4
20
  RWS = RakutenWebService
5
21
 
6
22
  require 'rakuten_web_service/ichiba'
7
23
  require 'rakuten_web_service/books'
24
+ require 'rakuten_web_service/travel'
8
25
  require 'rakuten_web_service/kobo'
9
26
  require 'rakuten_web_service/gora'
10
27
  require 'rakuten_web_service/recipe'
@@ -14,7 +14,8 @@ module RakutenWebService
14
14
  search_result.each do |resource|
15
15
  yield resource
16
16
  end
17
- break unless search_result.has_next_page?
17
+ break unless search_result.next_page?
18
+
18
19
  search_result = search_result.next_page
19
20
  end
20
21
  end
@@ -5,7 +5,7 @@ require 'rakuten_web_service/genre'
5
5
  module RakutenWebService
6
6
  module Books
7
7
  class Genre < RakutenWebService::BaseGenre
8
- set_resource_name 'books_genre'
8
+ self.resource_name = 'books_genre'
9
9
 
10
10
  endpoint 'https://app.rakuten.co.jp/services/api/BooksGenre/Search/20121128'
11
11
 
@@ -6,7 +6,7 @@ require 'rakuten_web_service/books/genre'
6
6
  module RakutenWebService
7
7
  module Books
8
8
  class Resource < RakutenWebService::Resource
9
- set_parser do |response|
9
+ parser do |response|
10
10
  response['Items'].map { |item| new(item) }
11
11
  end
12
12
 
@@ -7,7 +7,7 @@ module RakutenWebService
7
7
  class Total < Books::Resource
8
8
  endpoint 'https://app.rakuten.co.jp/services/api/BooksTotal/Search/20170404'
9
9
 
10
- set_parser do |response|
10
+ parser do |response|
11
11
  response['Items'].map do |item|
12
12
  resource_class = find_resource_by_genre_id(item['booksGenreId'])
13
13
  resource_class.new(item)
@@ -9,6 +9,8 @@ require 'rakuten_web_service/error'
9
9
 
10
10
  module RakutenWebService
11
11
  class Client
12
+ USER_AGENT = "RakutenWebService SDK for Ruby v#{RWS::VERSION}(ruby-#{RUBY_VERSION} [#{RUBY_PLATFORM}])".freeze
13
+
12
14
  attr_reader :url
13
15
 
14
16
  def initialize(resource_class)
@@ -20,25 +22,23 @@ module RakutenWebService
20
22
  params = RakutenWebService.configuration.generate_parameters(params)
21
23
  response = request(url.path, params)
22
24
  body = JSON.parse(response.body)
23
-
24
- if Net::HTTPSuccess === response
25
- return RakutenWebService::Response.new(@resource_class, body)
25
+ unless response.is_a?(Net::HTTPSuccess)
26
+ raise RakutenWebService::Error.for(response)
26
27
  end
27
- raise RakutenWebService::Error.repository[response.code.to_i], body['error_description']
28
+
29
+ RakutenWebService::Response.new(@resource_class, body)
28
30
  end
29
31
 
30
32
  private
31
33
 
32
34
  def request(path, params)
33
- http = Net::HTTP.new(@url.host, @url.port)
35
+ http = Net::HTTP.new(url.host, url.port)
34
36
  http.use_ssl = true
35
37
  if RakutenWebService.configuration.debug_mode?
36
38
  http.set_debug_output($stderr)
37
39
  end
38
- path = "#{path}?#{params.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')}"
39
- header = {
40
- 'User-Agent' => "RakutenWebService SDK for Ruby v#{RWS::VERSION}(ruby-#{RUBY_VERSION} [#{RUBY_PLATFORM}])"
41
- }
40
+ path = "#{path}?#{URI.encode_www_form(params)}"
41
+ header = { 'User-Agent' => USER_AGENT }
42
42
  http.get(path, header)
43
43
  end
44
44
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rakuten_web_service/string_support'
4
+
3
5
  module RakutenWebService
4
6
  class Configuration
5
7
  attr_accessor :application_id, :affiliate_id, :max_retries, :debug
@@ -29,28 +31,14 @@ module RakutenWebService
29
31
 
30
32
  private
31
33
 
34
+ using RakutenWebService::StringSupport
35
+
32
36
  def convert_snake_key_to_camel_key(params)
33
37
  params.inject({}) do |h, (k, v)|
34
- k = k.to_s.gsub(/([a-z]{1})_([a-z]{1})/) { "#{$1}#{$2.capitalize}" }
38
+ k = k.to_s.to_camel
35
39
  h[k] = v
36
40
  h
37
41
  end
38
42
  end
39
43
  end
40
-
41
- def configure(&block)
42
- @configuration ||= Configuration.new
43
- if block
44
- raise ArgumentError, 'Block is required to have one argument' if block.arity != 1
45
- yield @configuration
46
- end
47
- @configuration
48
- end
49
-
50
- def configuration(&block)
51
- warn 'Warning: RakutenWebService.configuration is deprecated. Use RakutenWebService.configure.' if block_given?
52
- configure(&block)
53
- end
54
-
55
- module_function :configure, :configuration
56
44
  end
@@ -6,6 +6,11 @@ module RakutenWebService
6
6
  repository[status_code] = error
7
7
  end
8
8
 
9
+ def self.for(response)
10
+ error_class = repository[response.code.to_i]
11
+ error_class.new(JSON.parse(response.body)['error_description'])
12
+ end
13
+
9
14
  def self.repository
10
15
  @repository ||= {}
11
16
  end
@@ -5,7 +5,9 @@ require 'rakuten_web_service/resource'
5
5
  module RakutenWebService
6
6
  class BaseGenre < RakutenWebService::Resource
7
7
  def self.inherited(klass)
8
- klass.set_parser do |response|
8
+ super
9
+
10
+ klass.parser do |response|
9
11
  current = response['current']
10
12
  %w[children parents brothers].each do |type|
11
13
  elements = Array(response[type]).map { |e| klass.new(e) }
@@ -7,7 +7,7 @@ module RakutenWebService
7
7
  class Course < Resource
8
8
  endpoint 'https://app.rakuten.co.jp/services/api/Gora/GoraGolfCourseSearch/20170623'
9
9
 
10
- set_parser do |response|
10
+ parser do |response|
11
11
  response['Items'].map { |item| new(item) }
12
12
  end
13
13
 
@@ -13,7 +13,7 @@ module RakutenWebService
13
13
 
14
14
  endpoint 'https://app.rakuten.co.jp/services/api/Gora/GoraGolfCourseDetail/20170623'
15
15
 
16
- set_parser do |response|
16
+ parser do |response|
17
17
  [new(response['Item'])]
18
18
  end
19
19
 
@@ -7,7 +7,7 @@ module RakutenWebService
7
7
  class Plan < Resource
8
8
  endpoint 'https://app.rakuten.co.jp/services/api/Gora/GoraPlanSearch/20170623'
9
9
 
10
- set_parser do |response|
10
+ parser do |response|
11
11
  response['Items'].map { |item| new(item) }
12
12
  end
13
13
 
@@ -8,3 +8,5 @@ require 'rakuten_web_service/ichiba/item'
8
8
  require 'rakuten_web_service/ichiba/genre'
9
9
  require 'rakuten_web_service/ichiba/ranking'
10
10
  require 'rakuten_web_service/ichiba/product'
11
+ require 'rakuten_web_service/ichiba/tag_group'
12
+ require 'rakuten_web_service/ichiba/tag'
@@ -17,7 +17,7 @@ module RakutenWebService
17
17
 
18
18
  endpoint 'https://app.rakuten.co.jp/services/api/IchibaItem/Search/20170706'
19
19
 
20
- set_parser do |response|
20
+ parser do |response|
21
21
  response['Items'].map { |item| Item.new(item) }
22
22
  end
23
23
 
@@ -34,7 +34,7 @@ module RakutenWebService
34
34
  :reviewCount, :reviewAverage,
35
35
  :pointRate, :pointRateStartTime, :pointRateEndTime,
36
36
  :shopName, :shopCode, :shopUrl, :shopAffiliateUrl,
37
- :genreId
37
+ :genreId, :tagIds
38
38
 
39
39
  def genre
40
40
  Genre.new(genre_id)
@@ -8,7 +8,7 @@ module RakutenWebService
8
8
  class Product < Resource
9
9
  endpoint 'https://app.rakuten.co.jp/services/api/Product/Search/20170426'
10
10
 
11
- set_parser do |response|
11
+ parser do |response|
12
12
  (response['Products'] || []).map { |prod| Product.new(prod) }
13
13
  end
14
14