attune 1.0.3 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/attune.gemspec +3 -3
- data/lib/attune.rb +14 -0
- data/lib/attune/api/anonymous.rb +131 -0
- data/lib/attune/api/entities.rb +195 -0
- data/lib/attune/call_dropping.rb +1 -0
- data/lib/attune/client.rb +20 -170
- data/lib/attune/configurable.rb +1 -0
- data/lib/attune/default.rb +1 -0
- data/lib/attune/json_logger.rb +1 -0
- data/lib/attune/models/anonymousresult.rb +41 -0
- data/lib/attune/models/batchrankingrequest.rb +44 -0
- data/lib/attune/models/batchrankingresult.rb +44 -0
- data/lib/attune/models/blacklist.rb +111 -0
- data/lib/attune/models/blacklistgetresponse.rb +44 -0
- data/lib/attune/models/blacklistparams.rb +87 -0
- data/lib/attune/models/blacklistsaveresponse.rb +41 -0
- data/lib/attune/models/customer.rb +41 -0
- data/lib/attune/models/rankedentities.rb +60 -0
- data/lib/attune/models/rankingparams.rb +103 -0
- data/lib/attune/models/scopeentry.rb +49 -0
- data/lib/attune/net_http_persistent.rb +1 -0
- data/lib/attune/param_flattener.rb +1 -0
- data/lib/attune/version.rb +2 -1
- data/spec/attune/client_spec.rb +51 -59
- data/spec/remote_spec.rb +27 -27
- metadata +40 -25
@@ -0,0 +1,60 @@
|
|
1
|
+
module Attune
|
2
|
+
module Model
|
3
|
+
#
|
4
|
+
class RankedEntities
|
5
|
+
attr_accessor :message
|
6
|
+
|
7
|
+
|
8
|
+
attr_accessor :status
|
9
|
+
|
10
|
+
|
11
|
+
attr_accessor :ranking
|
12
|
+
|
13
|
+
|
14
|
+
# :internal => :external
|
15
|
+
def self.attribute_map
|
16
|
+
{
|
17
|
+
:message => :message,
|
18
|
+
:status => :status,
|
19
|
+
:ranking => :ranking
|
20
|
+
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(attributes = {})
|
25
|
+
return if attributes.empty?
|
26
|
+
# Morph attribute keys into undescored rubyish style
|
27
|
+
if self.class.attribute_map[:"message"]
|
28
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
29
|
+
@message = attributes["message"] || attributes[:"message"]
|
30
|
+
end
|
31
|
+
if self.class.attribute_map[:"status"]
|
32
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
33
|
+
@status = attributes["status"] || attributes[:"status"]
|
34
|
+
end
|
35
|
+
if self.class.attribute_map[:"ranking"]
|
36
|
+
value = attributes["ranking"] || attributes[:"ranking"]
|
37
|
+
if value.is_a?(Array)
|
38
|
+
@ranking = value
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_body
|
47
|
+
body = {}
|
48
|
+
self.class.attribute_map.each_pair do |key, value|
|
49
|
+
body[value] = self.send(key) unless self.send(key).nil?
|
50
|
+
end
|
51
|
+
body
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_json(options = {})
|
55
|
+
to_body.to_json
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Attune
|
2
|
+
module Model
|
3
|
+
#
|
4
|
+
class RankingParams
|
5
|
+
attr_accessor :view
|
6
|
+
|
7
|
+
|
8
|
+
attr_accessor :entity_type
|
9
|
+
|
10
|
+
|
11
|
+
attr_accessor :ids
|
12
|
+
|
13
|
+
|
14
|
+
attr_accessor :scope
|
15
|
+
|
16
|
+
|
17
|
+
attr_accessor :ip
|
18
|
+
|
19
|
+
|
20
|
+
attr_accessor :user_agent
|
21
|
+
|
22
|
+
|
23
|
+
attr_accessor :customer
|
24
|
+
|
25
|
+
|
26
|
+
attr_accessor :anonymous
|
27
|
+
|
28
|
+
|
29
|
+
# :internal => :external
|
30
|
+
def self.attribute_map
|
31
|
+
{
|
32
|
+
:view => :view,
|
33
|
+
:entity_type => :entityType,
|
34
|
+
:ids => :ids,
|
35
|
+
:scope => :scope,
|
36
|
+
:ip => :ip,
|
37
|
+
:user_agent => :userAgent,
|
38
|
+
:customer => :customer,
|
39
|
+
:anonymous => :anonymous
|
40
|
+
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(attributes = {})
|
45
|
+
return if attributes.empty?
|
46
|
+
# Morph attribute keys into undescored rubyish style
|
47
|
+
if self.class.attribute_map[:"view"]
|
48
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
49
|
+
@view = attributes["view"] || attributes[:"view"]
|
50
|
+
end
|
51
|
+
if self.class.attribute_map[:"entity_type"]
|
52
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
53
|
+
@entity_type = attributes["entityType"] || attributes[:"entity_type"]
|
54
|
+
end
|
55
|
+
if self.class.attribute_map[:"ids"]
|
56
|
+
value = attributes["ids"] || attributes[:"ids"]
|
57
|
+
if value.is_a?(Array)
|
58
|
+
@ids = value
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
if self.class.attribute_map[:"scope"]
|
63
|
+
value = attributes["scope"] || attributes[:"scope"]
|
64
|
+
if value.is_a?(Array)
|
65
|
+
@scope = value.map{ |v| ScopeEntry.new(v) }
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
if self.class.attribute_map[:"ip"]
|
70
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
71
|
+
@ip = attributes["ip"] || attributes[:"ip"]
|
72
|
+
end
|
73
|
+
if self.class.attribute_map[:"user_agent"]
|
74
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
75
|
+
@user_agent = attributes["userAgent"] || attributes[:"user_agent"]
|
76
|
+
end
|
77
|
+
if self.class.attribute_map[:"customer"]
|
78
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
79
|
+
@customer = attributes["customer"] || attributes[:"customer"]
|
80
|
+
end
|
81
|
+
if self.class.attribute_map[:"anonymous"]
|
82
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
83
|
+
@anonymous = attributes["anonymous"] || attributes[:"anonymous"]
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_body
|
90
|
+
body = {}
|
91
|
+
self.class.attribute_map.each_pair do |key, value|
|
92
|
+
body[value] = self.send(key) unless self.send(key).nil?
|
93
|
+
end
|
94
|
+
body
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_json(options = {})
|
98
|
+
to_body.to_json
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Attune
|
2
|
+
module Model
|
3
|
+
#
|
4
|
+
class ScopeEntry
|
5
|
+
attr_accessor :name
|
6
|
+
|
7
|
+
|
8
|
+
attr_accessor :value
|
9
|
+
|
10
|
+
|
11
|
+
# :internal => :external
|
12
|
+
def self.attribute_map
|
13
|
+
{
|
14
|
+
:name => :name,
|
15
|
+
:value => :value
|
16
|
+
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(attributes = {})
|
21
|
+
return if attributes.empty?
|
22
|
+
# Morph attribute keys into undescored rubyish style
|
23
|
+
if self.class.attribute_map[:"name"]
|
24
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
25
|
+
@name = attributes["name"] || attributes[:"name"]
|
26
|
+
end
|
27
|
+
if self.class.attribute_map[:"value"]
|
28
|
+
# Workaround since JSON.parse has accessors as strings rather than symbols
|
29
|
+
@value = attributes["value"] || attributes[:"value"]
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_body
|
36
|
+
body = {}
|
37
|
+
self.class.attribute_map.each_pair do |key, value|
|
38
|
+
body[value] = self.send(key) unless self.send(key).nil?
|
39
|
+
end
|
40
|
+
body
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_json(options = {})
|
44
|
+
to_body.to_json
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
data/lib/attune/version.rb
CHANGED
data/spec/attune/client_spec.rb
CHANGED
@@ -26,23 +26,23 @@ describe Attune::Client do
|
|
26
26
|
|
27
27
|
describe "API errors" do
|
28
28
|
it "will raise timeout" do
|
29
|
-
stubs.post("anonymous",
|
29
|
+
stubs.post("anonymous", nil){ raise Faraday::Error::TimeoutError.new("test") }
|
30
30
|
expect {
|
31
|
-
client.
|
31
|
+
client.anonymous.create
|
32
32
|
}.to raise_exception(Faraday::Error::TimeoutError)
|
33
33
|
stubs.verify_stubbed_calls
|
34
34
|
end
|
35
35
|
it "will raise ConnectionFailed" do
|
36
|
-
stubs.post("anonymous",
|
36
|
+
stubs.post("anonymous", nil){ raise Faraday::Error::ConnectionFailed.new("test") }
|
37
37
|
expect {
|
38
|
-
client.
|
38
|
+
client.anonymous.create
|
39
39
|
}.to raise_exception(Faraday::Error::ConnectionFailed)
|
40
40
|
stubs.verify_stubbed_calls
|
41
41
|
end
|
42
42
|
it "will raise ConnectionFailed on Errno::ENOENT" do
|
43
|
-
stubs.post("anonymous",
|
43
|
+
stubs.post("anonymous", nil){ raise Errno::ENOENT.new("test") }
|
44
44
|
expect {
|
45
|
-
client.
|
45
|
+
client.anonymous.create
|
46
46
|
}.to raise_exception(Faraday::Error::ConnectionFailed)
|
47
47
|
end
|
48
48
|
it "will raise AuthenticationException" do
|
@@ -61,7 +61,7 @@ describe Attune::Client do
|
|
61
61
|
let(:options){ {disabled: true, exception_handler: :raise} }
|
62
62
|
it "will raise DisalbedException" do
|
63
63
|
expect {
|
64
|
-
client.
|
64
|
+
client.anonymous.create
|
65
65
|
}.to raise_exception(Attune::DisabledException)
|
66
66
|
end
|
67
67
|
end
|
@@ -73,11 +73,11 @@ describe Attune::Client do
|
|
73
73
|
expect(result).to match(/^[a-z0-9\-]+$/)
|
74
74
|
end
|
75
75
|
it "mocks create_anonymous with an id" do
|
76
|
-
result = client.
|
76
|
+
result = client.anonymous.create(id: '12345', user_agent: 'Mozilla/5.0')
|
77
77
|
expect(result).to eq('12345')
|
78
78
|
end
|
79
79
|
it "mocks create_anonymous with no id" do
|
80
|
-
result = client.
|
80
|
+
result = client.anonymous.create(user_agent: 'Mozilla/5.0')
|
81
81
|
expect(result).to match(/^[a-z0-9\-]+$/)
|
82
82
|
end
|
83
83
|
describe "mocks get_rankings" do
|
@@ -90,7 +90,7 @@ describe Attune::Client do
|
|
90
90
|
end
|
91
91
|
|
92
92
|
before(:each) do
|
93
|
-
@result = client.get_rankings(
|
93
|
+
@result = client.entities.get_rankings(
|
94
94
|
id: 'abcd123',
|
95
95
|
view: 'b/mens-pants',
|
96
96
|
collection: 'products',
|
@@ -157,59 +157,66 @@ describe Attune::Client do
|
|
157
157
|
end
|
158
158
|
|
159
159
|
it "can create_anonymous generating an id" do
|
160
|
-
stubs.post("anonymous",
|
161
|
-
|
160
|
+
stubs.post("anonymous", nil){ [200, {location: 'urn:id:abcd123'}, %[{"id": "abcd123"}]] }
|
161
|
+
result = client.anonymous.create
|
162
162
|
stubs.verify_stubbed_calls
|
163
163
|
|
164
|
-
expect(id).to eq('abcd123')
|
164
|
+
expect(result.id).to eq('abcd123')
|
165
165
|
end
|
166
166
|
|
167
167
|
it "can bind" do
|
168
|
-
stubs.put("
|
169
|
-
client.
|
168
|
+
stubs.put("anonymous/abcd123", %[{"customer":"foobar"}]){ [200, {}, nil] }
|
169
|
+
client.anonymous.update('abcd123', Attune::Model::Customer.new(customer:'foobar'))
|
170
170
|
stubs.verify_stubbed_calls
|
171
171
|
end
|
172
172
|
|
173
|
-
it "
|
174
|
-
stubs.
|
175
|
-
|
173
|
+
it "get anonymous using existing id" do
|
174
|
+
stubs.get("anonymous/abcd123"){ [200, {}, %[{"customer":"foobar"}]] }
|
175
|
+
response = client.anonymous.get('abcd123')
|
176
176
|
stubs.verify_stubbed_calls
|
177
177
|
|
178
|
-
expect(
|
178
|
+
expect(response.customer).to eq('foobar')
|
179
179
|
end
|
180
180
|
|
181
181
|
describe "get_rankings" do
|
182
182
|
before(:each) do
|
183
|
-
|
184
|
-
|
185
|
-
id: 'abcd123',
|
183
|
+
ranking_request = {
|
184
|
+
anonymous: 'abcd123',
|
186
185
|
view: 'b/mens-pants',
|
187
|
-
|
188
|
-
|
189
|
-
|
186
|
+
entity_type: 'products',
|
187
|
+
ids: %w[1001, 1002, 1003, 1004]
|
188
|
+
}
|
189
|
+
stubs.post("entities/ranking", ranking_request.to_json){ [200, nil, %[{"ranking":["1004","1003","1002","1001"]}]] }
|
190
|
+
@rankings = client.entities.get_rankings(ranking_request)
|
190
191
|
stubs.verify_stubbed_calls
|
191
192
|
end
|
192
193
|
|
193
194
|
it "can get ranked entities" do
|
194
|
-
expect(@rankings
|
195
|
-
end
|
196
|
-
|
197
|
-
it "can get ranking headers" do
|
198
|
-
expect(@rankings[:headers]).to eq({"attune-ranking"=>"test", "attune-cell"=>"test"})
|
195
|
+
expect(@rankings.ranking).to eq(%W[1004 1003 1002 1001])
|
199
196
|
end
|
200
197
|
end
|
201
198
|
|
202
199
|
describe "multi_get_rankings" do
|
203
|
-
let(:req1){ CGI::escape 'anonymous=0cddbc0-6114-11e3-949a-0800200c9a66&view=b%2Fmens-pants&entity_collection=products&entities=1001%2C%2C1002%2C%2C1003%2C%2C1004&ip=none' }
|
204
|
-
let(:req2){ CGI::escape 'anonymous=0cddbc0-6114-11e3-949a-0800200c9a66&view=b%2Fmens-pants&entity_collection=products&entities=2001%2C%2C2002%2C%2C2003%2C%2C2004&ip=none' }
|
205
|
-
|
206
200
|
before(:each) do
|
207
|
-
|
208
|
-
|
201
|
+
batch_request = {requests: [
|
202
|
+
{
|
203
|
+
anonymous: '0cddbc0-6114-11e3-949a-0800200c9a66',
|
204
|
+
view: 'b/mens-pants',
|
205
|
+
entity_type: 'products',
|
206
|
+
ids: %w[1001, 1002, 1003, 1004]
|
207
|
+
},
|
208
|
+
{
|
209
|
+
anonymous: '0cddbc0-6114-11e3-949a-0800200c9a66',
|
210
|
+
view: 'b/mens-pants',
|
211
|
+
entity_type: 'products',
|
212
|
+
ids: %w[2001, 2002, 2003, 2004]
|
213
|
+
}
|
214
|
+
]}
|
215
|
+
stubs.post("entities/ranking/many", batch_request.to_json) do
|
216
|
+
[200, nil, <<-JSON]
|
209
217
|
{
|
210
|
-
"
|
211
|
-
|
212
|
-
"anonymous=0cddbc0-6114-11e3-949a-0800200c9a66&entities=1001%2C%2C1002%2C%2C1003%2C%2C1004&entity_collection=products&ip=none&view=b%2Fmens-pants": {
|
218
|
+
"results": [
|
219
|
+
{
|
213
220
|
"ranking": [
|
214
221
|
"1004",
|
215
222
|
"1003",
|
@@ -217,7 +224,7 @@ describe Attune::Client do
|
|
217
224
|
"1001"
|
218
225
|
]
|
219
226
|
},
|
220
|
-
|
227
|
+
{
|
221
228
|
"ranking": [
|
222
229
|
"2004",
|
223
230
|
"2003",
|
@@ -225,36 +232,21 @@ describe Attune::Client do
|
|
225
232
|
"2001"
|
226
233
|
]
|
227
234
|
}
|
228
|
-
|
235
|
+
]
|
229
236
|
}
|
230
237
|
JSON
|
231
238
|
end
|
232
|
-
@
|
233
|
-
{
|
234
|
-
id: '0cddbc0-6114-11e3-949a-0800200c9a66',
|
235
|
-
view: 'b/mens-pants',
|
236
|
-
collection: 'products',
|
237
|
-
entities: %w[1001, 1002, 1003, 1004]
|
238
|
-
},
|
239
|
-
{
|
240
|
-
id: '0cddbc0-6114-11e3-949a-0800200c9a66',
|
241
|
-
view: 'b/mens-pants',
|
242
|
-
collection: 'products',
|
243
|
-
entities: %w[2001, 2002, 2003, 2004]
|
244
|
-
}
|
245
|
-
])
|
239
|
+
@results = client.entities.batch_get_rankings(batch_request)
|
246
240
|
stubs.verify_stubbed_calls
|
247
241
|
end
|
248
242
|
|
249
243
|
it "can get ranked entities" do
|
250
|
-
|
244
|
+
rankings = @results.results.map {|r| r.ranking }
|
245
|
+
expect(rankings).to eq [
|
251
246
|
%W[1004 1003 1002 1001],
|
252
247
|
%W[2004 2003 2002 2001]
|
253
248
|
]
|
254
249
|
end
|
255
|
-
|
256
|
-
it "can get ranking headers" do
|
257
|
-
expect(@rankings[:headers]).to eq({"attune-ranking"=>"test", "attune-cell"=>"test"})
|
258
|
-
end
|
259
250
|
end
|
260
251
|
end
|
252
|
+
|
data/spec/remote_spec.rb
CHANGED
@@ -21,49 +21,49 @@ describe "remote requests" do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "can create an anonymous user" do
|
24
|
-
|
25
|
-
id.should =~ /[a-z0-9\-]+/
|
24
|
+
result = client.anonymous.create
|
25
|
+
result.id.should =~ /[a-z0-9\-]+/
|
26
26
|
end
|
27
27
|
|
28
|
-
it "can
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
it "can bind an anonymous user" do
|
34
|
-
id = client.create_anonymous(id: '123456', user_agent: 'Mozilla/5.0')
|
35
|
-
client.bind(id, '654321')
|
28
|
+
it "can bind and get an anonymous user" do
|
29
|
+
client.anonymous.update('654321', Attune::Model::Customer.new(customer:'foobar'))
|
30
|
+
customer = client.anonymous.get('654321')
|
31
|
+
customer.customer.should == 'foobar'
|
36
32
|
end
|
37
33
|
|
38
34
|
let(:entities){ [202875,202876,202874,202900,202902,202898,202905,200182,200181,185940,188447,185932,190589,1238689589] }
|
39
35
|
describe "get_rankings" do
|
40
36
|
before(:each) do
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
anonymous_result = client.anonymous.create
|
38
|
+
params = Attune::Model::RankingParams.new
|
39
|
+
params.anonymous = anonymous_result.id
|
40
|
+
params.view = 'b/mens-pants'
|
41
|
+
params.entity_type = 'products'
|
42
|
+
params.ids = entities
|
43
|
+
@result = client.entities.get_rankings(params)
|
44
44
|
end
|
45
45
|
it "can get ranked entities" do
|
46
|
-
@result
|
47
|
-
@result
|
46
|
+
@result.ranking.should be_an Array
|
47
|
+
@result.ranking.sort.should == entities.map(&:to_s).sort
|
48
48
|
end
|
49
|
-
specify { expect(@result[:headers]).to be_a Hash }
|
50
|
-
specify { expect(@result[:headers]).to have_key "attune-ranking" }
|
51
|
-
specify { expect(@result[:headers]).to have_key "attune-cell" }
|
52
49
|
end
|
53
50
|
|
54
51
|
describe "multi_get_rankings" do
|
55
52
|
before(:each) do
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
anonymous_result = client.anonymous.create
|
54
|
+
params = Attune::Model::RankingParams.new
|
55
|
+
params.anonymous = anonymous_result.id
|
56
|
+
params.view = 'b/mens-pants'
|
57
|
+
params.entity_type = 'products'
|
58
|
+
params.ids = entities
|
59
|
+
batch_request = Attune::Model::BatchRankingRequest.new
|
60
|
+
batch_request.requests = [params]
|
61
|
+
@results = client.entities.batch_get_rankings(batch_request)
|
59
62
|
end
|
60
63
|
it "can batch get rankings" do
|
61
|
-
@results
|
62
|
-
|
63
|
-
|
64
|
+
@results.results.should be_an Array
|
65
|
+
ranking = @results.results[0].ranking
|
66
|
+
ranking.sort.should == entities.map(&:to_s).sort
|
64
67
|
end
|
65
|
-
specify { expect(@results[:headers]).to be_a Hash }
|
66
|
-
specify { expect(@results[:headers]).to have_key "attune-ranking" }
|
67
|
-
specify { expect(@results[:headers]).to have_key "attune-cell" }
|
68
68
|
end
|
69
69
|
end
|