rakuten_web_service 1.10.0 → 1.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +12 -0
  3. data/.github/workflows/ci.yml +30 -0
  4. data/CHANGELOG.md +103 -48
  5. data/Gemfile +3 -3
  6. data/README.ja.md +118 -48
  7. data/README.md +35 -10
  8. data/examples/ichiba_item_search.rb +1 -1
  9. data/examples/recipe_search.rb +16 -0
  10. data/lib/rakuten_web_service/all_proxy.rb +2 -1
  11. data/lib/rakuten_web_service/books/genre.rb +1 -1
  12. data/lib/rakuten_web_service/books/resource.rb +1 -1
  13. data/lib/rakuten_web_service/books/total.rb +1 -1
  14. data/lib/rakuten_web_service/client.rb +9 -9
  15. data/lib/rakuten_web_service/configuration.rb +0 -16
  16. data/lib/rakuten_web_service/error.rb +5 -0
  17. data/lib/rakuten_web_service/genre.rb +1 -1
  18. data/lib/rakuten_web_service/gora/course.rb +1 -1
  19. data/lib/rakuten_web_service/gora/course_detail.rb +1 -1
  20. data/lib/rakuten_web_service/gora/plan.rb +1 -1
  21. data/lib/rakuten_web_service/ichiba/item.rb +3 -3
  22. data/lib/rakuten_web_service/ichiba/product.rb +1 -1
  23. data/lib/rakuten_web_service/ichiba/ranking.rb +1 -1
  24. data/lib/rakuten_web_service/ichiba/tag.rb +16 -0
  25. data/lib/rakuten_web_service/ichiba/tag_group.rb +23 -0
  26. data/lib/rakuten_web_service/ichiba.rb +2 -0
  27. data/lib/rakuten_web_service/kobo/ebook.rb +1 -1
  28. data/lib/rakuten_web_service/kobo/genre.rb +1 -1
  29. data/lib/rakuten_web_service/recipe/category.rb +3 -1
  30. data/lib/rakuten_web_service/recipe.rb +1 -1
  31. data/lib/rakuten_web_service/resource.rb +29 -20
  32. data/lib/rakuten_web_service/response.rb +5 -4
  33. data/lib/rakuten_web_service/search_result.rb +14 -15
  34. data/lib/rakuten_web_service/travel/area_class.rb +30 -29
  35. data/lib/rakuten_web_service/travel/hotel.rb +3 -1
  36. data/lib/rakuten_web_service/travel/search_result.rb +1 -1
  37. data/lib/rakuten_web_service/version.rb +1 -1
  38. data/lib/rakuten_web_service.rb +17 -1
  39. data/rakuten_web_service.gemspec +6 -4
  40. data/spec/fixtures/ichiba/item_search_with_no_items.json +8 -0
  41. data/spec/fixtures/ichiba/tag_search.json +15 -0
  42. data/spec/rakuten_web_service/configuration_spec.rb +0 -52
  43. data/spec/rakuten_web_service/genre_spec.rb +1 -1
  44. data/spec/rakuten_web_service/ichiba/item_spec.rb +13 -0
  45. data/spec/rakuten_web_service/ichiba/tag_group_spec.rb +68 -0
  46. data/spec/rakuten_web_service/ichiba/tag_spec.rb +35 -0
  47. data/spec/rakuten_web_service/resource_spec.rb +2 -2
  48. data/spec/rakuten_web_service/response_spec.rb +7 -7
  49. data/spec/rakuten_web_service/travel/search_result_spec.rb +4 -4
  50. data/spec/rakuten_web_service_spec.rb +48 -0
  51. metadata +56 -16
  52. data/.travis.yml +0 -46
  53. data/spec/integration/integration_spec.rb +0 -78
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # RakutenWebService
2
-
2
+ [![CI](https://github.com/rakuten-ws/rws-ruby-sdk/workflows/CI/badge.svg)](https://github.com/rakuten-ws/rws-ruby-sdk/actions?query=workflow%3ACI+branch%3Amaster)
3
3
  [![Build Status](https://travis-ci.org/rakuten-ws/rws-ruby-sdk.svg?branch=master)](https://travis-ci.org/rakuten-ws/rws-ruby-sdk)
4
4
  [![Gem Version](https://badge.fury.io/rb/rakuten_web_service.svg)](https://badge.fury.io/rb/rakuten_web_service)
5
5
  [![Test Coverage](https://codeclimate.com/github/rakuten-ws/rws-ruby-sdk/badges/coverage.svg)](https://codeclimate.com/github/rakuten-ws/rws-ruby-sdk/coverage)
@@ -8,6 +8,8 @@
8
8
 
9
9
  This gem provides a client for easily accessing [Rakuten Web Service APIs](https://webservice.rakuten.co.jp/).
10
10
 
11
+ 日本語のドキュメントは[こちら](http://github.com/rakuten-ws/rws-ruby-sdk/blob/master/README.ja.md)。
12
+
11
13
  ## Table of Contents
12
14
 
13
15
  * [Prerequisite](#prerequisite)
@@ -30,23 +32,27 @@ This gem provides a client for easily accessing [Rakuten Web Service APIs](https
30
32
 
31
33
  ## Prerequisite
32
34
 
33
- * Ruby 2.3 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
53
+ ```sh
54
+ gem install rakuten_web_service
55
+ ```
50
56
 
51
57
  ## Usage
52
58
 
@@ -57,12 +63,12 @@ If you have not got it, register your application [here](https://webservice.raku
57
63
 
58
64
  ### Configuration
59
65
 
60
- 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`.
61
67
 
62
68
  #### In Your Code
63
69
 
64
70
  ```ruby
65
- RakutenWebService.configuration do |c|
71
+ RakutenWebService.configure do |c|
66
72
  # (Required) Appliction ID for your application.
67
73
  c.application_id = 'YOUR_APPLICATION_ID'
68
74
 
@@ -107,7 +113,7 @@ Responses of resources' `search` such as `RakutenWebService::Ichiba::Item.search
107
113
  last_items = items.page(3) # Skips first 2 pages.
108
114
 
109
115
  # Go to the last page
110
- while last_items.has_next_page?
116
+ while last_items.next_page?
111
117
  last_items = last_items.next_page
112
118
  end
113
119
 
@@ -143,12 +149,30 @@ Genre class provides an interface to traverse sub genres.
143
149
  ranking_by_age = RakutenWebService::Ichiba::Item.ranking(age: 30, sex: 1) # returns the TOP 30 items for Male in 30s
144
150
  # For attributes other than 'itemName', see: http://webservice.rakuten.co.jp/api/ichibaitemsearch/#outputParameter
145
151
  ranking_by_age.each do |ranking|
146
- puts ranking['itemName']
152
+ puts item.name
147
153
  end
148
154
 
149
155
  ranking_by_genre = RakutenWebService::Ichiba::Genre[200162].ranking # the TOP 30 items in "水・ソフトドリンク" genre
150
156
  ranking_by_genre.each do |ranking|
151
- 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
152
176
  end
153
177
  ```
154
178
 
@@ -162,6 +186,7 @@ Now rakuten\_web\_service is supporting the following APIs:
162
186
  * [Rakuten Ichiba Genre Search API](http://webservice.rakuten.co.jp/api/ichibagenresearch/)
163
187
  * [Rakuten Ichiba Ranking API](http://webservice.rakuten.co.jp/api/ichibaitemranking/)
164
188
  * [Rakuten Product API](http://webservice.rakuten.co.jp/api/productsearch/)
189
+ * [Rakuten Ichiba Tag Search API](https://webservice.rakuten.co.jp/api/ichibatagsearch/)
165
190
 
166
191
  ### Rakuten Books APIs
167
192
 
@@ -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
@@ -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
@@ -41,20 +41,4 @@ module RakutenWebService
41
41
  end
42
42
  end
43
43
  end
44
-
45
- def configure(&block)
46
- @configuration ||= Configuration.new
47
- if block
48
- raise ArgumentError, 'Block is required to have one argument' if block.arity != 1
49
- yield @configuration
50
- end
51
- @configuration
52
- end
53
-
54
- def configuration(&block)
55
- warn 'Warning: RakutenWebService.configuration is deprecated. Use RakutenWebService.configure.' if block_given?
56
- configure(&block)
57
- end
58
-
59
- module_function :configure, :configuration
60
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
@@ -7,7 +7,7 @@ module RakutenWebService
7
7
  def self.inherited(klass)
8
8
  super
9
9
 
10
- klass.set_parser do |response|
10
+ klass.parser do |response|
11
11
  current = response['current']
12
12
  %w[children parents brothers].each do |type|
13
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
 
@@ -17,8 +17,8 @@ module RakutenWebService
17
17
 
18
18
  endpoint 'https://app.rakuten.co.jp/services/api/IchibaItem/Search/20170706'
19
19
 
20
- set_parser do |response|
21
- response['Items'].map { |item| Item.new(item) }
20
+ parser do |response|
21
+ (response['Items'] || []).map { |item| Item.new(item) }
22
22
  end
23
23
 
24
24
  attribute :itemName, :catchcopy, :itemCode, :itemPrice,
@@ -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
 
@@ -7,7 +7,7 @@ module RakutenWebService
7
7
  class RankingItem < RakutenWebService::Ichiba::Item
8
8
  endpoint 'https://app.rakuten.co.jp/services/api/IchibaItem/Ranking/20170628'
9
9
 
10
- set_parser do |response|
10
+ parser do |response|
11
11
  response['Items'].map { |item| RankingItem.new(item) }
12
12
  end
13
13
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rakuten_web_service/resource'
4
+
5
+ module RakutenWebService
6
+ module Ichiba
7
+ class Tag < Resource
8
+ attribute :tagId, :tagName, :parentTagId
9
+
10
+ def search(params = {})
11
+ params = params.merge(tagId: id)
12
+ RakutenWebService::Ichiba::Item.search(params)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rakuten_web_service/resource'
4
+
5
+ module RakutenWebService
6
+ module Ichiba
7
+ class TagGroup < Resource
8
+ endpoint 'https://app.rakuten.co.jp/services/api/IchibaTag/Search/20140222'
9
+
10
+ parser do |response|
11
+ response['tagGroups'].map { |tag_group| TagGroup.new(tag_group) }
12
+ end
13
+
14
+ attribute :tagGroupName, :tagGroupId
15
+
16
+ def tags
17
+ get_attribute('tags').map do |tag|
18
+ Tag.new(tag)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -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'
@@ -16,7 +16,7 @@ module RakutenWebService
16
16
  :reviewCount, :reviewAverage,
17
17
  :koboGenreId
18
18
 
19
- set_parser do |response|
19
+ parser do |response|
20
20
  response['Items'].map { |i| new(i) }
21
21
  end
22
22
 
@@ -5,7 +5,7 @@ require 'rakuten_web_service/genre'
5
5
  module RakutenWebService
6
6
  module Kobo
7
7
  class Genre < RakutenWebService::BaseGenre
8
- set_resource_name :kobo_genre
8
+ self.resource_name = :kobo_genre
9
9
 
10
10
  root_id '101'
11
11
 
@@ -37,7 +37,9 @@ module RakutenWebService
37
37
 
38
38
  def parent_category
39
39
  return nil if parent_category_type.nil?
40
- Recipe.categories(parent_category_type).find { |c| c.id.to_i == parent_category_id.to_i }
40
+ Recipe.categories(parent_category_type).find do |c|
41
+ c.id.to_i == parent_category_id.to_i
42
+ end
41
43
  end
42
44
 
43
45
  def absolute_category_id
@@ -15,7 +15,7 @@ module RakutenWebService
15
15
  :recipeIndication, :recipeCost,
16
16
  :recipePublishday, :rank
17
17
 
18
- set_parser do |response|
18
+ parser do |response|
19
19
  response['result'].map { |r| Recipe.new(r) }
20
20
  end
21
21
 
@@ -12,6 +12,8 @@ module RakutenWebService
12
12
  using RakutenWebService::StringSupport
13
13
 
14
14
  class << self
15
+ attr_writer :resource_name
16
+
15
17
  def inherited(subclass)
16
18
  @@subclasses ||= []
17
19
  @@subclasses.push(subclass)
@@ -24,20 +26,11 @@ module RakutenWebService
24
26
  def attribute(*attribute_names)
25
27
  attribute_names.each do |attribute_name|
26
28
  attribute_name = attribute_name.to_s
27
- method_name = attribute_name.to_snake
28
- method_name = method_name.sub(/^#{resource_name}_(\w+)$/, '\1')
29
-
30
- instance_eval do
31
- define_method method_name do
32
- get_attribute(attribute_name)
33
- end
34
- end
35
- next if method_name !~ /(.+)_flag$/
36
- instance_eval do
37
- define_method "#{$1}?" do
38
- get_attribute(attribute_name) == 1
39
- end
40
- end
29
+
30
+ define_getter_for_attribute(attribute_name)
31
+ next unless attribute_name.end_with?('Flag')
32
+
33
+ define_asking_method_for_attribute(attribute_name)
41
34
  end
42
35
  end
43
36
 
@@ -57,19 +50,36 @@ module RakutenWebService
57
50
  @resource_name ||= name.split('::').last.downcase
58
51
  end
59
52
 
60
- def set_resource_name(name)
61
- @resource_name = name
62
- end
63
-
64
53
  def endpoint(url = nil)
65
54
  @endpoint = url || @endpoint
66
55
  end
67
56
 
68
- def set_parser(&block)
57
+ def parser(&block)
69
58
  instance_eval do
70
59
  define_singleton_method :parse_response, block
71
60
  end
72
61
  end
62
+
63
+ private
64
+
65
+ def define_getter_for_attribute(attribute_name)
66
+ method_name = attribute_name.to_snake
67
+ method_name.sub!(/^#{resource_name}_(\w+)$/, '\1')
68
+
69
+ define_method method_name do
70
+ get_attribute(attribute_name)
71
+ end
72
+ end
73
+
74
+ def define_asking_method_for_attribute(attribute_name)
75
+ method_name = attribute_name.to_snake
76
+ method_name.sub!(/^#{resource_name}_(\w+)$/, '\1')
77
+ method_name.sub!(/(.+)_flag$/, '\1')
78
+
79
+ define_method "#{method_name}?" do
80
+ get_attribute(attribute_name) == 1
81
+ end
82
+ end
73
83
  end
74
84
 
75
85
  def initialize(params)
@@ -79,7 +89,6 @@ module RakutenWebService
79
89
 
80
90
  def [](key)
81
91
  camel_key = key.to_camel
82
- # camel_key[0] = camel_key[0].downcase
83
92
  @params[key] || @params[camel_key]
84
93
  end
85
94