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
@@ -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
@@ -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
 
@@ -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
 
@@ -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
@@ -3,26 +3,34 @@
3
3
  require 'rakuten_web_service/client'
4
4
  require 'rakuten_web_service/search_result'
5
5
 
6
+ require 'rakuten_web_service/string_support'
7
+
6
8
  module RakutenWebService
7
9
  class Resource
8
10
  attr_reader :params
9
11
 
12
+ using RakutenWebService::StringSupport
13
+
10
14
  class << self
11
- def attribute(*attributes)
12
- attributes.each do |attribute|
13
- method_name = attribute.to_s.gsub(/([a-z]+)([A-Z]{1})/, '\1_\2').downcase
14
- method_name = method_name.sub(/^#{resource_name}_(\w+)$/, '\1')
15
- instance_eval do
16
- define_method method_name do
17
- get_attribute(attribute.to_s)
18
- end
19
- end
20
- next if method_name !~ /(.+)_flag$/
21
- instance_eval do
22
- define_method "#{$1}?" do
23
- get_attribute(attribute.to_s) == 1
24
- end
25
- end
15
+ attr_writer :resource_name
16
+
17
+ def inherited(subclass)
18
+ @@subclasses ||= []
19
+ @@subclasses.push(subclass)
20
+ end
21
+
22
+ def subclasses
23
+ @@subclasses || []
24
+ end
25
+
26
+ def attribute(*attribute_names)
27
+ attribute_names.each do |attribute_name|
28
+ attribute_name = attribute_name.to_s
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)
26
34
  end
27
35
  end
28
36
 
@@ -42,23 +50,36 @@ module RakutenWebService
42
50
  @resource_name ||= name.split('::').last.downcase
43
51
  end
44
52
 
45
- def set_resource_name(name)
46
- @resource_name = name
47
- end
48
-
49
53
  def endpoint(url = nil)
50
54
  @endpoint = url || @endpoint
51
55
  end
52
56
 
53
- def client
54
- @client ||= RakutenWebService::Client.new(endpoint)
55
- end
56
-
57
- def set_parser(&block)
57
+ def parser(&block)
58
58
  instance_eval do
59
59
  define_singleton_method :parse_response, block
60
60
  end
61
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
62
83
  end
63
84
 
64
85
  def initialize(params)
@@ -67,8 +88,7 @@ module RakutenWebService
67
88
  end
68
89
 
69
90
  def [](key)
70
- camel_key = key.split('_').map(&:capitalize).join
71
- camel_key[0] = camel_key[0].downcase
91
+ camel_key = key.to_camel
72
92
  @params[key] || @params[camel_key]
73
93
  end
74
94
 
@@ -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 Response
5
7
  include Enumerable
@@ -19,8 +21,10 @@ module RakutenWebService
19
21
  end
20
22
  end
21
23
 
24
+ using RakutenWebService::StringSupport
25
+
22
26
  %w[count hits page first last carrier pageCount].each do |name|
23
- method_name = name.gsub(/([a-z])([A-Z]{1})/) { "#{$1}_#{$2.downcase}" }
27
+ method_name = name.to_snake
24
28
  define_method method_name do
25
29
  self[name]
26
30
  end
@@ -29,6 +33,7 @@ module RakutenWebService
29
33
  def genre_information
30
34
  return unless @resource_class.respond_to?(:genre_class)
31
35
  return if self['GenreInformation'].empty?
36
+
32
37
  RWS::GenreInformation.new(self['GenreInformation'][0], @resource_class.genre_class)
33
38
  end
34
39
 
@@ -36,12 +41,12 @@ module RakutenWebService
36
41
  @resources ||= @resource_class.parse_response(@json)
37
42
  end
38
43
 
39
- def has_next_page?
40
- page && (not last_page?)
44
+ def next_page?
45
+ page && !last_page?
41
46
  end
42
47
 
43
- def has_previous_page?
44
- page && (not first_page?)
48
+ def previous_page?
49
+ page && !first_page?
45
50
  end
46
51
 
47
52
  def first_page?
@@ -2,11 +2,14 @@
2
2
 
3
3
  require 'rakuten_web_service/all_proxy'
4
4
  require 'rakuten_web_service/genre_information'
5
+ require 'rakuten_web_service/string_support'
5
6
 
6
7
  module RakutenWebService
7
8
  class SearchResult
8
9
  include Enumerable
9
10
 
11
+ using RakutenWebService::StringSupport
12
+
10
13
  def initialize(params, resource_class)
11
14
  @params = params.dup
12
15
  @resource_class = resource_class
@@ -14,7 +17,7 @@ module RakutenWebService
14
17
  end
15
18
 
16
19
  def search(params)
17
- SearchResult.new(self.params.dup.merge!(params), @resource_class)
20
+ self.class.new(self.params.dup.merge!(params), @resource_class)
18
21
  end
19
22
  alias with search
20
23
 
@@ -34,22 +37,25 @@ module RakutenWebService
34
37
  @params ||= {}
35
38
  end
36
39
 
40
+ def params_to_get_next_page
41
+ @params.merge('page' => @response.body['page'] + 1)
42
+ end
43
+
37
44
  def order(options)
38
45
  new_params = params.dup
39
- if options.is_a? Hash
40
- key, sort_order = *options.to_a.last
41
- key = camelize(key.to_s)
42
- new_params[:sort] = case sort_order.to_s.downcase
43
- when 'desc'
44
- "-#{key}"
45
- when 'asc'
46
- "+#{key}"
47
- end
48
- elsif options.to_s == 'standard'
46
+ if options.to_s == 'standard'
49
47
  new_params[:sort] = 'standard'
50
- else
48
+ return self.class.new(new_params, @resource_class)
49
+ end
50
+ unless options.is_a? Hash
51
51
  raise ArgumentError, "Invalid Sort Option: #{options.inspect}"
52
52
  end
53
+
54
+ key, sort_order = *options.to_a.last
55
+ case sort_order.to_s.downcase
56
+ when 'desc' then new_params[:sort] = "-#{key}".to_camel
57
+ when 'asc' then new_params[:sort] = "+#{key}".to_camel
58
+ end
53
59
  self.class.new(new_params, @resource_class)
54
60
  end
55
61
 
@@ -62,16 +68,16 @@ module RakutenWebService
62
68
  @response ||= query
63
69
  end
64
70
 
65
- def has_next_page?
66
- response.has_next_page?
71
+ def next_page?
72
+ response.next_page?
67
73
  end
68
74
 
69
75
  def next_page
70
76
  search(page: response.page + 1)
71
77
  end
72
78
 
73
- def has_previous_page?
74
- response.has_previous_page?
79
+ def previous_page?
80
+ response.previous_page?
75
81
  end
76
82
 
77
83
  def previous_page
@@ -96,12 +102,5 @@ module RakutenWebService
96
102
  sleep 1
97
103
  retry
98
104
  end
99
-
100
- def camelize(str)
101
- str = str.downcase
102
- str = str.split('_').map(&:capitalize).join
103
- str[0] = str[0].downcase
104
- str
105
- end
106
105
  end
107
106
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RakutenWebService
4
+ module StringSupport
5
+ refine String do
6
+ def to_snake
7
+ gsub(/([a-z]+)([A-Z]{1})/, '\1_\2').downcase
8
+ end
9
+
10
+ def to_camel
11
+ gsub(/([a-z]{1})_([a-z]{1})/) do |matched|
12
+ matched = matched.split('_')
13
+ matched[0] + matched[1].capitalize
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ require 'rakuten_web_service/travel/area_class'
2
+ require 'rakuten_web_service/travel/hotel'
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rakuten_web_service/travel/resource'
4
+
5
+ module RakutenWebService
6
+ module Travel
7
+ module AreaClass
8
+ def search(options = {})
9
+ Base.search(options)
10
+ end
11
+
12
+ def [](class_code)
13
+ LargeClass[class_code] ||
14
+ MiddleClass[class_code] ||
15
+ SmallClass[class_code] ||
16
+ DetailClass[class_code]
17
+ end
18
+ module_function :search, :[]
19
+
20
+ class Base < RakutenWebService::Travel::Resource
21
+ endpoint 'https://app.rakuten.co.jp/services/api/Travel/GetAreaClass/20131024'
22
+
23
+ parser do |response|
24
+ response['areaClasses']['largeClasses'].map do |data|
25
+ LargeClass.new(data)
26
+ end
27
+ end
28
+
29
+ class << self
30
+ def area_classes
31
+ @@area_classes ||= {}
32
+ end
33
+
34
+ def inherited(klass)
35
+ class_name = klass.to_s.split('::').last
36
+ area_level = class_name.to_s[/\A(\w*)Class\Z/, 1].downcase
37
+ class << klass
38
+ attr_reader :area_level
39
+ end
40
+ klass.instance_variable_set(:@area_level, area_level)
41
+
42
+ area_classes[klass.area_level] = klass
43
+
44
+ klass.attribute :"#{area_level}ClassCode", :"#{area_level}ClassName"
45
+ end
46
+
47
+ def [](area_code)
48
+ AreaClass.search.first unless repository[area_level][area_code]
49
+ repository[area_level][area_code]
50
+ end
51
+
52
+ def new(*args)
53
+ obj = super
54
+ repository[area_level][obj.class_code] = obj
55
+ obj
56
+ end
57
+
58
+ def repository
59
+ @@repository ||= Hash.new { |h, k| h[k] = {} }
60
+ end
61
+ end
62
+
63
+ attr_reader :parent, :children
64
+
65
+ def initialize(class_data, parent = nil)
66
+ @parent = parent
67
+ case class_data
68
+ when Array
69
+ @params = class_data.shift
70
+ @children = class_data.shift
71
+ when Hash
72
+ @params = class_data
73
+ @children = nil
74
+ end
75
+ parse_children_attributes
76
+ end
77
+
78
+ def area_level
79
+ self.class.area_level
80
+ end
81
+
82
+ def class_code
83
+ self["#{area_level}ClassCode"]
84
+ end
85
+
86
+ def class_name
87
+ self["#{area_level}ClassName"]
88
+ end
89
+
90
+ def to_query
91
+ query = { "#{area_level}ClassCode" => class_code }
92
+ query = query.merge(parent.to_query) unless parent.nil?
93
+ query
94
+ end
95
+
96
+ def search(params = {})
97
+ params = to_query.merge(params)
98
+
99
+ Hotel.search(params)
100
+ end
101
+
102
+ private
103
+
104
+ def parse_children_attributes
105
+ return @children = [] if children.nil? || children.empty?
106
+
107
+ children_class = children.keys.first[/\A(\w*)Classes\Z/, 1]
108
+ class_name = "#{children_class}Classes"
109
+ params[class_name] = children[class_name].map do |child_data|
110
+ Base.area_classes[children_class].new(child_data["#{children_class}Class"], self)
111
+ end
112
+ @children = params[class_name]
113
+ end
114
+ end
115
+
116
+ class LargeClass < Base
117
+ end
118
+
119
+ class MiddleClass < Base
120
+ end
121
+
122
+ class SmallClass < Base
123
+ end
124
+
125
+ class DetailClass < Base
126
+ end
127
+ end
128
+ end
129
+ end