vanity 1.3.0 → 1.4.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/CHANGELOG +61 -3
  2. data/Gemfile +22 -14
  3. data/README.rdoc +9 -4
  4. data/Rakefile +72 -12
  5. data/bin/vanity +16 -4
  6. data/lib/vanity.rb +7 -5
  7. data/lib/vanity/adapters/abstract_adapter.rb +135 -0
  8. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  9. data/lib/vanity/adapters/mongo_adapter.rb +162 -0
  10. data/lib/vanity/adapters/redis_adapter.rb +154 -0
  11. data/lib/vanity/backport.rb +0 -17
  12. data/lib/vanity/commands/upgrade.rb +34 -0
  13. data/lib/vanity/experiment/ab_test.rb +46 -41
  14. data/lib/vanity/experiment/base.rb +13 -15
  15. data/lib/vanity/frameworks/rails.rb +5 -9
  16. data/lib/vanity/metric/active_record.rb +10 -4
  17. data/lib/vanity/metric/base.rb +46 -23
  18. data/lib/vanity/metric/google_analytics.rb +7 -0
  19. data/lib/vanity/metric/remote.rb +53 -0
  20. data/lib/vanity/playground.rb +133 -49
  21. data/test/{ab_test_test.rb → experiment/ab_test.rb} +47 -3
  22. data/test/{experiment_test.rb → experiment/base_test.rb} +8 -8
  23. data/test/metric/active_record_test.rb +253 -0
  24. data/test/metric/base_test.rb +293 -0
  25. data/test/metric/google_analytics_test.rb +104 -0
  26. data/test/metric/remote_test.rb +108 -0
  27. data/test/myapp/app/controllers/application_controller.rbc +66 -0
  28. data/test/myapp/app/controllers/main_controller.rb +3 -3
  29. data/test/myapp/app/controllers/main_controller.rbc +347 -0
  30. data/test/myapp/config/boot.rbc +2534 -0
  31. data/test/myapp/config/environment.rbc +403 -0
  32. data/test/myapp/config/routes.rbc +174 -0
  33. data/test/myapp/log/production.log +2601 -0
  34. data/test/passenger_test.rb +14 -5
  35. data/test/passenger_test.rbc +0 -0
  36. data/test/playground_test.rbc +256 -0
  37. data/test/rails_test.rb +75 -22
  38. data/test/rails_test.rbc +4086 -0
  39. data/test/test_helper.rb +30 -7
  40. data/test/test_helper.rbc +4297 -0
  41. data/vanity.gemspec +6 -2
  42. metadata +74 -73
  43. data/lib/vanity/commands.rb +0 -2
  44. data/lib/vanity/mock_redis.rb +0 -76
  45. data/test/metric_test.rb +0 -622
  46. data/vendor/cache/RedCloth-4.2.2.gem +0 -0
  47. data/vendor/cache/actionmailer-2.3.5.gem +0 -0
  48. data/vendor/cache/actionpack-2.3.5.gem +0 -0
  49. data/vendor/cache/activerecord-2.3.5.gem +0 -0
  50. data/vendor/cache/activeresource-2.3.5.gem +0 -0
  51. data/vendor/cache/activesupport-2.3.5.gem +0 -0
  52. data/vendor/cache/autotest-4.2.7.gem +0 -0
  53. data/vendor/cache/autotest-fsevent-0.2.1.gem +0 -0
  54. data/vendor/cache/autotest-growl-0.2.0.gem +0 -0
  55. data/vendor/cache/bundler-0.9.7.gem +0 -0
  56. data/vendor/cache/classifier-1.3.1.gem +0 -0
  57. data/vendor/cache/directory_watcher-1.3.1.gem +0 -0
  58. data/vendor/cache/fastthread-1.0.7.gem +0 -0
  59. data/vendor/cache/garb-0.7.0.gem +0 -0
  60. data/vendor/cache/happymapper-0.3.0.gem +0 -0
  61. data/vendor/cache/jekyll-0.5.7.gem +0 -0
  62. data/vendor/cache/libxml-ruby-1.1.3.gem +0 -0
  63. data/vendor/cache/liquid-2.0.0.gem +0 -0
  64. data/vendor/cache/maruku-0.6.0.gem +0 -0
  65. data/vendor/cache/mocha-0.9.8.gem +0 -0
  66. data/vendor/cache/open4-1.0.1.gem +0 -0
  67. data/vendor/cache/passenger-2.2.9.gem +0 -0
  68. data/vendor/cache/rack-1.0.1.gem +0 -0
  69. data/vendor/cache/rails-2.3.5.gem +0 -0
  70. data/vendor/cache/rake-0.8.7.gem +0 -0
  71. data/vendor/cache/rubygems-update-1.3.5.gem +0 -0
  72. data/vendor/cache/shoulda-2.10.3.gem +0 -0
  73. data/vendor/cache/sqlite3-ruby-1.2.5.gem +0 -0
  74. data/vendor/cache/stemmer-1.0.1.gem +0 -0
  75. data/vendor/cache/syntax-1.0.0.gem +0 -0
  76. data/vendor/cache/sys-uname-0.8.4.gem +0 -0
  77. data/vendor/cache/timecop-0.3.4.gem +0 -0
  78. data/vendor/redis-rb/LICENSE +0 -20
  79. data/vendor/redis-rb/README.markdown +0 -36
  80. data/vendor/redis-rb/Rakefile +0 -62
  81. data/vendor/redis-rb/bench.rb +0 -44
  82. data/vendor/redis-rb/benchmarking/suite.rb +0 -24
  83. data/vendor/redis-rb/benchmarking/worker.rb +0 -71
  84. data/vendor/redis-rb/bin/distredis +0 -33
  85. data/vendor/redis-rb/examples/basic.rb +0 -16
  86. data/vendor/redis-rb/examples/incr-decr.rb +0 -18
  87. data/vendor/redis-rb/examples/list.rb +0 -26
  88. data/vendor/redis-rb/examples/sets.rb +0 -36
  89. data/vendor/redis-rb/lib/dist_redis.rb +0 -124
  90. data/vendor/redis-rb/lib/hash_ring.rb +0 -128
  91. data/vendor/redis-rb/lib/pipeline.rb +0 -21
  92. data/vendor/redis-rb/lib/redis.rb +0 -370
  93. data/vendor/redis-rb/lib/redis/raketasks.rb +0 -1
  94. data/vendor/redis-rb/profile.rb +0 -22
  95. data/vendor/redis-rb/redis-rb.gemspec +0 -30
  96. data/vendor/redis-rb/spec/redis_spec.rb +0 -637
  97. data/vendor/redis-rb/spec/spec_helper.rb +0 -4
  98. data/vendor/redis-rb/speed.rb +0 -16
  99. data/vendor/redis-rb/tasks/redis.tasks.rb +0 -140
data/CHANGELOG CHANGED
@@ -1,12 +1,70 @@
1
+ == 1.4.0 (Pending)
2
+
3
+ Note: Run this command to upgrade your database to 1.4, or you will not have
4
+ access to collected metrics and experiment data:
5
+
6
+ vanity upgrade
7
+
8
+
9
+ Connection adapters! We have a new way for managing connections which extends
10
+ to multiple adapters (not just Redis). The easiest is to use the configuration
11
+ file config/vanity.yml. For example:
12
+
13
+ production:
14
+ adapter: redis
15
+ worker:
16
+ adapter: mongodb
17
+
18
+ Redis is carried forward and we get MongoDB adapter. Instead of using mock
19
+ adapter or calling playground.test!, turn collection off when running outside
20
+ production. Under Rails, collection is turned off in all environment except
21
+ production. You can control it using:
22
+
23
+ Vanity.playground.collection = true/false.
24
+
25
+
26
+ This release switches from older vendored version of the Redis gem to the new
27
+ 2.0.x gem that is now required as a separate dependency. If your own code
28
+ relies on the Redis gem, watch out for subtle incompatibilities introduced in
29
+ 2.0.
30
+
31
+ Now using RVM, gemsets and Bundler to test Vanity in different configurations.
32
+ To run the full set of tests in all the supported versions of Ruby:
33
+ rake test:rubies
34
+ To test specific version of Ruby:
35
+ rake test:rubies[1.8.7]
36
+ To switch around:
37
+ rvm 1.9.2@vanity
38
+
39
+ * Added: Adapter API, see Vanity::Adapters::AbstractAdapter and
40
+ Vanity::Adapters::RedisAdapter.
41
+ * Added: MongoDB support.
42
+ * Added: Upgrade command.
43
+ * Added: Metric.last_update_at.
44
+ * Added: Vanity.playground.collecting. You want this to be true only in
45
+ production environment. When false, disables collecting of metric and
46
+ experiment data.
47
+ * Added: Remote metrics. Push data to remote service.
48
+ * Added: Partial support for multi-series metrics. Laying the ground for the
49
+ future.
50
+ * Change: Vanity.playground.redis and redis= methods are deprecated, use
51
+ connection and establish_connection instead.
52
+ * Removed: Metric.created_at, derived from experiment and never used.
53
+
54
+
1
55
  == 1.3.0 (2010-03-01)
2
- This release adds support for Google Analytics, AdWords and forking servers (Passenger, Unicorn).
3
56
 
4
- To view Google Analytics metrics from within Vanity, first make sure you are using Garb. For example, in your Gemfile:
57
+ This release adds support for Google Analytics, AdWords and forking servers
58
+ (Passenger, Unicorn).
59
+
60
+ To view Google Analytics metrics from within Vanity, first make sure you are
61
+ using Garb. For example, in your Gemfile:
5
62
 
6
63
  gem "vanity", "1.3.0"
7
64
  gem "garb", "0.5.0"
8
65
 
9
- Next, authenticate using your account credentials. For example, in your config/environments/production.rb:
66
+ Next, authenticate using your account credentials. For example, in your
67
+ config/environments/production.rb:
10
68
 
11
69
  require "garb"
12
70
  Garb::Session.login('..email..', '..password..', account_type: "GOOGLE") rescue nil
data/Gemfile CHANGED
@@ -1,16 +1,24 @@
1
1
  source "http://rubygems.org/"
2
- gem "autotest"
3
- gem "autotest-fsevent"
4
- gem "autotest-growl"
5
- gem "bundler"
6
2
  gem "garb"
7
- gem "jekyll"
8
- gem "mocha"
9
- gem "passenger"
10
- gem "rails", "2.3.5"
11
- gem "rack", "1.0.1"
12
- gem "rubygems-update"
13
- gem "shoulda"
14
- gem "sqlite3-ruby"
15
- gem "timecop"
16
- gem "yard"
3
+ gem "redis"
4
+ gem "redis-namespace"
5
+
6
+ group :development do
7
+ gem "jekyll"
8
+ gem "rake"
9
+ gem "RedCloth"
10
+ gem "yard"
11
+ end
12
+
13
+ group :test do
14
+ gem "bson_ext"
15
+ gem "mocha"
16
+ gem "mongo"
17
+ gem "passenger"
18
+ gem "rails", "2.3.8"
19
+ gem "rack", "1.1.0"
20
+ gem "shoulda"
21
+ gem "sqlite3-ruby", "1.2.5" # 1.3.0 doesn't like Ruby 1.9.1
22
+ gem "timecop"
23
+ gem "webmock"
24
+ end
data/README.rdoc CHANGED
@@ -2,7 +2,6 @@ Vanity is an Experiment Driven Development framework for Rails.
2
2
 
3
3
  * All about Vanity: http://vanity.labnotes.org
4
4
  * On github: http://github.com/assaf/vanity
5
- * Vanity requires Redis 1.0 or later.
6
5
 
7
6
  http://farm3.static.flickr.com/2540/4099665871_497f274f68_o.jpg
8
7
 
@@ -60,10 +59,16 @@ And:
60
59
 
61
60
  To run the test suite for the first time:
62
61
 
63
- $ bundle install
64
- $ bundle exec rake
62
+ $ rake test:setup test
65
63
 
66
- You can also +rake test+ if you insist on being explicit.
64
+ Vanity is tested against multiple Ruby implementations. To run the full test
65
+ suite against all Ruby implementations and bundled adapters:
66
+
67
+ $ rake test:rubies
68
+ $ # only ruby 1.9.2
69
+ $ rake test:rubies[1.9.2]
70
+ $ # only redis
71
+ $ rake test:adapters[redis]
67
72
 
68
73
  To build the documentation:
69
74
 
data/Rakefile CHANGED
@@ -1,9 +1,11 @@
1
1
  require "rake/testtask"
2
2
 
3
+ # -- Building stuff --
4
+
3
5
  spec = Gem::Specification.load(File.expand_path("vanity.gemspec", File.dirname(__FILE__)))
4
6
 
5
7
  desc "Build the Gem"
6
- task :build=>:test do
8
+ task :build do
7
9
  sh "gem build #{spec.name}.gemspec"
8
10
  end
9
11
 
@@ -14,7 +16,7 @@ task :install=>:build do
14
16
  end
15
17
 
16
18
  desc "Push new release to gemcutter and git tag"
17
- task :push=>:build do
19
+ task :push=>["test:rubies", "build"] do
18
20
  sh "git push"
19
21
  puts "Tagging version #{spec.version} .."
20
22
  sh "git tag v#{spec.version}"
@@ -24,10 +26,64 @@ task :push=>:build do
24
26
  end
25
27
 
26
28
 
29
+ # -- Testing stuff --
30
+
31
+ # Ruby versions we're testing with.
32
+ RUBIES = %w{1.8.7 1.9.1 1.9.2}
33
+
34
+ # Use rake test:rubies to run all combination of tests (see test:adapters) using
35
+ # all the versions of Ruby specified in RUBIES. Or to test a specific version of
36
+ # Ruby, rake test:rubies[1.8.7].
37
+ #
38
+ # This task uses RVM to install all the Ruby versions it needs, and creates a
39
+ # vanity gemset in each one that includes Bundler and all the gems specified in
40
+ # Gemfile. If anything goes south you can always wipe these gemsets or uninstall
41
+ # these Rubies and start over.
42
+ desc "Test using multiple versions of Ruby"
43
+ task "test:rubies", :ruby do |t, args|
44
+ rubies = args.ruby ? [args.ruby] : RUBIES
45
+ rubies.each do |ruby|
46
+ puts "** Setup #{ruby}"
47
+ sh "env rvm_install_on_use_flag=1 rvm_gemset_create_on_use_flag=1 rvm use #{ruby}@vanity"
48
+ sh "rvm #{ruby}@vanity rake test:setup"
49
+ puts
50
+ puts "** Test using #{ruby}"
51
+ sh "rvm #{ruby}@vanity -S bundle exec rake test:adapters #{'--trace' if Rake.application.options.trace}"
52
+ end
53
+ end
54
+
55
+ task "test:setup" do
56
+ # Intended to be used from test:rubies, within specific RVM context.
57
+ begin # Make sure we got Bundler installed.
58
+ require "bundler"
59
+ rescue LoadError
60
+ sh "gem install bundler"
61
+ end
62
+ begin # Make sure we got all the dependencies
63
+ sh "bundle exec ruby -e puts > /dev/null"
64
+ rescue
65
+ sh "bundle install"
66
+ end
67
+ end
68
+
69
+ # These are all the adapters we're going to test with.
70
+ ADAPTERS = %w{redis mongodb}
71
+
72
+ desc "Test using different back-ends"
73
+ task "test:adapters", :adapter do |t, args|
74
+ adapters = args.adapter ? [args.adapter] : ADAPTERS
75
+ adapters.each do |adapter|
76
+ puts "** Testing #{adapter} adapter"
77
+ sh "rake test ADAPTER=#{adapter} #{'--trace' if Rake.application.options.trace}"
78
+ end
79
+ end
80
+
81
+ # Run the test suit.
82
+
27
83
  task :default=>:test
28
- desc "Run all tests using Redis mock (also default task)"
84
+ desc "Run all tests"
29
85
  Rake::TestTask.new do |task|
30
- task.test_files = FileList['test/*_test.rb']
86
+ task.test_files = FileList['test/**/*_test.rb']
31
87
  if Rake.application.options.trace
32
88
  #task.warning = true
33
89
  task.verbose = true
@@ -36,17 +92,14 @@ Rake::TestTask.new do |task|
36
92
  else
37
93
  task.verbose = true
38
94
  end
39
- end
40
-
41
- desc "Run all tests using live redis server"
42
- task "test:redis" do
43
- ENV["REDIS"] = "true"
44
- task(:test).invoke
95
+ task.ruby_opts << "-I."
45
96
  end
46
97
 
47
98
  task(:clobber) { rm_rf "tmp" }
48
99
 
49
100
 
101
+ # -- Documenting stuff --
102
+
50
103
  begin
51
104
  require "yard"
52
105
  YARD::Rake::YardocTask.new(:yardoc) do |task|
@@ -59,10 +112,15 @@ end
59
112
  desc "Jekyll generates the main documentation (sans API)"
60
113
  task(:jekyll) { sh "jekyll", "doc", "html" }
61
114
 
115
+ file "html/vanity-api-#{spec.version}.zip"=>:yardoc do |t|
116
+ Dir.chdir "html" do
117
+ sh "zip vanity-api-#{spec.version}.zip -r api"
118
+ end
119
+ end
62
120
  desc "Create documentation in docs directory (including API)"
63
- task :docs=>[:jekyll, :yardoc]
121
+ task :docs=>[:jekyll, :yardoc, "html/vanity-api-#{spec.version}.zip"]
64
122
  desc "Remove temporary files and directories"
65
- task(:clobber) { rm_rf "html" }
123
+ task(:clobber) { rm_rf "html" ; rm_rf ".yardoc" }
66
124
 
67
125
  desc "Publish documentation to vanity.labnotes.org"
68
126
  task :publish=>[:clobber, :docs] do
@@ -70,6 +128,8 @@ task :publish=>[:clobber, :docs] do
70
128
  end
71
129
 
72
130
 
131
+ # -- Misc --
132
+
73
133
  task :report do
74
134
  $LOAD_PATH.unshift "lib"
75
135
  require "vanity"
data/bin/vanity CHANGED
@@ -17,6 +17,7 @@ opts = OptionParser.new("", 24, " ") do |opts|
17
17
  opts.banner << "Commands:\n"
18
18
  opts.banner << " list List all experiments and metrics\n"
19
19
  opts.banner << " report Report on all running experiments/metrics\n"
20
+ opts.banner << " upgrade Upgrade your database when deploying new release\n"
20
21
 
21
22
  opts.separator ""
22
23
  opts.separator "Reporting options:"
@@ -29,8 +30,12 @@ opts = OptionParser.new("", 24, " ") do |opts|
29
30
  opts.on "--load_path PATH", "Path to experiments directory (default: #{playground.load_path})" do |path|
30
31
  playground.load_path = path
31
32
  end
32
- opts.on "--redis HOST:PORT:DB", "Redis server host (default: localhost:6379)" do |redis|
33
- playground.redis = redis
33
+ opts.on "-d", "--database url", "Database connection URL (e.g. redis:/localhost:6379)" do |conn|
34
+ playground.establish_connection conn
35
+ end
36
+ opts.on "--redis HOST:PORT:DB", "DEPRECATED: Redis server host (default: localhost:6379)" do |redis|
37
+ host, port, db = redis.split(":")
38
+ playground.establish_connection "redis:/#{host}:#{port}/#{db}"
34
39
  end
35
40
  opts.on_tail "-h", "--help", "Show this message" do
36
41
  puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
@@ -50,8 +55,15 @@ end
50
55
 
51
56
  ARGV.each do |cmd|
52
57
  case cmd
53
- when "report"; Vanity::Commands.report options.output
54
- when "list"; Vanity::Commands.list
58
+ when "report"
59
+ require "vanity/commands/report"
60
+ Vanity::Commands.report options.output
61
+ when "list"
62
+ require "vanity/commands/list"
63
+ Vanity::Commands.list
64
+ when "upgrade"
65
+ require "vanity/commands/upgrade"
66
+ Vanity::Commands.upgrade
55
67
  else fail "No such command: #{cmd}"
56
68
  end
57
69
  end
data/lib/vanity.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  require "date"
2
2
  require "time"
3
3
  require "logger"
4
-
5
- $LOAD_PATH << File.join(File.dirname(__FILE__), "../vendor/redis-rb/lib")
6
- autoload :Redis, "redis"
4
+ require "cgi"
7
5
 
8
6
  # All the cool stuff happens in other places.
9
7
  # @see Vanity::Helper
@@ -28,13 +26,17 @@ require "vanity/backport" if RUBY_VERSION < "1.9"
28
26
  require "vanity/metric/base"
29
27
  require "vanity/metric/active_record"
30
28
  require "vanity/metric/google_analytics"
29
+ require "vanity/metric/remote"
31
30
  # Experiments.
32
31
  require "vanity/experiment/base"
33
32
  require "vanity/experiment/ab_test"
33
+ # Database adapters
34
+ require "vanity/adapters/abstract_adapter"
35
+ require "vanity/adapters/redis_adapter"
36
+ require "vanity/adapters/mongo_adapter"
37
+ require "vanity/adapters/mock_adapter"
34
38
  # Playground.
35
39
  require "vanity/playground"
36
40
  require "vanity/helpers"
37
- Vanity.autoload :MockRedis, "vanity/mock_redis"
38
- Vanity.autoload :Commands, "vanity/commands"
39
41
  # Integration with various frameworks.
40
42
  require "vanity/frameworks/rails" if defined?(Rails)
@@ -0,0 +1,135 @@
1
+ module Vanity
2
+ module Adapters
3
+
4
+ class << self
5
+ # Creates new connection to underlying datastore and returns suitable
6
+ # adapter (adapter object extends AbstractAdapter and wraps the
7
+ # connection). Vanity.playgroup.establish_connection uses this.
8
+ #
9
+ # @since 1.4.0
10
+ def establish_connection(spec)
11
+ adapter_method = "#{spec[:adapter]}_connection"
12
+ send adapter_method, spec
13
+ end
14
+ end
15
+
16
+ # Base class for all adapters. Adapters wrap underlying connection to a
17
+ # datastore and implement an API that Vanity can use to store/access
18
+ # metrics, experiments, etc.
19
+ class AbstractAdapter
20
+ # Returns true if connected.
21
+ def active?
22
+ false
23
+ end
24
+
25
+ # Close connection, release any resources.
26
+ def disconnect!
27
+ end
28
+
29
+ # Close and reopen connection.
30
+ def reconnect!
31
+ end
32
+
33
+ # Empty the database. This is used during tests.
34
+ def flushdb
35
+ end
36
+
37
+
38
+ # -- Metrics --
39
+
40
+ # Return when metric was last updated.
41
+ def get_metric_last_update_at(metric)
42
+ fail "Not implemented"
43
+ end
44
+
45
+ # Track metric data.
46
+ def metric_track(metric, timestamp, identity, values)
47
+ fail "Not implemented"
48
+ end
49
+
50
+ # Returns all the metric values between from and to time instances
51
+ # (inclusive). Returns pairs of date and total count for that date.
52
+ def metric_values(metric, from, to)
53
+ fail "Not implemented"
54
+ end
55
+
56
+ # Deletes all information about this metric.
57
+ def destroy_metric(metric)
58
+ fail "Not implemented"
59
+ end
60
+
61
+
62
+ # -- Experiments --
63
+
64
+ # Store when experiment was created (do not write over existing value).
65
+ def set_experiment_created_at(experiment, time)
66
+ fail "Not implemented"
67
+ end
68
+
69
+ # Return when experiment was created.
70
+ def get_experiment_created_at(experiment)
71
+ fail "Not implemented"
72
+ end
73
+
74
+ # Returns true if experiment completed.
75
+ def is_experiment_completed?(experiment)
76
+ fail "Not implemented"
77
+ end
78
+
79
+ # Returns counts for given A/B experiment and alternative (by index).
80
+ # Returns hash with values for the keys :participants, :converted and
81
+ # :conversions.
82
+ def ab_counts(experiment, alternative)
83
+ fail "Not implemented"
84
+ end
85
+
86
+ # Pick particular alternative (by index) to show to this particular
87
+ # participant (by identity).
88
+ def ab_show(experiment, identity, alternative)
89
+ fail "Not implemented"
90
+ end
91
+
92
+ # Indicates which alternative to show to this participant. See #ab_show.
93
+ def ab_showing(experiment, identity)
94
+ fail "Not implemented"
95
+ end
96
+
97
+ # Cancels previously set association between identity and alternative. See
98
+ # #ab_show.
99
+ def ab_not_showing(experiment, identity)
100
+ fail "Not implemented"
101
+ end
102
+
103
+ # Records a participant in this experiment for the given alternative.
104
+ def ab_add_participant(experiment, alternative, identity)
105
+ fail "Not implemented"
106
+ end
107
+
108
+ # Records a conversion in this experiment for the given alternative.
109
+ # Associates a value with the conversion (default to 1). If implicit is
110
+ # true, add particpant if not already recorded for this experiment. If
111
+ # implicit is false (default), only add conversion is participant
112
+ # previously recorded as participating in this experiment.
113
+ def ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false)
114
+ fail "Not implemented"
115
+ end
116
+
117
+ # Returns the outcome of this expriment (if set), the index of a
118
+ # particular alternative.
119
+ def ab_get_outcome(experiment)
120
+ fail "Not implemented"
121
+ end
122
+
123
+ # Sets the outcome of this experiment to a particular alternative.
124
+ def ab_set_outcome(experiment, alternative = 0)
125
+ fail "Not implemented"
126
+ end
127
+
128
+ # Deletes all information about this experiment.
129
+ def destroy_experiment(experiment)
130
+ fail "Not implemented"
131
+ end
132
+
133
+ end
134
+ end
135
+ end