Skip to content

Commit 8a90cf8

Browse files
committed
Release: v6.0.0
- Added support for the new Composite Recommendation endpoint - Added new parameter `autoPresented` for Detail View and View Portion interactions - Added new parameter `timeSpent` for View Portion interactions - Added support for `reqlExpressions` on recommended items - Added support for input classes - Format code using `rubocop`
1 parent 962bb1a commit 8a90cf8

File tree

225 files changed

+3850
-3287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

225 files changed

+3850
-3287
lines changed

lib/recombee_api_client.rb

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010

1111
require 'recombee_api_client/errors'
1212
Gem.find_files('recombee_api_client/api/*.rb').each { |path| require path }
13+
Gem.find_files('recombee_api_client/inputs/*.rb').each { |path| require path }
1314

1415
module RecombeeApiClient
1516
##
1617
# Client for sending requests to Recombee recommender system
1718
class RecombeeClient
1819
include HTTParty
1920

20-
BATCH_MAX_SIZE = 10000
21-
USER_AGENT = {'User-Agent' => 'recombee-ruby-api-client/5.1.0'}
21+
BATCH_MAX_SIZE = 10_000
22+
USER_AGENT = { 'User-Agent' => 'recombee-ruby-api-client/6.0.0' }
2223

2324
##
2425
# - +account+ -> Name of your account at Recombee
@@ -33,8 +34,7 @@ def initialize(account, token, options = {})
3334
##
3435
# - +request+ -> ApiRequest to be sent to Recombee recommender
3536
def send(request)
36-
37-
return send_multipart_batch(request) if request.kind_of? Batch and request.requests.size > BATCH_MAX_SIZE
37+
return send_multipart_batch(request) if request.is_a? Batch and request.requests.size > BATCH_MAX_SIZE
3838

3939
timeout = request.timeout / 1000
4040
uri = process_request_uri(request)
@@ -54,20 +54,23 @@ def send(request)
5454
delete(request, uri, timeout)
5555
end
5656
rescue Timeout::Error
57-
fail ApiTimeout.new(request)
57+
raise ApiTimeout.new(request)
5858
end
5959
end
6060

6161
private
6262

6363
def get_regional_base_uri(region)
6464
uri = {
65-
'ap-se' => 'rapi-ap-se.recombee.com',
66-
'ca-east' => 'rapi-ca-east.recombee.com',
67-
'eu-west' => 'rapi-eu-west.recombee.com',
68-
'us-west' => 'rapi-us-west.recombee.com'
69-
}[region.to_s.gsub('_', '-').downcase]
70-
raise ArgumentError.new("Region \"#{region}\" is unknown. You may need to update the version of the SDK.") if uri == nil
65+
'ap-se' => 'rapi-ap-se.recombee.com',
66+
'ca-east' => 'rapi-ca-east.recombee.com',
67+
'eu-west' => 'rapi-eu-west.recombee.com',
68+
'us-west' => 'rapi-us-west.recombee.com'
69+
}[region.to_s.gsub('_', '-').downcase]
70+
if uri.nil?
71+
raise ArgumentError.new("Region \"#{region}\" is unknown. You may need to update the version of the SDK.")
72+
end
73+
7174
uri
7275
end
7376

@@ -77,16 +80,17 @@ def get_base_uri(options)
7780

7881
if options.key? :region
7982
raise ArgumentError.new(':base_uri and :region cannot be specified at the same time') if base_uri
83+
8084
base_uri = get_regional_base_uri(options[:region])
8185
end
82-
base_uri||= 'rapi.recombee.com'
86+
base_uri ||= 'rapi.recombee.com'
8387
base_uri
8488
end
8589

8690
def put(request, uri, timeout)
87-
response = self.class.put(uri, body: request.body_parameters.to_json,
88-
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
89-
timeout: timeout)
91+
response = self.class.put(uri, body: request.body_parameters.to_json,
92+
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
93+
timeout: timeout)
9094
check_errors(response, request)
9195
response.body
9296
end
@@ -98,60 +102,62 @@ def get(request, uri, timeout)
98102
end
99103

100104
def post(request, uri, timeout)
101-
response = self.class.post(uri, body: request.body_parameters.to_json,
102-
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
103-
timeout: timeout)
105+
response = self.class.post(uri, body: request.body_parameters.to_json,
106+
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
107+
timeout: timeout)
104108
check_errors(response, request)
105109
begin
106-
return JSON.parse(response.body)
110+
JSON.parse(response.body)
107111
rescue JSON::ParserError
108-
return response.body
112+
response.body
109113
end
110114
end
111115

112116
def delete(request, uri, timeout)
113117
response = self.class.delete(uri, body: request.body_parameters.to_json,
114-
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
115-
timeout: timeout)
118+
headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT),
119+
timeout: timeout)
116120
check_errors(response, request)
117121
begin
118-
return JSON.parse(response.body)
122+
JSON.parse(response.body)
119123
rescue JSON::ParserError
120-
return response.body
124+
response.body
121125
end
122126
end
123127

124128
def check_errors(response, request)
125129
status_code = response.code
126-
return if status_code == 200 || status_code == 201
127-
fail ResponseError.new(request, status_code, response.body)
130+
return if [200, 201].include?(status_code)
131+
132+
raise ResponseError.new(request, status_code, response.body)
128133
end
129134

130135
def send_multipart_batch(request)
131136
requests_parts = request.requests.each_slice(BATCH_MAX_SIZE)
132-
responses = requests_parts.map {|rqs| Batch.new(rqs)}.map{|batch| send(batch)}
133-
responses.inject([]){|result,resp| result + resp}
137+
responses = requests_parts.map { |rqs| Batch.new(rqs) }.map { |batch| send(batch) }
138+
responses.inject([]) { |result, resp| result + resp }
134139
end
135140

136141
def process_request_uri(request)
137142
uri = request.path
138-
uri.slice! ('/{databaseId}/')
143+
uri.slice!('/{databaseId}/')
139144
uri += query_parameters_to_url(request)
140145
uri
141146
end
142147

143148
def query_parameters_to_url(req)
144149
ps = ''
145150
req.query_parameters.each do |name, val|
146-
ps += (ps.include? '?') ? '&' : '?'
151+
ps += ps.include?('?') ? '&' : '?'
147152
ps += "#{name}=#{format_query_parameter_value(val)}"
148153
end
149154
ps
150155
end
151156

152157
def format_query_parameter_value(value)
153-
return CGI::escape("#{value}") unless value.kind_of?(Array)
154-
value.map{|v| CGI::escape("#{v}")}.join(',')
158+
return CGI.escape("#{value}") unless value.is_a?(Array)
159+
160+
value.map { |v| CGI.escape("#{v}") }.join(',')
155161
end
156162

157163
# Sign request with HMAC, request URI must be exacly the same
@@ -160,12 +166,11 @@ def sign_url(req_part)
160166
uri = "/#{@account}/#{req_part}"
161167
time = hmac_time(uri)
162168
sign = hmac_sign(uri, time)
163-
res = uri + time + "&hmac_sign=#{sign}"
164-
res
169+
uri + time + "&hmac_sign=#{sign}"
165170
end
166171

167172
def hmac_time(uri)
168-
res = (uri.include? '?') ? '&' : '?'
173+
res = uri.include?('?') ? '&' : '?'
169174
res << "hmac_timestamp=#{Time.now.utc.to_i}"
170175
end
171176

lib/recombee_api_client/api/add_bookmark.rb

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,29 @@
55
module RecombeeApiClient
66
require_relative 'request'
77
require_relative '../errors'
8-
8+
99
##
10-
#Adds a bookmark of the given item made by the given user.
10+
# Adds a bookmark of the given item made by the given user.
1111
#
1212
class AddBookmark < ApiRequest
1313
attr_reader :user_id, :item_id, :timestamp, :cascade_create, :recomm_id, :additional_data
14-
attr_accessor :timeout
15-
attr_accessor :ensure_https
16-
17-
##
18-
# * *Required arguments*
19-
# - +user_id+ -> User who bookmarked the item
20-
# - +item_id+ -> Bookmarked item
21-
#
22-
# * *Optional arguments (given as hash optional)*
23-
# - +timestamp+ -> UTC timestamp of the bookmark as ISO8601-1 pattern or UTC epoch time. The default value is the current time.
24-
# - +cascadeCreate+ -> Sets whether the given user/item should be created if not present in the database.
25-
# - +recommId+ -> If this bookmark is based on a recommendation request, `recommId` is the id of the clicked recommendation.
26-
# - +additionalData+ -> A dictionary of additional data for the interaction.
27-
#
14+
attr_accessor :timeout, :ensure_https
15+
16+
##
17+
# * *Required arguments*
18+
# - +user_id+ -> User who bookmarked the item
19+
# - +item_id+ -> Bookmarked item
20+
#
21+
# * *Optional arguments (given as hash optional)*
22+
# - +timestamp+ -> UTC timestamp of the bookmark as ISO8601-1 pattern or UTC epoch time. The default value is the current time.
23+
# - +cascadeCreate+ -> Sets whether the given user/item should be created if not present in the database.
24+
# - +recommId+ -> If this bookmark is based on a recommendation request, `recommId` is the id of the clicked recommendation.
25+
# - +additionalData+ -> A dictionary of additional data for the interaction.
26+
#
2827
def initialize(user_id, item_id, optional = {})
2928
@user_id = user_id
3029
@item_id = item_id
31-
optional = normalize_optional(optional)
30+
optional = normalize_hash_to_camel_case(optional)
3231
@timestamp = optional['timestamp']
3332
@cascade_create = optional['cascadeCreate']
3433
@recomm_id = optional['recommId']
@@ -37,37 +36,38 @@ def initialize(user_id, item_id, optional = {})
3736
@timeout = 3000
3837
@ensure_https = false
3938
@optional.each do |par, _|
40-
fail UnknownOptionalParameter.new(par) unless ["timestamp","cascadeCreate","recommId","additionalData"].include? par
39+
raise UnknownOptionalParameter.new(par) unless %w[timestamp cascadeCreate recommId
40+
additionalData].include? par
4141
end
4242
end
43-
43+
4444
# HTTP method
4545
def method
4646
:post
4747
end
48-
48+
4949
# Values of body parameters as a Hash
5050
def body_parameters
51-
p = Hash.new
51+
p = {}
5252
p['userId'] = @user_id
5353
p['itemId'] = @item_id
5454
p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp'
5555
p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate'
5656
p['recommId'] = @optional['recommId'] if @optional.include? 'recommId'
5757
p['additionalData'] = @optional['additionalData'] if @optional.include? 'additionalData'
58+
5859
p
5960
end
60-
61+
6162
# Values of query parameters as a Hash.
6263
# name of parameter => value of the parameter
6364
def query_parameters
64-
params = {}
65-
params
65+
{}
6666
end
67-
67+
6868
# Relative path to the endpoint
6969
def path
70-
"/{databaseId}/bookmarks/"
70+
'/{databaseId}/bookmarks/'
7171
end
7272
end
7373
end

lib/recombee_api_client/api/add_cart_addition.rb

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,31 @@
55
module RecombeeApiClient
66
require_relative 'request'
77
require_relative '../errors'
8-
8+
99
##
10-
#Adds a cart addition of the given item made by the given user.
10+
# Adds a cart addition of the given item made by the given user.
1111
#
1212
class AddCartAddition < ApiRequest
1313
attr_reader :user_id, :item_id, :timestamp, :cascade_create, :amount, :price, :recomm_id, :additional_data
14-
attr_accessor :timeout
15-
attr_accessor :ensure_https
16-
17-
##
18-
# * *Required arguments*
19-
# - +user_id+ -> User who added the item to the cart
20-
# - +item_id+ -> Item added to the cart
21-
#
22-
# * *Optional arguments (given as hash optional)*
23-
# - +timestamp+ -> UTC timestamp of the cart addition as ISO8601-1 pattern or UTC epoch time. The default value is the current time.
24-
# - +cascadeCreate+ -> Sets whether the given user/item should be created if not present in the database.
25-
# - +amount+ -> Amount (number) added to cart. The default is 1. For example, if `user-x` adds two `item-y` during a single order (session...), the `amount` should equal 2.
26-
# - +price+ -> Price of the added item. If `amount` is greater than 1, the sum of prices of all the items should be given.
27-
# - +recommId+ -> If this cart addition is based on a recommendation request, `recommId` is the id of the clicked recommendation.
28-
# - +additionalData+ -> A dictionary of additional data for the interaction.
29-
#
14+
attr_accessor :timeout, :ensure_https
15+
16+
##
17+
# * *Required arguments*
18+
# - +user_id+ -> User who added the item to the cart
19+
# - +item_id+ -> Item added to the cart
20+
#
21+
# * *Optional arguments (given as hash optional)*
22+
# - +timestamp+ -> UTC timestamp of the cart addition as ISO8601-1 pattern or UTC epoch time. The default value is the current time.
23+
# - +cascadeCreate+ -> Sets whether the given user/item should be created if not present in the database.
24+
# - +amount+ -> Amount (number) added to cart. The default is 1. For example, if `user-x` adds two `item-y` during a single order (session...), the `amount` should equal 2.
25+
# - +price+ -> Price of the added item. If `amount` is greater than 1, the sum of prices of all the items should be given.
26+
# - +recommId+ -> If this cart addition is based on a recommendation request, `recommId` is the id of the clicked recommendation.
27+
# - +additionalData+ -> A dictionary of additional data for the interaction.
28+
#
3029
def initialize(user_id, item_id, optional = {})
3130
@user_id = user_id
3231
@item_id = item_id
33-
optional = normalize_optional(optional)
32+
optional = normalize_hash_to_camel_case(optional)
3433
@timestamp = optional['timestamp']
3534
@cascade_create = optional['cascadeCreate']
3635
@amount = optional['amount']
@@ -41,18 +40,19 @@ def initialize(user_id, item_id, optional = {})
4140
@timeout = 3000
4241
@ensure_https = false
4342
@optional.each do |par, _|
44-
fail UnknownOptionalParameter.new(par) unless ["timestamp","cascadeCreate","amount","price","recommId","additionalData"].include? par
43+
raise UnknownOptionalParameter.new(par) unless %w[timestamp cascadeCreate amount price recommId
44+
additionalData].include? par
4545
end
4646
end
47-
47+
4848
# HTTP method
4949
def method
5050
:post
5151
end
52-
52+
5353
# Values of body parameters as a Hash
5454
def body_parameters
55-
p = Hash.new
55+
p = {}
5656
p['userId'] = @user_id
5757
p['itemId'] = @item_id
5858
p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp'
@@ -61,19 +61,19 @@ def body_parameters
6161
p['price'] = @optional['price'] if @optional.include? 'price'
6262
p['recommId'] = @optional['recommId'] if @optional.include? 'recommId'
6363
p['additionalData'] = @optional['additionalData'] if @optional.include? 'additionalData'
64+
6465
p
6566
end
66-
67+
6768
# Values of query parameters as a Hash.
6869
# name of parameter => value of the parameter
6970
def query_parameters
70-
params = {}
71-
params
71+
{}
7272
end
73-
73+
7474
# Relative path to the endpoint
7575
def path
76-
"/{databaseId}/cartadditions/"
76+
'/{databaseId}/cartadditions/'
7777
end
7878
end
7979
end

0 commit comments

Comments
 (0)