sixpack-client 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/README.md +34 -2
- data/lib/sixpack/configuration.rb +16 -0
- data/lib/sixpack/version.rb +1 -1
- data/lib/sixpack.rb +37 -24
- data/sixpack.gemspec +0 -1
- data/spec/lib/sixpack_spec.rb +42 -61
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NzUyMTk0MjllOGI1MGIyYmRiYmY4OTQxOGZjOWFjYjViODNiOGRhNQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjM0MjFhYzlmNTAzYTE0MGJhNTIxZjgxMTZlMWEyZDY2MzUxNGI3OA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDkzZTc0MzI5NTEwOTVmMWQ0NmIyMTJmMWQ0MjRkMGJkMTdjYWQ3NWQ0YWNm
|
10
|
+
MTQxZDVjYzVlODQ2ZGFiZmQ0YzRmNjIyMzI4YTA5NTdmODBmZTAyMDgwMWJi
|
11
|
+
MDg4YTZlZjhmOTk0YzVhNzdiNjRkN2IwNzYwNTk2MzE3ZDk0MGM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTE0ODFkODkxMDg3YTNlYWFjMTRiYmIzZTFkNGQ1MDg0ODYwYzAwM2M1Yzgy
|
14
|
+
YzMwYjk2MGY3MTg4YWVjZGRjNGYxZTQxNTA3MmEwNDhhZDZjZWUyMzc2OWNk
|
15
|
+
NTEyMjYxZDQzY2NjMzliMmViZDlmMWFhODM3ZDNkYTgxYjZmYzk=
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Sixpack
|
2
2
|
|
3
|
+
[](https://travis-ci.org/seatgeek/sixpack-rb)
|
4
|
+
|
3
5
|
Ruby client library for SeatGeek's Sixpack ab testing framework.
|
4
6
|
|
5
7
|
## Installation
|
@@ -47,14 +49,14 @@ For future requests, create the `Session` using the `client_id` stored in the co
|
|
47
49
|
|
48
50
|
```ruby
|
49
51
|
client_id = get_cookie_from_web_framework("sixpack-id")
|
50
|
-
session = Sixpack::Session.new
|
52
|
+
session = Sixpack::Session.new(client_id)
|
51
53
|
session.convert("new-test")
|
52
54
|
```
|
53
55
|
|
54
56
|
Sessions can take an optional `options` hash that takes `:base_url`, and a params hash that takes `:ip_address`, and `:user_agent` a keys. If you would like to instantiate a session with a known client id, you can do that here. IP address and user agent can be passed to assist in bot detection.
|
55
57
|
|
56
58
|
options = {
|
57
|
-
:
|
59
|
+
:base_url => 'http://mysixpacklocation.com'
|
58
60
|
}
|
59
61
|
params = {
|
60
62
|
:ip_address => '1.2.3.4'
|
@@ -63,6 +65,36 @@ Sessions can take an optional `options` hash that takes `:base_url`, and a param
|
|
63
65
|
|
64
66
|
If Sixpack is unreachable or other errors occur, sixpack-rb will provide the control alternative object.
|
65
67
|
|
68
|
+
## Configuration
|
69
|
+
|
70
|
+
You can configure the Sixpack in the configure block:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
Sixpack.configure do |config|
|
74
|
+
config.base_url = 'http://10.20.30.40:5000'
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
You can use the `configure` block when initializing your app, for instance in a
|
79
|
+
Rails initializer.
|
80
|
+
|
81
|
+
Note that options, passed directly into `Session` constructor override the configuration options.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
Sixpack.configure do |config|
|
85
|
+
config.base_url = 'http://foo:5000'
|
86
|
+
end
|
87
|
+
|
88
|
+
s = Sixpack::Session.new(id, base_url: 'http://bar:6000')
|
89
|
+
|
90
|
+
expect(s.base_url).to eq 'http://bar:6000' #=> true
|
91
|
+
```
|
92
|
+
### Configuration options
|
93
|
+
|
94
|
+
* base_url - to set the base_url for the sixpack API server (can be
|
95
|
+
overriden in the Session constructor)
|
96
|
+
* user - set http basic authentication user
|
97
|
+
* password - set http basic authentication password
|
66
98
|
|
67
99
|
## Contributing
|
68
100
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sixpack
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :base_url, :user, :password
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@base_url = 'http://localhost:5000'
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_hash
|
10
|
+
config = {base_url: @base_url}
|
11
|
+
config[:user] = @user unless @user.nil?
|
12
|
+
config[:password] = @password unless @password.nil?
|
13
|
+
config
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/sixpack/version.rb
CHANGED
data/lib/sixpack.rb
CHANGED
@@ -1,30 +1,40 @@
|
|
1
1
|
require "addressable/uri"
|
2
2
|
require "net/http"
|
3
3
|
require "json"
|
4
|
-
require "uuid"
|
5
4
|
require "uri"
|
6
5
|
|
7
6
|
require "sixpack/version"
|
7
|
+
require "sixpack/configuration"
|
8
8
|
|
9
9
|
module Sixpack
|
10
|
-
extend self
|
11
10
|
|
12
|
-
|
11
|
+
class << self
|
13
12
|
|
14
|
-
|
13
|
+
def configuration
|
14
|
+
@configuration ||= Configuration.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure
|
18
|
+
yield(configuration)
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
def generate_client_id
|
22
|
+
SecureRandom.uuid
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
26
|
+
|
21
27
|
class Session
|
22
|
-
|
28
|
+
attr_reader :base_url
|
29
|
+
attr_accessor :client_id, :ip_address, :user_agent
|
23
30
|
|
24
31
|
def initialize(client_id=nil, options={}, params={})
|
25
|
-
|
26
|
-
options =
|
32
|
+
# options supplied directly will override the configured options
|
33
|
+
options = Sixpack.configuration.to_hash.merge(options)
|
34
|
+
|
27
35
|
@base_url = options[:base_url]
|
36
|
+
@user = options[:user]
|
37
|
+
@password = options[:password]
|
28
38
|
|
29
39
|
default_params = {:ip_address => nil, :user_agent => :nil}
|
30
40
|
params = default_params.merge(params)
|
@@ -39,32 +49,26 @@ module Sixpack
|
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
42
|
-
def participate(experiment_name, alternatives, force=nil
|
52
|
+
def participate(experiment_name, alternatives, force=nil)
|
43
53
|
if !(experiment_name =~ /^[a-z0-9][a-z0-9\-_ ]*$/)
|
44
|
-
raise ArgumentError, "Bad experiment_name"
|
54
|
+
raise ArgumentError, "Bad experiment_name, must be lowercase, start with an alphanumeric and contain alphanumerics, dashes and underscores"
|
45
55
|
end
|
46
56
|
|
47
57
|
if alternatives.length < 2
|
48
58
|
raise ArgumentError, "Must specify at least 2 alternatives"
|
49
59
|
end
|
50
60
|
|
51
|
-
if traffic_fraction.to_f < 0 || traffic_fraction > 1
|
52
|
-
raise ArgumentError, "Invalid Traffic Fraction"
|
53
|
-
end
|
54
|
-
|
55
61
|
alternatives.each { |alt|
|
56
62
|
if !(alt =~ /^[a-z0-9][a-z0-9\-_ ]*$/)
|
57
|
-
raise ArgumentError, "Bad alternative name: #{alt}"
|
63
|
+
raise ArgumentError, "Bad alternative name: #{alt}, must be lowercase, start with an alphanumeric and contain alphanumerics, dashes and underscores"
|
58
64
|
end
|
59
65
|
}
|
60
66
|
|
61
67
|
params = {
|
62
68
|
:client_id => @client_id,
|
63
69
|
:experiment => experiment_name,
|
64
|
-
:alternatives => alternatives
|
65
|
-
:traffic_fraction => traffic_fraction
|
70
|
+
:alternatives => alternatives
|
66
71
|
}
|
67
|
-
|
68
72
|
if !force.nil? && alternatives.include?(force)
|
69
73
|
return {"status" => "ok", "alternative" => {"name" => force}, "experiment" => {"version" => 0, "name" => experiment_name}, "client_id" => @client_id}
|
70
74
|
end
|
@@ -96,7 +100,7 @@ module Sixpack
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def get_response(endpoint, params)
|
99
|
-
uri = URI.parse(@base_url)
|
103
|
+
uri = URI.parse(@base_url)
|
100
104
|
http = Net::HTTP.new(uri.host, uri.port)
|
101
105
|
|
102
106
|
if uri.scheme == "https"
|
@@ -109,17 +113,26 @@ module Sixpack
|
|
109
113
|
query = Addressable::URI.form_encode(self.build_params(params))
|
110
114
|
|
111
115
|
begin
|
112
|
-
|
113
|
-
|
116
|
+
req = Net::HTTP::Get.new(uri.path + endpoint + "?" + query)
|
117
|
+
# basic auth
|
118
|
+
if @user && @password
|
119
|
+
req.basic_auth(@user, @password)
|
114
120
|
end
|
121
|
+
res = http.request(req)
|
115
122
|
rescue
|
116
123
|
return {"status" => "failed", "error" => "http error"}
|
117
124
|
end
|
118
125
|
if res.code == "500"
|
119
126
|
{"status" => "failed", "response" => res.body}
|
120
127
|
else
|
121
|
-
|
128
|
+
parse_response(res)
|
122
129
|
end
|
123
130
|
end
|
131
|
+
|
132
|
+
def parse_response(res)
|
133
|
+
JSON.parse(res.body)
|
134
|
+
rescue JSON::ParserError
|
135
|
+
{"status" => "failed", "response" => res.body}
|
136
|
+
end
|
124
137
|
end
|
125
138
|
end
|
data/sixpack.gemspec
CHANGED
data/spec/lib/sixpack_spec.rb
CHANGED
@@ -2,62 +2,65 @@ require 'redis'
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Sixpack do
|
5
|
+
RSpec.describe Sixpack do
|
6
6
|
before(:each) do
|
7
7
|
redis = Redis.new
|
8
|
-
redis.
|
9
|
-
|
8
|
+
redis.flushdb
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'configuration' do
|
12
|
+
it 'should contain default base_url' do
|
13
|
+
s = Sixpack::Session.new("foo")
|
14
|
+
expect(s.base_url).to eq 'http://localhost:5000'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should allow specifying the base_url in Session options' do
|
18
|
+
s = Sixpack::Session.new("foo", base_url: 'http://0.0.0.0:5555')
|
19
|
+
expect(s.base_url).to eq 'http://0.0.0.0:5555'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should allow specifying the base_url in configuration block' do
|
23
|
+
Sixpack.configure do |config|
|
24
|
+
config.base_url = 'http://4.4.4.4'
|
25
|
+
end
|
26
|
+
s = Sixpack::Session.new("foo")
|
27
|
+
expect(s.base_url).to eq 'http://4.4.4.4'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'session base_url should override configuration base_url' do
|
31
|
+
Sixpack.configure do |config|
|
32
|
+
config.base_url = 'http://4.4.4.4'
|
33
|
+
end
|
34
|
+
s = Sixpack::Session.new("foo", base_url: 'http://5.5.5.5')
|
35
|
+
expect(s.base_url).to eq 'http://5.5.5.5'
|
10
36
|
end
|
11
37
|
end
|
12
38
|
|
13
39
|
it "should return an alternative for participate" do
|
14
40
|
sess = Sixpack::Session.new("mike")
|
15
41
|
resp = sess.participate('show-bieber', ['trolled', 'not-trolled'])
|
16
|
-
['trolled', 'not-trolled'].
|
42
|
+
expect(['trolled', 'not-trolled']).to include(resp["alternative"]["name"])
|
17
43
|
end
|
18
44
|
|
19
45
|
it "should return the correct alternative for participate with force" do
|
20
46
|
sess = Sixpack::Session.new("mike")
|
21
47
|
alt = sess.participate('show-bieber', ['trolled', 'not-trolled'], "trolled")["alternative"]["name"]
|
22
|
-
alt.
|
48
|
+
expect(alt).to eq "trolled"
|
23
49
|
|
24
|
-
|
25
|
-
|
50
|
+
alt = sess.participate('show-bieber', ['trolled', 'not-trolled'], "not-trolled")["alternative"]["name"]
|
51
|
+
expect(alt).to eq "not-trolled"
|
26
52
|
end
|
27
53
|
|
28
54
|
it "should allow ip and user agent to be passed to a session" do
|
29
55
|
params = {:ip_address => '8.8.8.8', :user_agent => 'FirChromari'}
|
30
56
|
session = Sixpack::Session.new('client_id', {}, params)
|
31
|
-
session.ip_address.
|
32
|
-
session.user_agent.
|
57
|
+
expect(session.ip_address).to eq '8.8.8.8'
|
58
|
+
expect(session.user_agent).to eq'FirChromari'
|
33
59
|
end
|
34
60
|
|
35
61
|
it "should auto generate a client_id" do
|
36
62
|
sess = Sixpack::Session.new
|
37
|
-
sess.client_id.length.
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should return ok for convert" do
|
41
|
-
sess = Sixpack::Session.new("mike")
|
42
|
-
alternative = sess.participate('show-bieber', ['trolled', 'not-trolled'])
|
43
|
-
sess.convert("show-bieber")["status"].should == "ok"
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should return ok for multiple_converts" do
|
47
|
-
sess = Sixpack::Session.new("mike")
|
48
|
-
sess.participate('show-bieber', ['trolled', 'not-trolled'])
|
49
|
-
sess.convert("show-bieber")["status"].should == "ok"
|
50
|
-
sess.convert("show-bieber")["status"].should == "ok"
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should not return ok for convert with new id" do
|
54
|
-
sess = Sixpack::Session.new("unknown_id")
|
55
|
-
sess.convert("show-bieber")["status"].should == "failed"
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should not return ok for convert with new experiment" do
|
59
|
-
sess = Sixpack::Session.new
|
60
|
-
sess.convert("show-blieber")['status'].should == "failed"
|
63
|
+
expect(sess.client_id.length).to eq 36
|
61
64
|
end
|
62
65
|
|
63
66
|
it "should not allow bad experiment names" do
|
@@ -67,11 +70,12 @@ describe Sixpack do
|
|
67
70
|
}.to raise_error
|
68
71
|
end
|
69
72
|
|
70
|
-
it "should not
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
it "should not try parse bad response body data" do
|
74
|
+
sess = Sixpack::Session.new
|
75
|
+
response = double(body: 'something unexpected', code: 200)
|
76
|
+
allow_any_instance_of(Net::HTTP).to receive(:get).and_return(response)
|
77
|
+
res = sess.participate('show-bieber', ['trolled', 'not-trolled'])
|
78
|
+
expect(res["status"]).to eq('failed')
|
75
79
|
end
|
76
80
|
|
77
81
|
it "should not allow bad alternatives names" do
|
@@ -86,27 +90,4 @@ describe Sixpack do
|
|
86
90
|
}.to raise_error
|
87
91
|
end
|
88
92
|
|
89
|
-
it "should work" do
|
90
|
-
session = Sixpack::Session.new
|
91
|
-
session.convert("testing")["status"].should == "failed"
|
92
|
-
alt_one = session.participate("testing", ["one", "two"])["alternative"]
|
93
|
-
3.times do |n|
|
94
|
-
session.participate("testing", ["one", "two"])["alternative"].should == alt_one
|
95
|
-
end
|
96
|
-
session.convert("testing")["status"].should == "ok"
|
97
|
-
|
98
|
-
old_client_id = session.client_id
|
99
|
-
session.client_id = Sixpack::generate_client_id()
|
100
|
-
session.convert("testing")["status"].should == "failed"
|
101
|
-
alt_two = session.participate("testing", ["one", "two"])["alternative"]
|
102
|
-
3.times do |n|
|
103
|
-
session.participate("testing", ["one", "two"])["alternative"].should == alt_two
|
104
|
-
end
|
105
|
-
session.convert("testing")["status"].should == "ok"
|
106
|
-
|
107
|
-
session = Sixpack::Session.new old_client_id
|
108
|
-
3.times do |n|
|
109
|
-
session.participate("testing", ["one", "two"])["alternative"].should == alt_one
|
110
|
-
end
|
111
|
-
end
|
112
93
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sixpack-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SeatGeek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ! '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: uuid
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ! '>='
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ! '>='
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: addressable
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,12 +88,14 @@ extensions: []
|
|
102
88
|
extra_rdoc_files: []
|
103
89
|
files:
|
104
90
|
- .gitignore
|
91
|
+
- .rspec
|
105
92
|
- .travis.yml
|
106
93
|
- Gemfile
|
107
94
|
- LICENSE
|
108
95
|
- README.md
|
109
96
|
- Rakefile
|
110
97
|
- lib/sixpack.rb
|
98
|
+
- lib/sixpack/configuration.rb
|
111
99
|
- lib/sixpack/version.rb
|
112
100
|
- sixpack.gemspec
|
113
101
|
- spec/lib/sixpack_spec.rb
|