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.
Files changed (42) hide show
  1. data/.travis.yml +4 -2
  2. data/Appraisals +1 -1
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +4 -1
  5. data/gemfiles/rails32.gemfile +3 -2
  6. data/gemfiles/rails32.gemfile.lock +4 -5
  7. data/gemfiles/rails4.gemfile +2 -1
  8. data/gemfiles/rails4.gemfile.lock +3 -1
  9. data/gemfiles/rails41.gemfile +2 -1
  10. data/gemfiles/rails41.gemfile.lock +3 -1
  11. data/gemfiles/rails42.gemfile +2 -1
  12. data/gemfiles/rails42.gemfile.lock +3 -1
  13. data/lib/vanity.rb +11 -5
  14. data/lib/vanity/adapters.rb +20 -0
  15. data/lib/vanity/adapters/abstract_adapter.rb +0 -18
  16. data/lib/vanity/autoconnect.rb +1 -0
  17. data/lib/vanity/configuration.rb +211 -0
  18. data/lib/vanity/connection.rb +100 -0
  19. data/lib/vanity/frameworks.rb +2 -0
  20. data/lib/vanity/frameworks/rails.rb +7 -5
  21. data/lib/vanity/helpers.rb +1 -0
  22. data/{config → lib/vanity}/locales/vanity.en.yml +0 -0
  23. data/{config → lib/vanity}/locales/vanity.pt-BR.yml +0 -0
  24. data/lib/vanity/playground.rb +138 -338
  25. data/lib/vanity/vanity.rb +166 -0
  26. data/lib/vanity/version.rb +1 -1
  27. data/test/configuration_test.rb +90 -0
  28. data/test/connection_test.rb +46 -0
  29. data/test/data/redis.yml.url +2 -0
  30. data/test/data/vanity.yml.activerecord +6 -0
  31. data/test/data/vanity.yml.mock +4 -0
  32. data/test/data/vanity.yml.redis +5 -0
  33. data/test/data/vanity.yml.redis-erb +3 -0
  34. data/test/experiment/ab_test.rb +1 -1
  35. data/test/experiment/base_test.rb +1 -1
  36. data/test/frameworks/rails/rails_test.rb +34 -30
  37. data/test/metric/remote_test.rb +8 -8
  38. data/test/playground_test.rb +1 -27
  39. data/test/templates_test.rb +3 -2
  40. data/test/test_helper.rb +24 -12
  41. data/test/vanity_test.rb +130 -0
  42. 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
@@ -1,5 +1,5 @@
1
1
  module Vanity
2
- VERSION = "2.0.0.beta8"
2
+ VERSION = "2.0.0.beta9"
3
3
 
4
4
  module Version
5
5
  version = VERSION.to_s.split(".").map { |i| i.to_i }
@@ -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
@@ -0,0 +1,2 @@
1
+ development: localhost:6379/0
2
+ test: localhost:6379/15
@@ -0,0 +1,6 @@
1
+ development:
2
+ adapter: active_record
3
+ active_record_adapter: default
4
+ test:
5
+ adapter: active_record
6
+ active_record_adapter: default
@@ -0,0 +1,4 @@
1
+ development:
2
+ adapter: mock
3
+ test:
4
+ adapter: mock
@@ -0,0 +1,5 @@
1
+ test:
2
+ adapter: redis
3
+ collecting: false
4
+ production:
5
+ adapter: redis
@@ -0,0 +1,3 @@
1
+ production:
2
+ adapter: redis
3
+ connection: redis://<%= ENV["REDIS_USER"] %>:<%= ENV["REDIS_PASSWORD"] %>@<%= ENV["REDIS_HOST"] %>:<%= ENV["REDIS_PORT"] %>/0
@@ -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.playground.use_js!
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
- new_playground
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 load path and connection configuration" do
3
+ describe "deprecated Rails load_path and deprecated connection configuration" do
4
4
 
5
5
  it "load_path" do
6
- assert_equal File.expand_path("tmp/experiments"), load_rails("", <<-RB)
6
+ assert_equal "./experiments", load_rails("", <<-RB)
7
7
  $stdout << Vanity.playground.load_path
8
8
  RB
9
9
  end
10
10
 
11
- it "settable_load_path" do
12
- assert_equal File.expand_path("tmp/predictions"), load_rails(%Q{\nVanity.playground.load_path = "predictions"\n}, <<-RB)
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 "absolute_load_path" do
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 "default_connection" do
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 "connection_from_string" do
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 "connection_from_yaml" do
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 "connection_from_yaml_url" do
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 "connection_from_yaml_with_erb" do
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 "connection_from_redis_yml" do
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
- assert_equal "redis://internal.local:6379/0", load_rails("", <<-RB)
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 "mongo_connection_from_yaml" do
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' #TODO this doesn't get tested on CI
140
- it "mongodb_replica_set_connection" do
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 "connection_from_yaml_missing" do
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 RuntimeError => e
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 "collection_from_vanity_yaml" do
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 "collection_true_in_production_by_default" do
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 "collection_false_in_production_when_configured" do
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 "collection_true_in_development_by_default" do
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 "collection_true_in_development_when_configured" do
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 "playground_loads_if_connected" do
230
+ it "playground loads experiments if connected" do
231
231
  assert_equal "{}", load_rails("", <<-RB)
232
- $stdout << Vanity.playground.instance_variable_get(:@experiments).inspect
232
+ $stdout << Vanity.playground.experiments.inspect
233
233
  RB
234
234
  end
235
235
 
236
- it "playground_does_not_load_if_not_connected" do
237
- ENV['VANITY_DISABLED'] = '1'
238
- assert_equal "nil", load_rails("", <<-RB)
239
- $stdout << Vanity.playground.instance_variable_get(:@experiments).inspect
240
- RB
241
- ENV['VANITY_DISABLED'] = nil
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")