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,100 @@
1
+ module Vanity
2
+ class Connection
3
+ class InvalidSpecification < StandardError; end
4
+
5
+ DEFAULT_SPECIFICATION = { adapter: "redis" }
6
+
7
+ attr_reader :adapter, :specification
8
+
9
+ # With no argument, uses the connection specified in the configuration
10
+ # file, or defaults to Redis on localhost, port 6379.
11
+ # @example
12
+ # Vanity::Connection.new
13
+ #
14
+ # If the argument is a string, it is processed as a URL.
15
+ # @example
16
+ # Vanity::Connection.new("redis://redis.local/5")
17
+ #
18
+ # If the argument is a Hash, and contains a key `:redis` the value is used
19
+ # as a redis connection.
20
+ # @example
21
+ # $shared_redis_connection = Redis.new
22
+ # Vanity::Connection.new(adapter: :redis, redis: $shared_redis_connection)
23
+ #
24
+ # Otherwise, the argument is a hash and specifies the adapter name and any
25
+ # additional options understood by that adapter (as with
26
+ # config/vanity.yml). Note that all keys are expected to be symbols.
27
+ # @example
28
+ # Vanity::Connection.new(
29
+ # :adapter=>:redis,
30
+ # :host=>"redis.local"
31
+ # )
32
+ # @since 2.0.0
33
+ def initialize(specification=nil)
34
+ @specification = specification || DEFAULT_SPECIFICATION
35
+
36
+ if Autoconnect.playground_should_autoconnect?
37
+ @adapter = setup_connection(@specification)
38
+ end
39
+ end
40
+
41
+ # Closes the current connection.
42
+ #
43
+ # @since 2.0.0
44
+ def disconnect!
45
+ @adapter.disconnect! if connected?
46
+ end
47
+
48
+ # Returns true if connection is open.
49
+ #
50
+ # @since 2.0.0
51
+ def connected?
52
+ @adapter && @adapter.active?
53
+ end
54
+
55
+ private
56
+
57
+ def setup_connection(spec)
58
+ case spec
59
+ when String
60
+ spec_hash = build_specification_hash_from_url(spec)
61
+ establish_connection(spec_hash)
62
+ when Hash
63
+ validate_specification_hash(spec)
64
+ if spec[:redis]
65
+ establish_connection(
66
+ adapter: :redis,
67
+ redis: spec[:redis]
68
+ )
69
+ else
70
+ establish_connection(spec)
71
+ end
72
+ else
73
+ raise InvalidSpecification.new("Unsupported connection specification: #{spec.inspect}")
74
+ end
75
+ end
76
+
77
+ def build_specification_hash_from_url(connection_url)
78
+ uri = URI.parse(connection_url)
79
+ params = CGI.parse(uri.query) if uri.query
80
+ {
81
+ adapter: uri.scheme,
82
+ username: uri.user,
83
+ password: uri.password,
84
+ host: uri.host,
85
+ port: uri.port,
86
+ path: uri.path,
87
+ params: params
88
+ }
89
+ end
90
+
91
+ def validate_specification_hash(spec)
92
+ all_symbol_keys = spec.keys.all? { |key| key.is_a?(Symbol) }
93
+ raise InvalidSpecification unless all_symbol_keys
94
+ end
95
+
96
+ def establish_connection(spec)
97
+ Adapters.establish_connection(spec)
98
+ end
99
+ end
100
+ end
@@ -1,8 +1,10 @@
1
+ # TODO turn this into a real rails engine jobbie
1
2
  # Automatically configure Vanity.
2
3
  if defined?(Rails)
3
4
  class Plugin < Rails::Railtie # :nodoc:
4
5
  initializer "vanity.require" do |app|
5
6
  require 'vanity/frameworks/rails'
7
+
6
8
  Vanity::Rails.load!
7
9
  end
8
10
  end
@@ -1,13 +1,15 @@
1
1
  module Vanity
2
2
  module Rails
3
3
  def self.load!
4
- Vanity.playground.load_path = ::Rails.root + Vanity.playground.load_path
5
- Vanity.playground.logger ||= ::Rails.logger
4
+ ::Rails.configuration.before_initialize do
5
+ Vanity.configuration.logger ||= ::Rails.logger
6
+ Vanity.configuration.setup_locales
7
+ end
6
8
 
7
9
  # Do this at the very end of initialization, allowing you to change
8
10
  # connection adapter, turn collection on/off, etc.
9
11
  ::Rails.configuration.after_initialize do
10
- Vanity.playground.load! if Vanity.playground.connected?
12
+ Vanity.load! if Vanity.connection.connected?
11
13
  end
12
14
  end
13
15
 
@@ -44,7 +46,7 @@ module Vanity
44
46
  @_vanity_experiments[name] ||= alternative
45
47
  @_vanity_experiments[name].value
46
48
  end
47
-
49
+
48
50
  if block
49
51
  define_method(:vanity_identity) { block.call(self) }
50
52
  else
@@ -323,7 +325,7 @@ module Vanity
323
325
  exp.chooses(exp.alternatives[params[:a].to_i].value)
324
326
  render :file=>Vanity.template("_experiment"), :locals=>{:experiment=>exp}
325
327
  end
326
-
328
+
327
329
  def reset
328
330
  exp = Vanity.playground.experiment(params[:e].to_sym)
329
331
  exp.reset
@@ -69,6 +69,7 @@ module Vanity
69
69
  end
70
70
  end
71
71
 
72
+ # TODO do we actually want to do this?
72
73
  Object.class_eval do
73
74
  include Vanity::Helpers
74
75
  end
File without changes
File without changes
@@ -1,221 +1,142 @@
1
1
  require "uri"
2
2
 
3
3
  module Vanity
4
-
5
- # Playground catalogs all your experiments, holds the Vanity configuration.
6
- #
7
- # @example
8
- # Vanity.playground.logger = my_logger
9
- # puts Vanity.playground.map(&:name)
4
+ # Playground catalogs all your experiments. For configuration please see
5
+ # Vanity::Configuration, for connection management, please see
6
+ # Vanity::Connection.
10
7
  class Playground
11
8
 
12
- DEFAULTS = { :collecting => true, :load_path=>"experiments" }
13
- DEFAULT_ADD_PARTICIPANT_PATH = '/vanity/add_participant'
14
-
15
9
  # Created new Playground. Unless you need to, use the global
16
10
  # Vanity.playground.
17
- #
18
- # First argument is connection specification (see #redis=), last argument is
19
- # a set of options, both are optional. Supported options are:
20
- # - connection -- Connection specification
21
- # - load_path -- Path to load experiments/metrics from
22
- # - logger -- Logger to use
23
- # - redis -- A Redis object that will be used for the connection
24
- def initialize(*args)
25
- options = Hash === args.last ? args.pop : {}
26
- # In the case of Rails, use the Rails logger and collect only for
27
- # production environment by default.
28
- defaults = options[:rails] ? DEFAULTS.merge(:collecting => true, :logger => ::Rails.logger) : DEFAULTS
29
- if config_file_exists?
30
- env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
31
- config = load_config_file[env]
32
- if Hash === config
33
- config = config.inject({}) { |h,kv| h[kv.first.to_sym] = kv.last ; h }
34
- else
35
- config = { :connection=>config }
36
- end
37
- else
38
- config = {}
39
- end
40
-
41
- @options = defaults.merge(config).merge(options)
42
-
43
- @load_path = @options[:load_path] || DEFAULTS[:load_path]
44
-
45
- I18n.load_path += locale_file_paths
46
- unless @logger = @options[:logger]
47
- @logger = Logger.new(STDOUT)
48
- @logger.level = Logger::ERROR
49
- end
50
-
51
- autoconnect(@options, args) if Vanity::Autoconnect.playground_should_autoconnect?
52
-
11
+ def initialize
53
12
  @loading = []
54
- @use_js = false
55
- @failover_on_datastore_error = false
56
- self.add_participant_path = DEFAULT_ADD_PARTICIPANT_PATH
57
- @collecting = !!@options[:collecting]
58
13
  end
59
14
 
60
- # Path to load experiment files from.
61
- attr_accessor :load_path
62
-
63
- # Logger.
64
- attr_accessor :logger
65
-
66
- # Path to the add_participant action.
67
- attr_accessor :add_participant_path
68
-
69
- attr_accessor :on_datastore_error
70
-
71
- attr_accessor :request_filter
72
-
73
- # Path to custom templates (overriding those in the gem)
74
- attr_writer :custom_templates_path
75
- def custom_templates_path
76
- @custom_templates_path ||= (File.expand_path(File.join(::Rails.root, 'app', 'views', 'vanity')) if defined?(::Rails))
15
+ # @deprecated
16
+ # @see Configuration#experiments_path
17
+ def load_path
18
+ Vanity.configuration.experiments_path
77
19
  end
78
20
 
79
- # Returns the experiment. You may not have guessed, but this method raises
80
- # an exception if it cannot load the experiment's definition.
81
- #
82
- # @see Vanity::Experiment
83
- def experiment(name)
84
- id = name.to_s.downcase.gsub(/\W/, "_").to_sym
85
- warn "Deprecated: please call experiment method with experiment identifier (a Ruby symbol)" unless id == name
86
- experiments[id.to_sym] or raise NoExperimentError, "No experiment #{id}"
21
+ # @deprecated
22
+ # @see Configuration#experiments_path
23
+ def load_path=(path)
24
+ Vanity.configuration.experiments_path = path
87
25
  end
88
26
 
27
+ # @deprecated
28
+ # @see Configuration#logger
29
+ def logger
30
+ Vanity.configuration.logger
31
+ end
89
32
 
90
- # -- Participant Information --
91
-
92
- # Returns an array of all experiments this participant is involved in, with their assignment.
93
- # This is done as an array of arrays [[<experiment_1>, <assignment_1>], [<experiment_2>, <assignment_2>]], sorted by experiment name, so that it will give a consistent string
94
- # when converted to_s (so could be used for caching, for example)
95
- def participant_info(participant_id)
96
- participant_array = []
97
- experiments.values.sort_by(&:name).each do |e|
98
- index = connection.ab_assigned(e.id, participant_id)
99
- if index
100
- participant_array << [e, e.alternatives[index.to_i]]
101
- end
102
- end
103
- participant_array
33
+ # @deprecated
34
+ # @see Configuration#logger
35
+ def logger=(logger)
36
+ Vanity.configuration.logger = logger
104
37
  end
105
38
 
39
+ # @deprecated
40
+ # @see Configuration#templates_path
41
+ def custom_templates_path
42
+ Vanity.configuration.templates_path
43
+ end
106
44
 
107
- # -- Robot Detection --
45
+ def custom_templates_path=(path)
46
+ Vanity.configuration.templates_path = path
47
+ end
108
48
 
109
- # Call to indicate that participants should be added via js. This helps
110
- # keep robots from participating in the A/B test and skewing results.
111
- #
112
- # If you want to use this:
113
- # - Add <%= vanity_js %> to any page that needs uses an ab_test. vanity_js
114
- # needs to be included after your call to ab_test so that it knows which
115
- # version of the experiment the participant is a member of. The helper
116
- # will render nothing if the there are no ab_tests running on the current
117
- # page, so adding vanity_js to the bottom of your layouts is a good
118
- # option. Keep in mind that if you call use_js! and don't include
119
- # vanity_js in your view no participants will be recorded.
120
- #
121
- # Note that a custom JS callback path can be set using:
122
- # - Set Vanity.playground.add_participant_path = '/path/to/vanity/action',
123
- # this should point to the add_participant path that is added with
124
- # Vanity::Rails::Dashboard, make sure that this action is available
125
- # to all users.
49
+ # @deprecated
50
+ # @see Configuration#use_js
126
51
  def use_js!
127
- @use_js = true
52
+ Vanity.configuration.use_js = true
128
53
  end
129
54
 
55
+ # @deprecated
56
+ # @see Configuration#use_js
130
57
  def using_js?
131
- @use_js
58
+ Vanity.configuration.use_js
132
59
  end
133
60
 
61
+ # @deprecated
62
+ # @see Configuration#add_participant_route
63
+ def add_participant_path
64
+ Vanity.configuration.add_participant_route
65
+ end
134
66
 
135
- # -- Datastore graceful failover --
67
+ # @deprecated
68
+ # @see Configuration#add_participant_route=
69
+ def add_participant_path=(path)
70
+ Vanity.configuration.add_participant_route=path
71
+ end
136
72
 
137
- # Turns on passing of errors to the Proc returned by #on_datastore_error.
138
- # Call Vanity.playground.failover_on_datastore_error! to turn this on.
139
- #
140
73
  # @since 1.9.0
74
+ # @deprecated
75
+ # @see Configuration#failover_on_datastore_error
141
76
  def failover_on_datastore_error!
142
- @failover_on_datastore_error = true
77
+ Vanity.configuration.failover_on_datastore_error = true
143
78
  end
144
79
 
145
- # Returns whether to failover on an error raise by the datastore adapter.
146
- #
147
80
  # @since 1.9.0
81
+ # @deprecated
82
+ # @see Configuration#failover_on_datastore_error
148
83
  def failover_on_datastore_error?
149
- @failover_on_datastore_error
84
+ Vanity.configuration.failover_on_datastore_error
150
85
  end
151
86
 
152
- # Must return a Proc that accepts as parameters: the thrown error, the
153
- # calling Class, the calling method, and an array of arguments passed to
154
- # the calling method. The return value is ignored.
155
- #
156
- # Proc.new do |error, klass, method, arguments|
157
- # ...
158
- # end
159
- #
160
- # The default implementation logs this information to Playground#logger.
161
- #
162
- # Set a custom action by calling Vanity.playground.on_datastore_error =
163
- # Proc.new { ... }.
164
- #
165
87
  # @since 1.9.0
88
+ # @deprecated
89
+ # @see Configuration#on_datastore_error
166
90
  def on_datastore_error
167
- @on_datastore_error || default_on_datastore_error
91
+ Vanity.configuration.on_datastore_error
168
92
  end
169
93
 
170
- def default_on_datastore_error # :nodoc:
171
- Proc.new do |error, klass, method, arguments|
172
- log = "[#{Time.now.iso8601}]"
173
- log << " [vanity #{klass} #{method}]"
174
- log << " [#{error.message}]"
175
- log << " [#{arguments.join(' ')}]"
176
- @logger.error(log)
177
- nil
178
- end
94
+ # @deprecated
95
+ # @see Configuration#on_datastore_error
96
+ def on_datastore_error=(closure)
97
+ Vanity.configuration.on_datastore_error = closure
179
98
  end
180
- protected :default_on_datastore_error
181
-
182
99
 
183
- # -- Blocking or ignoring visitors --
184
-
185
- # Must return a Proc that accepts as a parameter the request object, if
186
- # made available by the implement framework. The return value should be a
187
- # boolean whether to ignore the request. This is called only for the JS
188
- # callback action.
189
- #
190
- # Proc.new do |request|
191
- # ...
192
- # end
193
- #
194
- # The default implementation does a simple test of whether the request's
195
- # HTTP_USER_AGENT header contains a URI, since well behaved bots typically
196
- # include a reference URI in their user agent strings. (Original idea:
197
- # http://stackoverflow.com/a/9285889.)
198
- #
199
- # Alternatively, one could filter an explicit list of IPs, add additional
200
- # user agent strings to filter, or any custom test. Set a custom filter
201
- # by calling Vanity.playground.request_filter = Proc.new { ... }.
202
- #
203
100
  # @since 1.9.0
101
+ # @deprecated
102
+ # @see Configuration#request_filter
204
103
  def request_filter
205
- @request_filter || default_request_filter
104
+ Vanity.configuration.request_filter
206
105
  end
207
106
 
208
- def default_request_filter # :nodoc:
209
- Proc.new do |request|
210
- request &&
211
- request.env &&
212
- request.env["HTTP_USER_AGENT"] &&
213
- request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
214
- end
107
+ # @deprecated
108
+ # @see Configuration#request_filter=
109
+ def request_filter=(filter)
110
+ Vanity.configuration.request_filter = filter
111
+ end
112
+
113
+ # @since 1.4.0
114
+ # @deprecated
115
+ # @see Configuration#collecting
116
+ def collecting?
117
+ Vanity.configuration.collecting
118
+ end
119
+
120
+ # @since 1.4.0
121
+ # @deprecated
122
+ # @see Configuration#collecting
123
+ def collecting=(enabled)
124
+ Vanity.configuration.collecting = enabled
215
125
  end
216
- protected :default_request_filter
217
126
 
218
- # Returns hash of experiments (key is experiment id). This create the
127
+ # @deprecated
128
+ # @see Vanity#reload!
129
+ def reload!
130
+ Vanity.reload!
131
+ end
132
+
133
+ # @deprecated
134
+ # @see Vanity#load!
135
+ def load!
136
+ Vanity.load!
137
+ end
138
+
139
+ # Returns hash of experiments (key is experiment id). This creates the
219
140
  # Experiment and persists it to the datastore.
220
141
  #
221
142
  # @see Vanity::Experiment
@@ -223,8 +144,8 @@ module Vanity
223
144
  return @experiments if @experiments
224
145
 
225
146
  @experiments = {}
226
- @logger.info "Vanity: loading experiments from #{load_path}"
227
- Dir[File.join(load_path, "*.rb")].each do |file|
147
+ Vanity.logger.info("Vanity: loading experiments from #{Vanity.configuration.experiments_path}")
148
+ Dir[File.join(Vanity.configuration.experiments_path, "*.rb")].each do |file|
228
149
  Experiment::Base.load(self, @loading, file)
229
150
  end
230
151
  @experiments
@@ -234,21 +155,6 @@ module Vanity
234
155
  experiments.keys.all? { |id| connection.experiment_persisted?(id) }
235
156
  end
236
157
 
237
- # Reloads all metrics and experiments. Rails calls this for each request in
238
- # development mode.
239
- def reload!
240
- @experiments = nil
241
- @metrics = nil
242
- load!
243
- end
244
-
245
- # Loads all metrics and experiments. Rails calls this during
246
- # initialization.
247
- def load!
248
- experiments
249
- metrics
250
- end
251
-
252
158
  # Returns a metric (raises NameError if no metric with that identifier).
253
159
  #
254
160
  # @see Vanity::Metric
@@ -257,40 +163,18 @@ module Vanity
257
163
  metrics[id.to_sym] or raise NameError, "No metric #{id}"
258
164
  end
259
165
 
260
- # True if collection data (metrics and experiments). You only want to
261
- # collect data in production environment, everywhere else run with
262
- # collection off.
263
- #
264
- # @since 1.4.0
265
- def collecting?
266
- @collecting
267
- end
268
-
269
- # Turns data collection on and off.
270
- #
271
- # @since 1.4.0
272
- def collecting=(enabled)
273
- @collecting = !!enabled
274
- end
275
-
276
166
  # Returns hash of metrics (key is metric id).
277
167
  #
278
168
  # @see Vanity::Metric
279
169
  # @since 1.1.0
170
+ # @deprecated
280
171
  def metrics
281
172
  unless @metrics
282
173
  @metrics = {}
283
- @logger.info "Vanity: loading metrics from #{load_path}/metrics"
284
- Dir[File.join(load_path, "metrics/*.rb")].each do |file|
285
- Metric.load self, @loading, file
286
- end
287
- if config_file_exists? && remote = load_config_file["metrics"]
288
- remote.each do |id, url|
289
- fail "Metric #{id} already defined in playground" if metrics[id.to_sym]
290
- metric = Metric.new(self, id)
291
- metric.remote url
292
- metrics[id.to_sym] = metric
293
- end
174
+ Vanity.logger.info("Vanity: loading metrics from #{Vanity.configuration.experiments_path}/metrics")
175
+
176
+ Dir[File.join(Vanity.configuration.experiments_path, "metrics/*.rb")].each do |file|
177
+ Metric.load(self, @loading, file)
294
178
  end
295
179
  end
296
180
  @metrics
@@ -303,156 +187,72 @@ module Vanity
303
187
  #
304
188
  # @since 1.1.0
305
189
  def track!(id, count = 1)
306
- metric(id).track! count
190
+ metric(id).track!(count)
307
191
  end
308
192
 
309
-
310
- # -- Connection management --
311
-
312
- # This is the preferred way to programmatically create a new connection (or
313
- # switch to a new connection). If no connection was established, the
314
- # playground will create a new one by calling this method with no arguments.
315
- #
316
- # With no argument, uses the connection specified in config/vanity.yml file
317
- # for the current environment (RACK_ENV, RAILS_ENV or development). If there
318
- # is no config/vanity.yml file, picks the configuration from
319
- # config/redis.yml, or defaults to Redis on localhost, port 6379.
320
- #
321
- # If the argument is a symbol, uses the connection specified in
322
- # config/vanity.yml for that environment. For example:
323
- # Vanity.playground.establish_connection :production
324
- #
325
- # If the argument is a string, it is processed as a URL. For example:
326
- # Vanity.playground.establish_connection "redis://redis.local/5"
327
- #
328
- # Otherwise, the argument is a hash and specifies the adapter name and any
329
- # additional options understood by that adapter (as with config/vanity.yml).
330
- # For example:
331
- # Vanity.playground.establish_connection :adapter=>:redis,
332
- # :host=>"redis.local"
193
+ # Returns the experiment. You may not have guessed, but this method raises
194
+ # an exception if it cannot load the experiment's definition.
333
195
  #
334
- # @since 1.4.0
335
- def establish_connection(spec = nil)
336
- @spec = spec
337
- disconnect! if @adapter
338
- case spec
339
- when nil
340
- if config_file_exists?
341
- env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
342
- spec = load_config_file[env]
343
- fail "No configuration for #{env}" unless spec
344
- establish_connection spec
345
- elsif config_file_exists?("redis.yml")
346
- env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
347
- redis = load_config_file("redis.yml")[env]
348
- fail "No configuration for #{env}" unless redis
349
- establish_connection "redis://" + redis
350
- else
351
- establish_connection :adapter=>"redis"
352
- end
353
- when Symbol
354
- spec = load_config_file[spec.to_s]
355
- establish_connection spec
356
- when String
357
- uri = URI.parse(spec)
358
- params = CGI.parse(uri.query) if uri.query
359
- establish_connection :adapter=>uri.scheme, :username=>uri.user, :password=>uri.password,
360
- :host=>uri.host, :port=>uri.port, :path=>uri.path, :params=>params
361
- else
362
- spec = spec.inject({}) { |hash,(k,v)| hash[k.to_sym] = v ; hash }
363
- @adapter = Adapters.establish_connection(spec)
364
- end
196
+ # @see Vanity::Experiment
197
+ # @deprecated
198
+ def experiment(name)
199
+ id = name.to_s.downcase.gsub(/\W/, "_").to_sym
200
+ Vanity.logger.warn("Deprecated: Please call experiment method with experiment identifier (a Ruby symbol)") unless id == name
201
+ experiments[id.to_sym] or raise NoExperimentError, "No experiment #{id}"
365
202
  end
366
203
 
367
- def config_file_root
368
- (defined?(::Rails) ? ::Rails.root : Pathname.new(".")) + "config"
369
- end
370
204
 
371
- def config_file_exists?(basename = "vanity.yml")
372
- File.exists?(config_file_root + basename)
373
- end
205
+ # -- Participant Information --
374
206
 
375
- def load_config_file(basename = "vanity.yml")
376
- YAML.load(ERB.new(File.read(config_file_root + basename)).result)
207
+ # Returns an array of all experiments this participant is involved in, with their assignment.
208
+ # This is done as an array of arrays [[<experiment_1>, <assignment_1>], [<experiment_2>, <assignment_2>]], sorted by experiment name, so that it will give a consistent string
209
+ # when converted to_s (so could be used for caching, for example)
210
+ def participant_info(participant_id)
211
+ participant_array = []
212
+ experiments.values.sort_by(&:name).each do |e|
213
+ index = connection.ab_assigned(e.id, participant_id)
214
+ if index
215
+ participant_array << [e, e.alternatives[index.to_i]]
216
+ end
217
+ end
218
+ participant_array
377
219
  end
378
220
 
379
- def locale_file_paths
380
- locale_files_dir = File.expand_path('../../config/locales/', File.dirname(__FILE__))
381
- Dir[locale_files_dir+'/*.{rb,yml}']
221
+ # @since 1.4.0
222
+ # @deprecated
223
+ # @see Vanity::Connection
224
+ def establish_connection(spec=nil)
225
+ disconnect!
226
+ Vanity.connect!(spec)
382
227
  end
383
228
 
384
- # Returns the current connection. Establishes new connection is necessary.
385
- #
386
229
  # @since 1.4.0
230
+ # @deprecated
231
+ # @see Vanity.connection
387
232
  def connection
388
- @adapter || establish_connection
233
+ Vanity.connection.adapter
389
234
  end
390
235
 
391
- # Returns true if connection is open.
392
- #
393
236
  # @since 1.4.0
237
+ # @deprecated
238
+ # @see Vanity.connection
394
239
  def connected?
395
- @adapter && @adapter.active?
240
+ Vanity.connection.connected?
396
241
  end
397
242
 
398
- # Closes the current connection.
399
- #
400
243
  # @since 1.4.0
244
+ # @deprecated
245
+ # @see Vanity.disconnect!
401
246
  def disconnect!
402
- @adapter.disconnect! if @adapter
247
+ Vanity.disconnect!
403
248
  end
404
249
 
405
250
  # Closes the current connection and establishes a new one.
406
251
  #
407
252
  # @since 1.3.0
253
+ # @deprecated
408
254
  def reconnect!
409
- establish_connection(@spec)
255
+ Vanity.reconnect!
410
256
  end
411
-
412
- protected
413
-
414
- def autoconnect(options, arguments)
415
- if options[:redis]
416
- @adapter = RedisAdapter.new(:redis=>options[:redis])
417
- else
418
- connection_spec = arguments.shift || options[:connection]
419
- if connection_spec
420
- connection_spec = "redis://" + connection_spec unless connection_spec[/^\w+:/]
421
- establish_connection connection_spec
422
- else
423
- establish_connection
424
- end
425
- end
426
- end
427
-
428
- end
429
-
430
- # In the case of Rails, use the Rails logger and collect only for
431
- # production environment by default.
432
- class << self
433
-
434
- # The playground instance.
435
- #
436
- # @see Vanity::Playground
437
- attr_accessor :playground
438
- def playground
439
- # In the case of Rails, use the Rails logger and collect only for
440
- # production environment by default.
441
- @playground ||= Playground.new(:rails=>defined?(::Rails))
442
- end
443
-
444
- # Returns the Vanity context. For example, when using Rails this would be
445
- # the current controller, which can be used to get/set the vanity identity.
446
- def context
447
- Thread.current[:vanity_context]
448
- end
449
-
450
- # Sets the Vanity context. For example, when using Rails this would be
451
- # set by the set_vanity_context before filter (via Vanity::Rails#use_vanity).
452
- def context=(context)
453
- Thread.current[:vanity_context] = context
454
- end
455
-
456
-
457
257
  end
458
258
  end