Class: Vanity::Playground
Overview
Playground catalogs all your experiments, holds the Vanity configuration.
Constant Summary
- DEFAULTS =
{ :collecting => true, :load_path=>"experiments" }
- DEFAULT_ADD_PARTICIPANT_PATH =
'/vanity/add_participant'
Instance Attribute Summary (collapse)
-
- (Object) add_participant_path
Path to the add_participant action, necessary if you have called use_js!.
-
- (Object) db
Deprecated.
-
- (Object) host
Deprecated.
-
- (Object) load_path
Path to load experiment files from.
-
- (Object) logger
Logger.
-
- (Object) namespace
Deprecated.
-
- (Object) password
Deprecated.
-
- (Object) port
Deprecated.
Instance Method Summary (collapse)
-
- (Object) collecting=(enabled)
Turns data collection on and off.
-
- (Boolean) collecting?
True if collection data (metrics and experiments).
- - (Boolean) config_file_exists?(basename = "vanity.yml")
- - (Object) config_file_root
-
- (Boolean) connected?
Returns true if connection is open.
-
- (Object) connection
Returns the current connection.
-
- (Object) define(name, type, options = {}, &block)
Defines a new experiment.
-
- (Object) disconnect!
Closes the current connection.
-
- (Object) establish_connection(spec = nil)
This is the preferred way to programmatically create a new connection (or switch to a new connection).
-
- (Object) experiment(name)
Returns the experiment.
-
- (Object) experiments
Returns hash of experiments (key is experiment id).
-
- (Playground) initialize(*args)
constructor
Created new Playground.
-
- (Object) load!
Loads all metrics and experiments.
- - (Object) load_config_file(basename = "vanity.yml")
-
- (Object) metric(id)
Returns a metric (raises NameError if no metric with that identifier).
-
- (Object) metrics
Returns hash of metrics (key is metric id).
-
- (Object) reconnect!
Closes the current connection and establishes a new one.
- - (Object) redis
-
- (Object) redis=(spec_or_connection)
Deprecated.
-
- (Object) reload!
Reloads all metrics and experiments.
-
- (Object) test!
Deprecated.
-
- (Object) track!(id, count = 1)
Tracks an action associated with a metric.
-
- (Object) use_js!
Call to indicate that participants should be added via js This helps keep robots from participating in the ab test and skewing results.
- - (Boolean) using_js?
Constructor Details
- (Playground) initialize(*args)
Created new Playground. Unless you need to, use the global Vanity.playground.
First argument is connection specification (see #redis=), last argument is a set of options, both are optional. Supported options are:
connection — Connection specification
namespace — Namespace to use
load_path — Path to load experiments/metrics from
logger — Logger to use
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/vanity/playground.rb', line 24 def initialize(*args) = Hash === args.last ? args.pop : {} # In the case of Rails, use the Rails logger and collect only for # production environment by default. defaults = [:rails] ? DEFAULTS.merge(:collecting => ::Rails.env.production?, :logger => ::Rails.logger) : DEFAULTS if config_file_exists? env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development" config = load_config_file[env] if Hash === config config = config.inject({}) { |h,kv| h[kv.first.to_sym] = kv.last ; h } else config = { :connection=>config } end else config = {} end @options = defaults.merge(config).merge() if @options[:host] == 'redis' && @options.values_at(:host, :port, :db).any? warn "Deprecated: please specify Redis connection as URL (\"redis://host:port/db\")" establish_connection :adapter=>"redis", :host=>@options[:host], :port=>@options[:port], :database=>@options[:db] || @options[:database] elsif @options[:redis] @adapter = RedisAdapter.new(:redis=>@options[:redis]) else connection_spec = args.shift || @options[:connection] if connection_spec connection_spec = "redis://" + connection_spec unless connection_spec[/^\w+:/] establish_connection connection_spec end end warn "Deprecated: namespace option no longer supported directly" if @options[:namespace] @load_path = @options[:load_path] || DEFAULTS[:load_path] unless @logger = @options[:logger] @logger = Logger.new(STDOUT) @logger.level = Logger::ERROR end @loading = [] @use_js = false self.add_participant_path = DEFAULT_ADD_PARTICIPANT_PATH @collecting = !!@options[:collecting] end |
Instance Attribute Details
- (Object) add_participant_path
Path to the add_participant action, necessary if you have called use_js!
77 78 79 |
# File 'lib/vanity/playground.rb', line 77 def add_participant_path @add_participant_path end |
- (Object) db
Deprecated. Use redis.server instead.
68 69 70 |
# File 'lib/vanity/playground.rb', line 68 def db @db end |
- (Object) host
Deprecated. Use redis.server instead.
68 69 70 |
# File 'lib/vanity/playground.rb', line 68 def host @host end |
- (Object) load_path
Path to load experiment files from.
71 72 73 |
# File 'lib/vanity/playground.rb', line 71 def load_path @load_path end |
- (Object) logger
Logger.
74 75 76 |
# File 'lib/vanity/playground.rb', line 74 def logger @logger end |
- (Object) namespace
Deprecated. Use redis.server instead.
68 69 70 |
# File 'lib/vanity/playground.rb', line 68 def namespace @namespace end |
- (Object) password
Deprecated. Use redis.server instead.
68 69 70 |
# File 'lib/vanity/playground.rb', line 68 def password @password end |
- (Object) port
Deprecated. Use redis.server instead.
68 69 70 |
# File 'lib/vanity/playground.rb', line 68 def port @port end |
Instance Method Details
- (Object) collecting=(enabled)
Turns data collection on and off.
181 182 183 |
# File 'lib/vanity/playground.rb', line 181 def collecting=(enabled) @collecting = !!enabled end |
- (Boolean) collecting?
True if collection data (metrics and experiments). You only want to collect data in production environment, everywhere else run with collection off.
174 175 176 |
# File 'lib/vanity/playground.rb', line 174 def collecting? @collecting end |
- (Boolean) config_file_exists?(basename = "vanity.yml")
279 280 281 |
# File 'lib/vanity/playground.rb', line 279 def config_file_exists?(basename = "vanity.yml") File.exists?(config_file_root + basename) end |
- (Object) config_file_root
275 276 277 |
# File 'lib/vanity/playground.rb', line 275 def config_file_root (defined?(::Rails) ? ::Rails.root : Pathname.new(".")) + "config" end |
- (Boolean) connected?
Returns true if connection is open.
297 298 299 |
# File 'lib/vanity/playground.rb', line 297 def connected? @adapter && @adapter.active? end |
- (Object) connection
Returns the current connection. Establishes new connection is necessary.
290 291 292 |
# File 'lib/vanity/playground.rb', line 290 def connection @adapter || establish_connection end |
- (Object) define(name, type, options = {}, &block)
Defines a new experiment. Generally, do not call this directly, use one of the definition methods (ab_test, measure, etc).
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/vanity/playground.rb', line 83 def define(name, type, = {}, &block) warn "Deprecated: if you need this functionality let's make a better API" id = name.to_s.downcase.gsub(/\W/, "_").to_sym raise "Experiment #{id} already defined once" if experiments[id] klass = Experiment.const_get(type.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }) experiment = klass.new(self, id, name, ) experiment.instance_eval &block experiment.save experiments[id] = experiment end |
- (Object) disconnect!
Closes the current connection.
304 305 306 |
# File 'lib/vanity/playground.rb', line 304 def disconnect! @adapter.disconnect! if @adapter end |
- (Object) establish_connection(spec = nil)
This is the preferred way to programmatically create a new connection (or switch to a new connection). If no connection was established, the playground will create a new one by calling this method with no arguments.
With no argument, uses the connection specified in config/vanity.yml file for the current environment (RACK_ENV, RAILS_ENV or development). If there is no config/vanity.yml file, picks the configuration from config/redis.yml, or defaults to Redis on localhost, port 6379.
If the argument is a symbol, uses the connection specified in config/vanity.yml for that environment. For example:
Vanity.playground.establish_connection :production
If the argument is a string, it is processed as a URL. For example:
Vanity.playground.establish_connection "redis://redis.local/5"
Otherwise, the argument is a hash and specifies the adapter name and any additional options understood by that adapter (as with config/vanity.yml). For example:
Vanity.playground.establish_connection :adapter=>:redis, :host=>"redis.local"
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/vanity/playground.rb', line 244 def establish_connection(spec = nil) disconnect! if @adapter case spec when nil if config_file_exists? env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development" spec = load_config_file[env] fail "No configuration for #{env}" unless spec establish_connection spec elsif config_file_exists?("redis.yml") env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development" redis = load_config_file("redis.yml")[env] fail "No configuration for #{env}" unless redis establish_connection "redis://" + redis else establish_connection :adapter=>"redis" end when Symbol spec = load_config_file[spec.to_s] establish_connection spec when String uri = URI.parse(spec) params = CGI.parse(uri.query) if uri.query establish_connection :adapter=>uri.scheme, :username=>uri.user, :password=>uri.password, :host=>uri.host, :port=>uri.port, :path=>uri.path, :params=>params else spec = spec.inject({}) { |hash,(k,v)| hash[k.to_sym] = v ; hash } @adapter = Adapters.establish_connection(spec) end end |
- (Object) experiment(name)
Returns the experiment. You may not have guessed, but this method raises an exception if it cannot load the experiment’s definition.
98 99 100 101 102 |
# File 'lib/vanity/playground.rb', line 98 def experiment(name) id = name.to_s.downcase.gsub(/\W/, "_").to_sym warn "Deprecated: pleae call experiment method with experiment identifier (a Ruby symbol)" unless id == name experiments[id.to_sym] or raise NameError, "No experiment #{id}" end |
- (Object) experiments
Returns hash of experiments (key is experiment id).
135 136 137 138 139 140 141 142 143 144 |
# File 'lib/vanity/playground.rb', line 135 def experiments unless @experiments @experiments = {} @logger.info "Vanity: loading experiments from #{load_path}" Dir[File.join(load_path, "*.rb")].each do |file| Experiment::Base.load self, @loading, file end end @experiments end |
- (Object) load!
Loads all metrics and experiments. Rails calls this during initialization.
156 157 158 159 |
# File 'lib/vanity/playground.rb', line 156 def load! experiments metrics end |
- (Object) load_config_file(basename = "vanity.yml")
283 284 285 |
# File 'lib/vanity/playground.rb', line 283 def load_config_file(basename = "vanity.yml") YAML.load(ERB.new(File.read(config_file_root + basename)).result) end |
- (Object) metric(id)
Returns a metric (raises NameError if no metric with that identifier).
165 166 167 |
# File 'lib/vanity/playground.rb', line 165 def metric(id) metrics[id.to_sym] or raise NameError, "No metric #{id}" end |
- (Object) metrics
Returns hash of metrics (key is metric id).
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/vanity/playground.rb', line 189 def metrics unless @metrics @metrics = {} @logger.info "Vanity: loading metrics from #{load_path}/metrics" Dir[File.join(load_path, "metrics/*.rb")].each do |file| Metric.load self, @loading, file end if config_file_exists? && remote = load_config_file["metrics"] remote.each do |id, url| fail "Metric #{id} already defined in playground" if metrics[id.to_sym] metric = Metric.new(self, id) metric.remote url metrics[id.to_sym] = metric end end end @metrics end |
- (Object) reconnect!
Closes the current connection and establishes a new one.
311 312 313 |
# File 'lib/vanity/playground.rb', line 311 def reconnect! establish_connection end |
- (Object) redis
338 339 340 341 |
# File 'lib/vanity/playground.rb', line 338 def redis warn "Deprecated: use connection method instead" connection end |
- (Object) redis=(spec_or_connection)
Deprecated. Use establish_connection or configuration file instead.
324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/vanity/playground.rb', line 324 def redis=(spec_or_connection) warn "Deprecated: use establish_connection method instead" case spec_or_connection when String establish_connection "redis://" + spec_or_connection when ::Redis @connection = Adapters::RedisAdapter.new(spec_or_connection) when :mock establish_connection :adapter=>:mock else raise "I don't know what to do with #{spec_or_connection.inspect}" end end |
- (Object) reload!
Reloads all metrics and experiments. Rails calls this for each request in development mode.
148 149 150 151 152 |
# File 'lib/vanity/playground.rb', line 148 def reload! @experiments = nil @metrics = nil load! end |
- (Object) test!
Deprecated. Use Vanity.playground.collecting = true/false instead. Under Rails, collecting is true in production environment, false in all other environments, which is exactly what you want.
318 319 320 321 |
# File 'lib/vanity/playground.rb', line 318 def test! warn "Deprecated: use collecting = false instead" self.collecting = false end |
- (Object) track!(id, count = 1)
Tracks an action associated with a metric.
214 215 216 |
# File 'lib/vanity/playground.rb', line 214 def track!(id, count = 1) metric(id).track! count end |
- (Object) use_js!
Call to indicate that participants should be added via js This helps keep robots from participating in the ab test and skewing results.
If you use this, there are two more steps:
Set Vanity.playground.add_participant_path = ’/path/to/vanity/action’, this should point to the add_participant path that is added with Vanity::Rails::Dashboard, make sure that this action is available to all users
Add <%= vanity_js %> to any page that needs uses an ab_test. vanity_js needs to be included after your call to ab_test so that it knows which version of the experiment the participant is a member of. The helper will render nothing if the there are no ab_tests running on the current page, so adding vanity_js to the bottom of your layouts is a good option. Keep in mind that if you call use_js! and don’t include vanity_js in your view no participants will be recorded.
123 124 125 |
# File 'lib/vanity/playground.rb', line 123 def use_js! @use_js = true end |
- (Boolean) using_js?
127 128 129 |
# File 'lib/vanity/playground.rb', line 127 def using_js? @use_js end |