vanity 3.1.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/linting.yml +28 -0
- data/.github/workflows/test.yml +3 -6
- data/.rubocop.yml +114 -0
- data/.rubocop_todo.yml +67 -0
- data/Appraisals +9 -31
- data/CHANGELOG +5 -0
- data/Gemfile +7 -3
- data/Gemfile.lock +31 -3
- data/README.md +4 -9
- data/Rakefile +25 -24
- data/bin/vanity +1 -1
- data/doc/configuring.textile +1 -0
- data/gemfiles/rails52.gemfile +6 -3
- data/gemfiles/rails52.gemfile.lock +34 -9
- data/gemfiles/rails60.gemfile +6 -3
- data/gemfiles/rails60.gemfile.lock +34 -9
- data/gemfiles/rails61.gemfile +6 -3
- data/gemfiles/rails61.gemfile.lock +34 -9
- data/lib/generators/vanity/migration_generator.rb +5 -7
- data/lib/vanity/adapters/abstract_adapter.rb +43 -45
- data/lib/vanity/adapters/active_record_adapter.rb +30 -30
- data/lib/vanity/adapters/mock_adapter.rb +14 -18
- data/lib/vanity/adapters/mongodb_adapter.rb +73 -69
- data/lib/vanity/adapters/redis_adapter.rb +19 -27
- data/lib/vanity/adapters.rb +1 -1
- data/lib/vanity/autoconnect.rb +6 -7
- data/lib/vanity/commands/list.rb +7 -7
- data/lib/vanity/commands/report.rb +18 -22
- data/lib/vanity/configuration.rb +19 -19
- data/lib/vanity/connection.rb +12 -14
- data/lib/vanity/experiment/ab_test.rb +82 -70
- data/lib/vanity/experiment/alternative.rb +3 -5
- data/lib/vanity/experiment/base.rb +24 -19
- data/lib/vanity/experiment/bayesian_bandit_score.rb +7 -13
- data/lib/vanity/experiment/definition.rb +6 -6
- data/lib/vanity/frameworks/rails.rb +39 -39
- data/lib/vanity/frameworks.rb +2 -2
- data/lib/vanity/helpers.rb +1 -1
- data/lib/vanity/metric/active_record.rb +21 -19
- data/lib/vanity/metric/base.rb +22 -23
- data/lib/vanity/metric/google_analytics.rb +6 -9
- data/lib/vanity/metric/remote.rb +3 -5
- data/lib/vanity/playground.rb +3 -6
- data/lib/vanity/vanity.rb +8 -12
- data/lib/vanity/version.rb +1 -1
- data/test/adapters/active_record_adapter_test.rb +1 -5
- data/test/adapters/mock_adapter_test.rb +0 -2
- data/test/adapters/mongodb_adapter_test.rb +1 -5
- data/test/adapters/redis_adapter_test.rb +2 -3
- data/test/adapters/shared_tests.rb +9 -12
- data/test/autoconnect_test.rb +3 -3
- data/test/cli_test.rb +0 -1
- data/test/configuration_test.rb +18 -34
- data/test/connection_test.rb +3 -3
- data/test/dummy/Rakefile +1 -1
- data/test/dummy/app/controllers/use_vanity_controller.rb +12 -8
- data/test/dummy/app/mailers/vanity_mailer.rb +3 -3
- data/test/dummy/config/application.rb +1 -1
- data/test/dummy/config/boot.rb +3 -3
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/development.rb +0 -1
- data/test/dummy/config/environments/test.rb +1 -1
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/dummy/config.ru +1 -1
- data/test/dummy/script/rails +2 -2
- data/test/experiment/ab_test.rb +148 -154
- data/test/experiment/base_test.rb +48 -32
- data/test/frameworks/rails/action_controller_test.rb +25 -25
- data/test/frameworks/rails/action_mailer_test.rb +2 -2
- data/test/frameworks/rails/action_view_test.rb +5 -6
- data/test/frameworks/rails/rails_test.rb +147 -181
- data/test/helper_test.rb +2 -2
- data/test/metric/active_record_test.rb +174 -212
- data/test/metric/base_test.rb +21 -46
- data/test/metric/google_analytics_test.rb +17 -25
- data/test/metric/remote_test.rb +7 -10
- data/test/playground_test.rb +7 -14
- data/test/templates_test.rb +16 -20
- data/test/test_helper.rb +28 -29
- data/test/vanity_test.rb +4 -10
- data/test/web/rails/dashboard_test.rb +21 -21
- data/vanity.gemspec +8 -7
- metadata +28 -30
- data/gemfiles/rails42.gemfile +0 -33
- data/gemfiles/rails42.gemfile.lock +0 -265
- data/gemfiles/rails42_protected_attributes.gemfile +0 -34
- data/gemfiles/rails42_protected_attributes.gemfile.lock +0 -264
- data/gemfiles/rails51.gemfile +0 -33
- data/gemfiles/rails51.gemfile.lock +0 -285
@@ -1,259 +1,226 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
describe "deprecated Rails load_path and deprecated connection configuration" do
|
4
|
-
|
5
4
|
it "load_path" do
|
6
|
-
assert_equal "./experiments", load_rails("",
|
7
|
-
$stdout << Vanity.playground.load_path
|
5
|
+
assert_equal "./experiments", load_rails("", <<~RB)
|
6
|
+
$stdout << Vanity.playground.load_path
|
8
7
|
RB
|
9
8
|
end
|
10
9
|
|
11
10
|
it "settable load_path" do
|
12
|
-
assert_equal "predictions", load_rails(%
|
13
|
-
$stdout << Vanity.playground.load_path
|
11
|
+
assert_equal "predictions", load_rails(%{\nVanity.playground.load_path = "predictions"\n}, <<~RB)
|
12
|
+
$stdout << Vanity.playground.load_path
|
14
13
|
RB
|
15
14
|
end
|
16
15
|
|
17
16
|
it "absolute load_path" do
|
18
17
|
Dir.mktmpdir do |dir|
|
19
|
-
assert_equal dir, load_rails(%
|
20
|
-
$stdout << Vanity.playground.load_path
|
18
|
+
assert_equal dir, load_rails(%{\nVanity.playground.load_path = "#{dir}"\n}, <<~RB)
|
19
|
+
$stdout << Vanity.playground.load_path
|
21
20
|
RB
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
24
|
if ENV['DB'] == 'redis'
|
26
25
|
it "default connection" do
|
27
|
-
assert_equal "redis://127.0.0.1:6379/0", load_rails("",
|
28
|
-
$stdout << Vanity.playground.connection
|
26
|
+
assert_equal "redis://127.0.0.1:6379/0", load_rails("", <<~RB)
|
27
|
+
$stdout << Vanity.playground.connection
|
29
28
|
RB
|
30
29
|
end
|
31
30
|
|
32
31
|
it "connection from string" do
|
33
|
-
assert_equal "redis://192.168.1.1:6379/5", load_rails(%
|
34
|
-
$stdout << Vanity.playground.connection
|
32
|
+
assert_equal "redis://192.168.1.1:6379/5", load_rails(%{\nVanity.playground.establish_connection "redis://192.168.1.1:6379/5"\n}, <<~RB)
|
33
|
+
$stdout << Vanity.playground.connection
|
35
34
|
RB
|
36
35
|
end
|
37
36
|
|
38
37
|
it "connection from yaml" do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
RB
|
52
|
-
ensure
|
53
|
-
File.unlink "tmp/config/vanity.yml"
|
54
|
-
end
|
38
|
+
FileUtils.mkpath "tmp/config"
|
39
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
40
|
+
production:
|
41
|
+
adapter: redis
|
42
|
+
host: somehost
|
43
|
+
database: 15
|
44
|
+
YML
|
45
|
+
assert_equal "redis://somehost:6379/15", load_rails("", <<~RB, "production")
|
46
|
+
$stdout << Vanity.playground.connection
|
47
|
+
RB
|
48
|
+
ensure
|
49
|
+
File.unlink "tmp/config/vanity.yml"
|
55
50
|
end
|
56
51
|
|
57
52
|
it "connection from yaml url" do
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
RB
|
68
|
-
ensure
|
69
|
-
File.unlink "tmp/config/vanity.yml"
|
70
|
-
end
|
53
|
+
FileUtils.mkpath "tmp/config"
|
54
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
55
|
+
production: redis://somehost/15
|
56
|
+
YML
|
57
|
+
assert_equal "redis://somehost:6379/15", load_rails("", <<~RB, "production")
|
58
|
+
$stdout << Vanity.playground.connection
|
59
|
+
RB
|
60
|
+
ensure
|
61
|
+
File.unlink "tmp/config/vanity.yml"
|
71
62
|
end
|
72
63
|
|
73
64
|
it "connection from yaml with erb" do
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
ensure
|
88
|
-
ENV["REDIS_URL"] = @original_redis_url
|
89
|
-
File.unlink "tmp/config/vanity.yml"
|
90
|
-
end
|
65
|
+
FileUtils.mkpath "tmp/config"
|
66
|
+
# Pass storage URL through environment like heroku does
|
67
|
+
@original_redis_url = ENV["REDIS_URL"]
|
68
|
+
ENV["REDIS_URL"] = "redis://somehost:6379/15"
|
69
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
70
|
+
production: <%= ENV['REDIS_URL'] %>
|
71
|
+
YML
|
72
|
+
assert_equal "redis://somehost:6379/15", load_rails("", <<~RB, "production")
|
73
|
+
$stdout << Vanity.playground.connection
|
74
|
+
RB
|
75
|
+
ensure
|
76
|
+
ENV["REDIS_URL"] = @original_redis_url
|
77
|
+
File.unlink "tmp/config/vanity.yml"
|
91
78
|
end
|
92
79
|
|
93
80
|
it "connection from redis yml" do
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
File.unlink yml.path
|
104
|
-
end
|
81
|
+
FileUtils.mkpath "tmp/config"
|
82
|
+
yml = File.open("tmp/config/redis.yml", "w")
|
83
|
+
yml << "production: internal.local:6379\n"
|
84
|
+
yml.flush
|
85
|
+
assert_match %r{redis://internal.local:6379/0\Z}, load_rails("", <<~RB)
|
86
|
+
$stdout << Vanity.playground.connection
|
87
|
+
RB
|
88
|
+
ensure
|
89
|
+
File.unlink yml.path
|
105
90
|
end
|
106
91
|
end
|
107
92
|
|
108
93
|
if ENV['DB'] == 'mongo'
|
109
94
|
it "mongo connection from yaml" do
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
database: vanity_test
|
119
|
-
YML
|
120
|
-
end
|
95
|
+
FileUtils.mkpath "tmp/config"
|
96
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
97
|
+
mongodb:
|
98
|
+
adapter: mongodb
|
99
|
+
host: localhost
|
100
|
+
port: 27017
|
101
|
+
database: vanity_test
|
102
|
+
YML
|
121
103
|
|
122
|
-
|
123
|
-
$stdout << Vanity.playground.connection
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
104
|
+
assert_equal "mongodb://localhost:27017/vanity_test", load_rails("", <<~RB, "mongodb")
|
105
|
+
$stdout << Vanity.playground.connection
|
106
|
+
RB
|
107
|
+
ensure
|
108
|
+
File.unlink "tmp/config/vanity.yml"
|
128
109
|
end
|
129
110
|
|
130
111
|
unless ENV['CI'] == 'true' # See http://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
|
131
112
|
it "mongodb replica set connection" do
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
database: vanity_test
|
142
|
-
YML
|
143
|
-
end
|
113
|
+
FileUtils.mkpath "tmp/config"
|
114
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
115
|
+
mongodb:
|
116
|
+
adapter: mongodb
|
117
|
+
hosts:
|
118
|
+
- localhost
|
119
|
+
port: 27017
|
120
|
+
database: vanity_test
|
121
|
+
YML
|
144
122
|
|
145
|
-
|
146
|
-
$stdout << Vanity.playground.connection
|
147
|
-
|
123
|
+
assert_equal "mongodb://localhost:27017/vanity_test", load_rails("", <<~RB, "mongodb")
|
124
|
+
$stdout << Vanity.playground.connection
|
125
|
+
RB
|
148
126
|
|
149
|
-
|
150
|
-
$stdout << Vanity.playground.connection.mongo.class
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
end
|
127
|
+
assert_equal "Mongo::ReplSetConnection", load_rails("", <<~RB, "mongodb")
|
128
|
+
$stdout << Vanity.playground.connection.mongo.class
|
129
|
+
RB
|
130
|
+
ensure
|
131
|
+
File.unlink "tmp/config/vanity.yml"
|
155
132
|
end
|
156
133
|
end
|
157
134
|
end
|
158
135
|
|
159
136
|
it "connection from yaml missing" do
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
adapter: redis
|
166
|
-
YML
|
167
|
-
end
|
137
|
+
FileUtils.mkpath "tmp/config"
|
138
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
139
|
+
production:
|
140
|
+
adapter: redis
|
141
|
+
YML
|
168
142
|
|
169
|
-
|
170
|
-
rescue => e
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
143
|
+
assert_equal "No configuration for development", load_rails("\nbegin\n", <<~RB, "development")
|
144
|
+
rescue => e
|
145
|
+
$stdout << e.message
|
146
|
+
end
|
147
|
+
RB
|
148
|
+
ensure
|
149
|
+
File.unlink "tmp/config/vanity.yml"
|
177
150
|
end
|
178
151
|
|
179
152
|
it "collection from vanity yaml" do
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
RB
|
192
|
-
ensure
|
193
|
-
File.unlink "tmp/config/vanity.yml"
|
194
|
-
end
|
153
|
+
FileUtils.mkpath "tmp/config"
|
154
|
+
File.write("tmp/config/vanity.yml", <<~YML)
|
155
|
+
production:
|
156
|
+
collecting: false
|
157
|
+
adapter: mock
|
158
|
+
YML
|
159
|
+
assert_equal "false", load_rails("", <<~RB)
|
160
|
+
$stdout << Vanity.playground.collecting?
|
161
|
+
RB
|
162
|
+
ensure
|
163
|
+
File.unlink "tmp/config/vanity.yml"
|
195
164
|
end
|
196
165
|
|
197
166
|
it "collection true in production by default" do
|
198
|
-
assert_equal "true", load_rails("",
|
199
|
-
$stdout << Vanity.playground.collecting?
|
167
|
+
assert_equal "true", load_rails("", <<~RB)
|
168
|
+
$stdout << Vanity.playground.collecting?
|
200
169
|
RB
|
201
170
|
end
|
202
171
|
|
203
172
|
it "collection false in production when configured" do
|
204
|
-
assert_equal "false", load_rails("\nVanity.playground.collecting = false\n",
|
205
|
-
$stdout << Vanity.playground.collecting?
|
173
|
+
assert_equal "false", load_rails("\nVanity.playground.collecting = false\n", <<~RB)
|
174
|
+
$stdout << Vanity.playground.collecting?
|
206
175
|
RB
|
207
176
|
end
|
208
177
|
|
209
178
|
it "collection true in development by default" do
|
210
|
-
assert_equal "true", load_rails("",
|
211
|
-
$stdout << Vanity.playground.collecting?
|
179
|
+
assert_equal "true", load_rails("", <<~RB, "development")
|
180
|
+
$stdout << Vanity.playground.collecting?
|
212
181
|
RB
|
213
182
|
end
|
214
183
|
|
215
184
|
it "collection true in development when configured" do
|
216
|
-
assert_equal "true", load_rails("\nVanity.playground.collecting = true\n",
|
217
|
-
$stdout << Vanity.playground.collecting?
|
185
|
+
assert_equal "true", load_rails("\nVanity.playground.collecting = true\n", <<~RB, "development")
|
186
|
+
$stdout << Vanity.playground.collecting?
|
218
187
|
RB
|
219
188
|
end
|
220
189
|
|
221
190
|
it "playground loads experiments if connected" do
|
222
|
-
assert_equal "{}", load_rails("",
|
223
|
-
$stdout << Vanity.playground.experiments.inspect
|
191
|
+
assert_equal "{}", load_rails("", <<~RB)
|
192
|
+
$stdout << Vanity.playground.experiments.inspect
|
224
193
|
RB
|
225
194
|
end
|
226
195
|
|
227
196
|
it "playground does not instantiate connection if disabled" do
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
Vanity.playground.
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
ENV['VANITY_DISABLED'] = nil
|
236
|
-
end
|
197
|
+
ENV['VANITY_DISABLED'] = '1'
|
198
|
+
assert_equal "false", load_rails("", <<~RB)
|
199
|
+
Vanity.playground.experiments.inspect
|
200
|
+
$stdout << !!Vanity.playground.connected?
|
201
|
+
RB
|
202
|
+
ensure
|
203
|
+
ENV['VANITY_DISABLED'] = nil
|
237
204
|
end
|
238
205
|
|
239
|
-
def load_rails(before_initialize, after_initialize, env="production")
|
206
|
+
def load_rails(before_initialize, after_initialize, env = "production")
|
240
207
|
tmp = Tempfile.open("test.rb")
|
241
208
|
begin
|
242
|
-
code_setup =
|
243
|
-
$:.delete_if { |path| path[/gems\\/vanity-\\d/] }
|
244
|
-
$:.unshift File.expand_path("../lib")
|
245
|
-
RAILS_ROOT = File.expand_path(".")
|
209
|
+
code_setup = <<~RB
|
210
|
+
$:.delete_if { |path| path[/gems\\/vanity-\\d/] }
|
211
|
+
$:.unshift File.expand_path("../lib")
|
212
|
+
RAILS_ROOT = File.expand_path(".")
|
246
213
|
RB
|
247
214
|
code = code_setup
|
248
215
|
code += load_rails_3_or_4(env)
|
249
|
-
code += %
|
216
|
+
code += %{\nrequire "vanity"\n}
|
250
217
|
code += before_initialize
|
251
218
|
code += initialize_rails_3_or_4
|
252
219
|
code += after_initialize
|
253
220
|
tmp.write code
|
254
221
|
tmp.flush
|
255
222
|
Dir.chdir "tmp" do
|
256
|
-
open("| ruby #{tmp.path}").read
|
223
|
+
open("| ruby #{tmp.path}").read # rubocop:todo Security/Open
|
257
224
|
end
|
258
225
|
ensure
|
259
226
|
tmp.close!
|
@@ -261,30 +228,29 @@ RAILS_ROOT = File.expand_path(".")
|
|
261
228
|
end
|
262
229
|
|
263
230
|
def load_rails_3_or_4(env)
|
264
|
-
|
265
|
-
ENV['BUNDLE_GEMFILE'] ||= "#{ENV['BUNDLE_GEMFILE']}"
|
266
|
-
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
267
|
-
ENV['RAILS_ENV'] = ENV['RACK_ENV'] = "#{env}"
|
268
|
-
require "active_model/railtie"
|
269
|
-
require "action_controller/railtie"
|
231
|
+
<<~RB
|
232
|
+
ENV['BUNDLE_GEMFILE'] ||= "#{ENV['BUNDLE_GEMFILE']}"
|
233
|
+
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
234
|
+
ENV['RAILS_ENV'] = ENV['RACK_ENV'] = "#{env}"
|
235
|
+
require "active_model/railtie"
|
236
|
+
require "action_controller/railtie"
|
270
237
|
|
271
|
-
Bundler.require(:default)
|
238
|
+
Bundler.require(:default)
|
272
239
|
|
273
|
-
module Foo
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
end
|
240
|
+
module Foo
|
241
|
+
class Application < Rails::Application
|
242
|
+
config.active_support.deprecation = :notify
|
243
|
+
config.log_level = :fatal
|
244
|
+
config.eager_load = #{env == 'production'} if Rails::Application.respond_to?(:eager_load!)
|
245
|
+
ActiveSupport::Deprecation.silenced = true if ActiveSupport::Deprecation.respond_to?(:silenced) && ENV['CI']
|
246
|
+
end
|
247
|
+
end
|
281
248
|
RB
|
282
249
|
end
|
283
250
|
|
284
251
|
def initialize_rails_3_or_4
|
285
|
-
|
286
|
-
Foo::Application.initialize!
|
252
|
+
<<~RB
|
253
|
+
Foo::Application.initialize!
|
287
254
|
RB
|
288
255
|
end
|
289
|
-
|
290
256
|
end
|
data/test/helper_test.rb
CHANGED
@@ -9,7 +9,7 @@ describe Vanity::Helpers do
|
|
9
9
|
default "foo"
|
10
10
|
metrics :coolness
|
11
11
|
end
|
12
|
-
Vanity.track!(:coolness, :
|
12
|
+
Vanity.track!(:coolness, identity: 'quux')
|
13
13
|
|
14
14
|
assert_equal 1, experiment(:foobar).alternatives.sum(&:conversions)
|
15
15
|
end
|
@@ -21,7 +21,7 @@ describe Vanity::Helpers do
|
|
21
21
|
default "foo"
|
22
22
|
metrics :coolness
|
23
23
|
end
|
24
|
-
Vanity.track!(:coolness, :
|
24
|
+
Vanity.track!(:coolness, identity: 'quux', values: [2])
|
25
25
|
|
26
26
|
assert_equal 2, experiment(:foobar).alternatives.sum(&:conversions)
|
27
27
|
end
|