vanity 2.0.0.beta8 → 2.0.0.beta9
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.
- data/.travis.yml +4 -2
- data/Appraisals +1 -1
- data/Gemfile +2 -1
- data/Gemfile.lock +4 -1
- data/gemfiles/rails32.gemfile +3 -2
- data/gemfiles/rails32.gemfile.lock +4 -5
- data/gemfiles/rails4.gemfile +2 -1
- data/gemfiles/rails4.gemfile.lock +3 -1
- data/gemfiles/rails41.gemfile +2 -1
- data/gemfiles/rails41.gemfile.lock +3 -1
- data/gemfiles/rails42.gemfile +2 -1
- data/gemfiles/rails42.gemfile.lock +3 -1
- data/lib/vanity.rb +11 -5
- data/lib/vanity/adapters.rb +20 -0
- data/lib/vanity/adapters/abstract_adapter.rb +0 -18
- data/lib/vanity/autoconnect.rb +1 -0
- data/lib/vanity/configuration.rb +211 -0
- data/lib/vanity/connection.rb +100 -0
- data/lib/vanity/frameworks.rb +2 -0
- data/lib/vanity/frameworks/rails.rb +7 -5
- data/lib/vanity/helpers.rb +1 -0
- data/{config → lib/vanity}/locales/vanity.en.yml +0 -0
- data/{config → lib/vanity}/locales/vanity.pt-BR.yml +0 -0
- data/lib/vanity/playground.rb +138 -338
- data/lib/vanity/vanity.rb +166 -0
- data/lib/vanity/version.rb +1 -1
- data/test/configuration_test.rb +90 -0
- data/test/connection_test.rb +46 -0
- data/test/data/redis.yml.url +2 -0
- data/test/data/vanity.yml.activerecord +6 -0
- data/test/data/vanity.yml.mock +4 -0
- data/test/data/vanity.yml.redis +5 -0
- data/test/data/vanity.yml.redis-erb +3 -0
- data/test/experiment/ab_test.rb +1 -1
- data/test/experiment/base_test.rb +1 -1
- data/test/frameworks/rails/rails_test.rb +34 -30
- data/test/metric/remote_test.rb +8 -8
- data/test/playground_test.rb +1 -27
- data/test/templates_test.rb +3 -2
- data/test/test_helper.rb +24 -12
- data/test/vanity_test.rb +130 -0
- metadata +25 -5
@@ -0,0 +1,166 @@
|
|
1
|
+
#
|
2
|
+
# Run time configuration and helpers
|
3
|
+
#
|
4
|
+
module Vanity
|
5
|
+
# Returns the current configuration.
|
6
|
+
#
|
7
|
+
# @see Vanity::Configuration
|
8
|
+
# @since 2.0.0
|
9
|
+
def self.configuration(set_if_needed=true)
|
10
|
+
if @configuration
|
11
|
+
@configuration
|
12
|
+
elsif set_if_needed
|
13
|
+
configure!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# @since 2.0.0
|
18
|
+
def self.configure!
|
19
|
+
@configuration = Configuration.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# @since 2.0.0
|
23
|
+
def self.reset!
|
24
|
+
@configuration = nil
|
25
|
+
configuration
|
26
|
+
end
|
27
|
+
|
28
|
+
# This is the preferred way to configure Vanity.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# Vanity.configure do |config|
|
32
|
+
# config.use_js = true
|
33
|
+
# end
|
34
|
+
# @since 2.0.0
|
35
|
+
def self.configure
|
36
|
+
yield(configuration)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @since 2.0.0
|
40
|
+
def self.logger
|
41
|
+
configuration.logger
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the Vanity context. For example, when using Rails this would be
|
45
|
+
# the current controller, which can be used to get/set the vanity identity.
|
46
|
+
def self.context
|
47
|
+
Thread.current[:vanity_context]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sets the Vanity context. For example, when using Rails this would be
|
51
|
+
# set by the set_vanity_context before filter (via Vanity::Rails#use_vanity).
|
52
|
+
def self.context=(context)
|
53
|
+
Thread.current[:vanity_context] = context
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Datastore connection management
|
58
|
+
#
|
59
|
+
|
60
|
+
# Returns the current connection. Establishes new connection is necessary.
|
61
|
+
#
|
62
|
+
# @since 2.0.0
|
63
|
+
def self.connection(connect_if_needed=true)
|
64
|
+
if @connection
|
65
|
+
@connection
|
66
|
+
elsif connect_if_needed
|
67
|
+
connect!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# This is the preferred way to programmatically create a new connection (or
|
72
|
+
# switch to a new connection). If no connection was established, the
|
73
|
+
# playground will create a new one by calling this method with no arguments.
|
74
|
+
#
|
75
|
+
# @since 2.0.0
|
76
|
+
# @see Vanity::Connection
|
77
|
+
def self.connect!(spec_or_nil=nil)
|
78
|
+
spec_or_nil ||= configuration.connection_params
|
79
|
+
|
80
|
+
# Legacy redis.yml fallback
|
81
|
+
if spec_or_nil.nil?
|
82
|
+
redis_url = configuration.redis_url_from_file
|
83
|
+
|
84
|
+
if redis_url
|
85
|
+
spec_or_nil = redis_url
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Legacy special config variables permitted in connection spec
|
90
|
+
update_configuration_from_connection_params(spec_or_nil)
|
91
|
+
|
92
|
+
@connection = Connection.new(spec_or_nil)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Destroys a connection
|
96
|
+
#
|
97
|
+
# @since 2.0.0
|
98
|
+
def self.disconnect!
|
99
|
+
if @connection
|
100
|
+
@connection.disconnect!
|
101
|
+
@connection = nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.reconnect!
|
106
|
+
disconnect!
|
107
|
+
connect!
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Experiment metadata
|
112
|
+
#
|
113
|
+
|
114
|
+
# The playground instance.
|
115
|
+
#
|
116
|
+
# @see Vanity::Playground
|
117
|
+
def self.playground(load_if_needed=true)
|
118
|
+
if @playground
|
119
|
+
@playground
|
120
|
+
elsif load_if_needed
|
121
|
+
load!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Loads all metrics and experiments. Called during initialization. In the
|
126
|
+
# case of Rails, use the Rails logger and look for templates at
|
127
|
+
# app/views/vanity.
|
128
|
+
#
|
129
|
+
# @since 2.0.0
|
130
|
+
def self.load!
|
131
|
+
@playground = Playground.new
|
132
|
+
end
|
133
|
+
|
134
|
+
# @since 2.0.0
|
135
|
+
def self.unload!
|
136
|
+
@playground = nil
|
137
|
+
end
|
138
|
+
|
139
|
+
# Reloads all metrics and experiments. Rails calls this for each request in
|
140
|
+
# development mode.
|
141
|
+
#
|
142
|
+
# @since 2.0.0
|
143
|
+
def self.reload!
|
144
|
+
unload!
|
145
|
+
load!
|
146
|
+
end
|
147
|
+
|
148
|
+
class << self
|
149
|
+
# @since 2.0.0
|
150
|
+
attr_writer :configuration
|
151
|
+
|
152
|
+
# @since 2.0.0
|
153
|
+
attr_writer :playground
|
154
|
+
|
155
|
+
# @since 2.0.0
|
156
|
+
attr_writer :connection
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def update_configuration_from_connection_params(spec_or_nil) # # :nodoc:
|
161
|
+
return unless spec_or_nil.respond_to?(:has_key?)
|
162
|
+
|
163
|
+
configuration.collecting = spec_or_nil[:collecting] if spec_or_nil.has_key?(:collecting)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/vanity/version.rb
CHANGED
@@ -0,0 +1,90 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Vanity::Configuration do
|
4
|
+
let(:config) { Vanity::Configuration.new }
|
5
|
+
|
6
|
+
it "returns default values" do
|
7
|
+
assert_equal Vanity::Configuration.new.collecting, Vanity::Configuration::DEFAULTS[:collecting]
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "overriding defaults" do
|
11
|
+
it "returns overridden values" do
|
12
|
+
config.collecting = true
|
13
|
+
assert_equal config.collecting, true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "connection_params" do
|
18
|
+
before do
|
19
|
+
FakeFS.activate!
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
FakeFS.deactivate!
|
24
|
+
FakeFS::FileSystem.clear
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "using the default config file & path" do
|
28
|
+
it "returns the connection params" do
|
29
|
+
FileUtils.mkpath "./config"
|
30
|
+
File.open("./config/vanity.yml", "w") do |f|
|
31
|
+
f.write VanityTestHelpers::VANITY_CONFIGS["vanity.yml.mock"]
|
32
|
+
end
|
33
|
+
|
34
|
+
mock_connection_hash = { adapter: "mock" }
|
35
|
+
assert_equal mock_connection_hash, config.connection_params
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "accepts a file name" do
|
40
|
+
FileUtils.mkpath "./config"
|
41
|
+
File.open("./config/vanity.yml", "w") do |f|
|
42
|
+
f.write VanityTestHelpers::VANITY_CONFIGS["vanity.yml.mock"]
|
43
|
+
end
|
44
|
+
|
45
|
+
mock_connection_hash = { adapter: "mock" }
|
46
|
+
assert_equal mock_connection_hash, config.connection_params("vanity.yml")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns connection strings" do
|
50
|
+
FileUtils.mkpath "./config"
|
51
|
+
File.open("./config/redis.yml", "w") do |f|
|
52
|
+
f.write VanityTestHelpers::VANITY_CONFIGS["redis.yml.url"]
|
53
|
+
end
|
54
|
+
|
55
|
+
mock_connection_string = "localhost:6379/15"
|
56
|
+
assert_equal mock_connection_string, config.connection_params("redis.yml")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns nil if the file doesn't exist" do
|
60
|
+
FileUtils.mkpath "./config"
|
61
|
+
assert_nil config.connection_params
|
62
|
+
end
|
63
|
+
|
64
|
+
it "raises an error if the environment isn't configured" do
|
65
|
+
FileUtils.mkpath "./config"
|
66
|
+
File.open("./config/vanity.yml", "w") do |f|
|
67
|
+
f.write VanityTestHelpers::VANITY_CONFIGS["vanity.yml.mock"]
|
68
|
+
end
|
69
|
+
|
70
|
+
config.environment = "staging"
|
71
|
+
assert_raises(Vanity::Configuration::MissingEnvironment) {
|
72
|
+
config.connection_params
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
it "symbolizes hash keys" do
|
77
|
+
FileUtils.mkpath "./config"
|
78
|
+
File.open("./config/vanity.yml", "w") do |f|
|
79
|
+
f.write VanityTestHelpers::VANITY_CONFIGS["vanity.yml.activerecord"]
|
80
|
+
end
|
81
|
+
|
82
|
+
ar_connection_values = [:adapter, :active_record_adapter]
|
83
|
+
assert_equal ar_connection_values, config.connection_params.keys
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "setup_locales" do
|
88
|
+
it "adds vanity locales to the gem"
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Vanity::Connection do
|
4
|
+
describe "#new" do
|
5
|
+
it "establishes connection with default specification" do
|
6
|
+
Vanity::Adapters.expects(:establish_connection).with(adapter: "redis")
|
7
|
+
Vanity::Connection.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "establishes connection given a connection specification" do
|
11
|
+
Vanity::Adapters.expects(:establish_connection).with(adapter: "mock")
|
12
|
+
Vanity::Connection.new(adapter: "mock")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "can skip connection" do
|
16
|
+
Vanity::Autoconnect.stubs(:playground_should_autoconnect?).returns(false)
|
17
|
+
connection = Vanity::Connection.new(adapter: "mock")
|
18
|
+
assert !connection.connected?
|
19
|
+
end
|
20
|
+
|
21
|
+
it "parses from a string" do
|
22
|
+
Vanity::Adapters.expects(:establish_connection).with(
|
23
|
+
adapter: 'redis',
|
24
|
+
username: 'user',
|
25
|
+
password: 'secrets',
|
26
|
+
host: 'redis.local',
|
27
|
+
port: 6379,
|
28
|
+
path: '/5',
|
29
|
+
params: nil
|
30
|
+
)
|
31
|
+
Vanity::Connection.new("redis://user:secrets@redis.local:6379/5")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises an error for invalid specification hashes" do
|
35
|
+
assert_raises(Vanity::Connection::InvalidSpecification) {
|
36
|
+
Vanity::Connection.new("adapter" => "mock")
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "allows a redis connection to be specified" do
|
41
|
+
redis = stub("Redis")
|
42
|
+
Vanity::Adapters.expects(:establish_connection).with(adapter: :redis, redis: redis)
|
43
|
+
Vanity::Connection.new(redis: redis)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/test/experiment/ab_test.rb
CHANGED
@@ -138,7 +138,7 @@ class AbTestTest < ActionController::TestCase
|
|
138
138
|
# -- use_js! --
|
139
139
|
|
140
140
|
def test_choose_does_not_record_participant_when_using_js
|
141
|
-
Vanity.
|
141
|
+
Vanity.configuration.use_js = true
|
142
142
|
ids = (0...10).to_a
|
143
143
|
new_ab_test :foobar do
|
144
144
|
alternatives "foo", "bar"
|
@@ -111,7 +111,7 @@ describe Vanity::Experiment::Base do
|
|
111
111
|
new_ab_test(:ice_cream_flavor) { metrics :happiness }
|
112
112
|
end
|
113
113
|
|
114
|
-
|
114
|
+
vanity_reset
|
115
115
|
metric :happiness
|
116
116
|
new_ab_test(:ice_cream_flavor) { metrics :happiness }
|
117
117
|
assert_equal past.to_time.to_i, experiment(:ice_cream_flavor).created_at.to_i
|
@@ -1,20 +1,20 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
describe "Rails
|
3
|
+
describe "deprecated Rails load_path and deprecated connection configuration" do
|
4
4
|
|
5
5
|
it "load_path" do
|
6
|
-
assert_equal
|
6
|
+
assert_equal "./experiments", load_rails("", <<-RB)
|
7
7
|
$stdout << Vanity.playground.load_path
|
8
8
|
RB
|
9
9
|
end
|
10
10
|
|
11
|
-
it "
|
12
|
-
assert_equal
|
11
|
+
it "settable load_path" do
|
12
|
+
assert_equal "predictions", load_rails(%Q{\nVanity.playground.load_path = "predictions"\n}, <<-RB)
|
13
13
|
$stdout << Vanity.playground.load_path
|
14
14
|
RB
|
15
15
|
end
|
16
16
|
|
17
|
-
it "
|
17
|
+
it "absolute load_path" do
|
18
18
|
Dir.mktmpdir do |dir|
|
19
19
|
assert_equal dir, load_rails(%Q{\nVanity.playground.load_path = "#{dir}"\n}, <<-RB)
|
20
20
|
$stdout << Vanity.playground.load_path
|
@@ -23,19 +23,19 @@ $stdout << Vanity.playground.load_path
|
|
23
23
|
end
|
24
24
|
|
25
25
|
if ENV['DB'] == 'redis'
|
26
|
-
it "
|
26
|
+
it "default connection" do
|
27
27
|
assert_equal "redis://127.0.0.1:6379/0", load_rails("", <<-RB)
|
28
28
|
$stdout << Vanity.playground.connection
|
29
29
|
RB
|
30
30
|
end
|
31
31
|
|
32
|
-
it "
|
32
|
+
it "connection from string" do
|
33
33
|
assert_equal "redis://192.168.1.1:6379/5", load_rails(%Q{\nVanity.playground.establish_connection "redis://192.168.1.1:6379/5"\n}, <<-RB)
|
34
34
|
$stdout << Vanity.playground.connection
|
35
35
|
RB
|
36
36
|
end
|
37
37
|
|
38
|
-
it "
|
38
|
+
it "connection from yaml" do
|
39
39
|
begin
|
40
40
|
FileUtils.mkpath "tmp/config"
|
41
41
|
@original_env = ENV["RAILS_ENV"]
|
@@ -57,7 +57,7 @@ $stdout << Vanity.playground.connection
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
it "
|
60
|
+
it "connection from yaml url" do
|
61
61
|
begin
|
62
62
|
FileUtils.mkpath "tmp/config"
|
63
63
|
@original_env = ENV["RAILS_ENV"]
|
@@ -76,7 +76,7 @@ $stdout << Vanity.playground.connection
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
it "
|
79
|
+
it "connection from yaml with erb" do
|
80
80
|
begin
|
81
81
|
FileUtils.mkpath "tmp/config"
|
82
82
|
@original_env = ENV["RAILS_ENV"]
|
@@ -99,13 +99,13 @@ $stdout << Vanity.playground.connection
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
it "
|
102
|
+
it "connection from redis yml" do
|
103
103
|
begin
|
104
104
|
FileUtils.mkpath "tmp/config"
|
105
105
|
yml = File.open("tmp/config/redis.yml", "w")
|
106
106
|
yml << "production: internal.local:6379\n"
|
107
107
|
yml.flush
|
108
|
-
|
108
|
+
assert_match %r{redis://internal.local:6379/0\Z}, load_rails("", <<-RB)
|
109
109
|
$stdout << Vanity.playground.connection
|
110
110
|
RB
|
111
111
|
ensure
|
@@ -115,7 +115,7 @@ $stdout << Vanity.playground.connection
|
|
115
115
|
end
|
116
116
|
|
117
117
|
if ENV['DB'] == 'mongo'
|
118
|
-
it "
|
118
|
+
it "mongo connection from yaml" do
|
119
119
|
begin
|
120
120
|
FileUtils.mkpath "tmp/config"
|
121
121
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
@@ -136,8 +136,8 @@ $stdout << Vanity.playground.connection
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
unless ENV['CI'] == 'true' #
|
140
|
-
it "
|
139
|
+
unless ENV['CI'] == 'true' # See http://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
|
140
|
+
it "mongodb replica set connection" do
|
141
141
|
begin
|
142
142
|
FileUtils.mkpath "tmp/config"
|
143
143
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
@@ -165,7 +165,7 @@ $stdout << Vanity.playground.connection.mongo.class
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
it "
|
168
|
+
it "connection from yaml missing" do
|
169
169
|
begin
|
170
170
|
FileUtils.mkpath "tmp/config"
|
171
171
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
@@ -176,7 +176,7 @@ production:
|
|
176
176
|
end
|
177
177
|
|
178
178
|
assert_equal "No configuration for development", load_rails("\nbegin\n", <<-RB, "development")
|
179
|
-
rescue
|
179
|
+
rescue => e
|
180
180
|
$stdout << e.message
|
181
181
|
end
|
182
182
|
RB
|
@@ -185,7 +185,7 @@ end
|
|
185
185
|
end
|
186
186
|
end
|
187
187
|
|
188
|
-
it "
|
188
|
+
it "collection from vanity yaml" do
|
189
189
|
begin
|
190
190
|
FileUtils.mkpath "tmp/config"
|
191
191
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
@@ -203,42 +203,46 @@ $stdout << Vanity.playground.collecting?
|
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
206
|
-
it "
|
206
|
+
it "collection true in production by default" do
|
207
207
|
assert_equal "true", load_rails("", <<-RB)
|
208
208
|
$stdout << Vanity.playground.collecting?
|
209
209
|
RB
|
210
210
|
end
|
211
211
|
|
212
|
-
it "
|
212
|
+
it "collection false in production when configured" do
|
213
213
|
assert_equal "false", load_rails("\nVanity.playground.collecting = false\n", <<-RB)
|
214
214
|
$stdout << Vanity.playground.collecting?
|
215
215
|
RB
|
216
216
|
end
|
217
217
|
|
218
|
-
it "
|
218
|
+
it "collection true in development by default" do
|
219
219
|
assert_equal "true", load_rails("", <<-RB, "development")
|
220
220
|
$stdout << Vanity.playground.collecting?
|
221
221
|
RB
|
222
222
|
end
|
223
223
|
|
224
|
-
it "
|
224
|
+
it "collection true in development when configured" do
|
225
225
|
assert_equal "true", load_rails("\nVanity.playground.collecting = true\n", <<-RB, "development")
|
226
226
|
$stdout << Vanity.playground.collecting?
|
227
227
|
RB
|
228
228
|
end
|
229
229
|
|
230
|
-
it "
|
230
|
+
it "playground loads experiments if connected" do
|
231
231
|
assert_equal "{}", load_rails("", <<-RB)
|
232
|
-
$stdout << Vanity.playground.
|
232
|
+
$stdout << Vanity.playground.experiments.inspect
|
233
233
|
RB
|
234
234
|
end
|
235
235
|
|
236
|
-
it "
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
236
|
+
it "playground does not instantiate connection if disabled" do
|
237
|
+
begin
|
238
|
+
ENV['VANITY_DISABLED'] = '1'
|
239
|
+
assert_equal "false", load_rails("", <<-RB)
|
240
|
+
Vanity.playground.experiments.inspect
|
241
|
+
$stdout << !!Vanity.playground.connected?
|
242
|
+
RB
|
243
|
+
ensure
|
244
|
+
ENV['VANITY_DISABLED'] = nil
|
245
|
+
end
|
242
246
|
end
|
243
247
|
|
244
248
|
def load_rails(before_initialize, after_initialize, env="production")
|