abingo_port 0.1.0
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.
- data/.gitignore +1 -0
- data/MIT-LICENSE +20 -0
- data/README +160 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/abingo.gemspec +72 -0
- data/init.rb +5 -0
- data/install.rb +1 -0
- data/lib/abingo.rb +235 -0
- data/lib/abingo/alternative.rb +23 -0
- data/lib/abingo/controller/dashboard.rb +25 -0
- data/lib/abingo/conversion_rate.rb +9 -0
- data/lib/abingo/experiment.rb +99 -0
- data/lib/abingo/rails/controller/dashboard.rb +13 -0
- data/lib/abingo/railtie.rb +12 -0
- data/lib/abingo/statistics.rb +90 -0
- data/lib/abingo/views/dashboard/_experiment.erb +43 -0
- data/lib/abingo/views/dashboard/index.erb +20 -0
- data/lib/abingo_sugar.rb +28 -0
- data/lib/abingo_view_helper.rb +42 -0
- data/lib/generators/abingo_migration/USAGE +8 -0
- data/lib/generators/abingo_migration/abingo_migration_generator.rb +13 -0
- data/lib/generators/abingo_migration/templates/create_abingo_tables.rb +29 -0
- data/lib/generators/abingo_views/USAGE +8 -0
- data/lib/generators/abingo_views/abingo_views_generator.rb +9 -0
- data/lib/generators/abingo_views/templates/views/dashboard/_experiment.html.erb +43 -0
- data/lib/generators/abingo_views/templates/views/dashboard/index.html.erb +20 -0
- data/strip.rb +11 -0
- data/tasks/abingo_tasks.rake +4 -0
- data/test/abingo_test.rb +135 -0
- data/test/test_helper.rb +3 -0
- data/uninstall.rb +1 -0
- metadata +99 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
class AbingoViewsGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
|
4
|
+
|
5
|
+
def copy_views
|
6
|
+
copy_file "views/dashboard/_experiment.html.erb", "app/views/dashboard/_experiment.html.erb"
|
7
|
+
copy_file "views/dashboard/index.html.erb", "app/views/dashboard/index.html.erb"
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<h3><%= experiment.test_name.titleize %> <%= %Q|<i>(Test completed)</i>| if experiment.status != "Live" %> </h3>
|
2
|
+
<% short_circuit = Abingo.cache.read("Abingo::Experiment::short_circuit(#{experiment.test_name})".gsub(" ", "")) %>
|
3
|
+
<table class="experiment" style="border: 1px black;">
|
4
|
+
<tr class="header_row">
|
5
|
+
<th>Name</th>
|
6
|
+
<th>Participants</th>
|
7
|
+
<th>Conversions</th>
|
8
|
+
<th>Notes</th>
|
9
|
+
</tr>
|
10
|
+
<tr class="experiment_row">
|
11
|
+
<td>Experiment Total: </td>
|
12
|
+
<td><%= experiment.participants %> </td>
|
13
|
+
<td><%= experiment.conversions %> (<%= experiment.pretty_conversion_rate %>)</td>
|
14
|
+
<td></td>
|
15
|
+
</tr>
|
16
|
+
<% experiment.alternatives.each do |alternative| %>
|
17
|
+
<tr class="alternative_row">
|
18
|
+
<td>
|
19
|
+
<%= h alternative.content %>
|
20
|
+
</td>
|
21
|
+
<td><%= alternative.participants %></td>
|
22
|
+
<td><%= alternative.conversions %> (<%= alternative.pretty_conversion_rate %>)</td>
|
23
|
+
<td>
|
24
|
+
<% unless experiment.status != "Live" %>
|
25
|
+
<%= link_to("End experiment, picking this.", url_for(:id => alternative.id,
|
26
|
+
:action => "end_experiment"),
|
27
|
+
:method => :post,
|
28
|
+
:confirm => "Are you sure you want to terminate this experiment? This is not reversible."
|
29
|
+
) %>
|
30
|
+
<% else %>
|
31
|
+
<% if alternative.content == short_circuit %>
|
32
|
+
<b>(All users seeing this.)</b>
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
<tr>
|
39
|
+
<td colspan="4">
|
40
|
+
<b>Significance test results: </b><%= experiment.describe_result_in_words %>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
</table>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div id="abingo_dashboard">
|
2
|
+
<p><h1>Welcome to your A/Bingo dashboard!</h1>
|
3
|
+
|
4
|
+
See <a href="http://www.bingocardcreator.com/abingo">the official site</a> for documentation.
|
5
|
+
I encourage you to customize this page to fit your needs. See /vendor/plugins/abingo/views for
|
6
|
+
the view templates. Hack them to pieces -- please!
|
7
|
+
</p>
|
8
|
+
|
9
|
+
<p>
|
10
|
+
<% if flash[:notice] %>
|
11
|
+
<span style="color: green;"><%= flash[:notice] %> </span>
|
12
|
+
<% end %>
|
13
|
+
<h2>All Experiments</h2>
|
14
|
+
|
15
|
+
<% @experiments.each do |experiment| %>
|
16
|
+
<%= render :partial => "dashboard/experiment", :locals => {:experiment => experiment} %>
|
17
|
+
<br/>
|
18
|
+
<% end %>
|
19
|
+
</p>
|
20
|
+
</div>
|
data/strip.rb
ADDED
data/test/abingo_test.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AbingoTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
#Wipes cache, D/B prior to doing a test run.
|
6
|
+
Abingo.cache.clear
|
7
|
+
Abingo::Experiment.delete_all
|
8
|
+
Abingo::Alternative.delete_all
|
9
|
+
|
10
|
+
test "identity automatically assigned" do
|
11
|
+
assert Abingo.identity != nil
|
12
|
+
end
|
13
|
+
|
14
|
+
test "alternative parsing" do
|
15
|
+
array = %w{a b c}
|
16
|
+
assert_equal array, Abingo.parse_alternatives(array)
|
17
|
+
assert_equal 65, Abingo.parse_alternatives(65).size
|
18
|
+
assert_equal 4, Abingo.parse_alternatives(2..5).size
|
19
|
+
assert !(Abingo.parse_alternatives(2..5).include? 1)
|
20
|
+
end
|
21
|
+
|
22
|
+
test "experiment creation" do
|
23
|
+
assert_equal 0, Abingo::Experiment.count
|
24
|
+
assert_equal 0, Abingo::Alternative.count
|
25
|
+
alternatives = %w{A B}
|
26
|
+
alternative_selected = Abingo.test("unit_test_sample_A", alternatives)
|
27
|
+
assert_equal 1, Abingo::Experiment.count
|
28
|
+
assert_equal 2, Abingo::Alternative.count
|
29
|
+
assert alternatives.include?(alternative_selected)
|
30
|
+
end
|
31
|
+
|
32
|
+
test "exists works right" do
|
33
|
+
Abingo.test("exist works right", %w{does does_not})
|
34
|
+
assert Abingo::Experiment.exists?("exist works right")
|
35
|
+
end
|
36
|
+
|
37
|
+
test "alternatives picked consistently" do
|
38
|
+
alternative_picked = Abingo.test("consistency_test", 1..100)
|
39
|
+
100.times do
|
40
|
+
assert_equal alternative_picked, Abingo.test("consistency_test", 1..100)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test "participation works" do
|
45
|
+
new_tests = %w{participationA participationB participationC}
|
46
|
+
new_tests.map do |test_name|
|
47
|
+
Abingo.test(test_name, 1..5)
|
48
|
+
end
|
49
|
+
|
50
|
+
participating_tests = Abingo.cache.read("Abingo::participating_tests::#{Abingo.identity}") || []
|
51
|
+
|
52
|
+
new_tests.map do |test_name|
|
53
|
+
assert participating_tests.include? test_name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
test "participants counted" do
|
58
|
+
test_name = "participants_counted_test"
|
59
|
+
alternative = Abingo.test(test_name, %w{a b c})
|
60
|
+
|
61
|
+
ex = Abingo::Experiment.find_by_test_name(test_name)
|
62
|
+
lookup = Abingo::Alternative.calculate_lookup(test_name, alternative)
|
63
|
+
chosen_alt = Abingo::Alternative.find_by_lookup(lookup)
|
64
|
+
assert_equal 1, ex.participants
|
65
|
+
assert_equal 1, chosen_alt.participants
|
66
|
+
end
|
67
|
+
|
68
|
+
test "conversion tracking by test name" do
|
69
|
+
test_name = "conversion_test_by_name"
|
70
|
+
alternative = Abingo.test(test_name, %w{a b c})
|
71
|
+
Abingo.bingo!(test_name)
|
72
|
+
ex = Abingo::Experiment.find_by_test_name(test_name)
|
73
|
+
lookup = Abingo::Alternative.calculate_lookup(test_name, alternative)
|
74
|
+
chosen_alt = Abingo::Alternative.find_by_lookup(lookup)
|
75
|
+
assert_equal 1, ex.conversions
|
76
|
+
assert_equal 1, chosen_alt.conversions
|
77
|
+
Abingo.bingo!(test_name)
|
78
|
+
|
79
|
+
#Should still only have one because this conversion should not be double counted.
|
80
|
+
#We haven't specified that in the test options.
|
81
|
+
assert_equal 1, Abingo::Experiment.find_by_test_name(test_name).conversions
|
82
|
+
end
|
83
|
+
|
84
|
+
test "conversion tracking by conversion name" do
|
85
|
+
conversion_name = "purchase"
|
86
|
+
tests = %w{conversionTrackingByConversionNameA conversionTrackingByConversionNameB conversionTrackingByConversionNameC}
|
87
|
+
tests.map do |test_name|
|
88
|
+
Abingo.test(test_name, %w{A B}, :conversion => conversion_name)
|
89
|
+
end
|
90
|
+
|
91
|
+
Abingo.bingo!(conversion_name)
|
92
|
+
tests.map do |test_name|
|
93
|
+
assert_equal 1, Abingo::Experiment.find_by_test_name(test_name).conversions
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test "short circuiting works" do
|
98
|
+
conversion_name = "purchase"
|
99
|
+
test_name = "short circuit test"
|
100
|
+
alt_picked = Abingo.test(test_name, %w{A B}, :conversion => conversion_name)
|
101
|
+
ex = Abingo::Experiment.find_by_test_name(test_name)
|
102
|
+
alt_not_picked = (%w{A B} - [alt_picked]).first
|
103
|
+
|
104
|
+
ex.end_experiment!(alt_not_picked, conversion_name)
|
105
|
+
|
106
|
+
ex.reload
|
107
|
+
assert_equal "Finished", ex.status
|
108
|
+
|
109
|
+
Abingo.bingo!(test_name) #Should not be counted, test is over.
|
110
|
+
assert_equal 0, ex.conversions
|
111
|
+
|
112
|
+
old_identity = Abingo.identity
|
113
|
+
Abingo.identity = "shortCircuitTestNewIdentity"
|
114
|
+
Abingo.test(test_name, %w{A B}, :conversion => conversion_name)
|
115
|
+
Abingo.identity = old_identity
|
116
|
+
ex.reload
|
117
|
+
assert_equal 1, ex.participants #Original identity counted, new identity not counted b/c test stopped
|
118
|
+
end
|
119
|
+
|
120
|
+
test "proper experiment creation in high concurrency" do
|
121
|
+
conversion_name = "purchase"
|
122
|
+
test_name = "high_concurrency_test"
|
123
|
+
alternatives = %w{foo bar}
|
124
|
+
|
125
|
+
threads = []
|
126
|
+
5.times do
|
127
|
+
threads << Thread.new do
|
128
|
+
Abingo.test(test_name, alternatives, conversion_name)
|
129
|
+
1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
sleep(10)
|
133
|
+
assert_equal 1, Abingo::Experiment.count_by_sql(["select count(id) from experiments where test_name = ?", test_name])
|
134
|
+
end
|
135
|
+
end
|
data/test/test_helper.rb
ADDED
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abingo_port
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Wildfalcon
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-07 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Incorperate AB Testing into your rails apps
|
23
|
+
email: laurie@wildfalcon.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- MIT-LICENSE
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- abingo.gemspec
|
37
|
+
- init.rb
|
38
|
+
- install.rb
|
39
|
+
- lib/abingo.rb
|
40
|
+
- lib/abingo/alternative.rb
|
41
|
+
- lib/abingo/controller/dashboard.rb
|
42
|
+
- lib/abingo/conversion_rate.rb
|
43
|
+
- lib/abingo/experiment.rb
|
44
|
+
- lib/abingo/rails/controller/dashboard.rb
|
45
|
+
- lib/abingo/railtie.rb
|
46
|
+
- lib/abingo/statistics.rb
|
47
|
+
- lib/abingo/views/dashboard/_experiment.erb
|
48
|
+
- lib/abingo/views/dashboard/index.erb
|
49
|
+
- lib/abingo_sugar.rb
|
50
|
+
- lib/abingo_view_helper.rb
|
51
|
+
- lib/generators/abingo_migration/USAGE
|
52
|
+
- lib/generators/abingo_migration/abingo_migration_generator.rb
|
53
|
+
- lib/generators/abingo_migration/templates/create_abingo_tables.rb
|
54
|
+
- lib/generators/abingo_views/USAGE
|
55
|
+
- lib/generators/abingo_views/abingo_views_generator.rb
|
56
|
+
- lib/generators/abingo_views/templates/views/dashboard/_experiment.html.erb
|
57
|
+
- lib/generators/abingo_views/templates/views/dashboard/index.html.erb
|
58
|
+
- strip.rb
|
59
|
+
- tasks/abingo_tasks.rake
|
60
|
+
- test/abingo_test.rb
|
61
|
+
- test/test_helper.rb
|
62
|
+
- uninstall.rb
|
63
|
+
has_rdoc: true
|
64
|
+
homepage: http://github.com/wildfalcon/abingo
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --charset=UTF-8
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.7
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: A/B Testing for Rails
|
97
|
+
test_files:
|
98
|
+
- test/abingo_test.rb
|
99
|
+
- test/test_helper.rb
|