ab_panel 0.0.9 → 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.
- checksums.yaml +7 -0
- data/README.md +14 -12
- data/ab_panel.gemspec +2 -2
- data/example/app/controllers/application_controller.rb +1 -2
- data/example/app/controllers/posts_controller.rb +5 -18
- data/example/config/environments/development.rb +2 -0
- data/example/config/environments/production.rb +2 -0
- data/example/config/mixpanel.yml +4 -3
- data/lib/ab_panel/controller_additions.rb +75 -95
- data/lib/ab_panel/javascript.rb +1 -1
- data/lib/ab_panel/mixpanel.rb +25 -8
- data/lib/ab_panel/version.rb +1 -1
- data/lib/ab_panel.rb +15 -10
- metadata +19 -43
- data/example/config/initializers/mixpanel_middleware.rb +0 -2
- data/example/public/index.html +0 -241
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ca41b9170ae4617dee1623e58c77c4964d71caa
|
4
|
+
data.tar.gz: b0a191f70c30e6efd7521cfbfde7b0acf79872ca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb555a360068bcbda0cd7242c97d93e58f2e81f55bf2752454bd5cd65a69bb8f92359e31e3807441e894a2bdcddb775aca292cc0ea5a9f9298c382536816baf7
|
7
|
+
data.tar.gz: 05a0bc19937ba1266539051a49ec892369cdebd2b20c37fd19af6eb4bcd13f7367d87f424ce18352789e58814e1d76662fccdfa900409da77b4524ab561aa8e1
|
data/README.md
CHANGED
@@ -40,19 +40,21 @@ You can add as many experiments and conditions as you want. Every visitor
|
|
40
40
|
will be assigned randomly to one condition for each scenario for as long as
|
41
41
|
their session remains active.
|
42
42
|
|
43
|
-
To track events in [Mixpanel](https://mixpanel.com),
|
44
|
-
api key, api secret, and the token of of your
|
43
|
+
To track events in [Mixpanel](https://mixpanel.com), create a file called
|
44
|
+
`config/mixpanel.yml` with your api key, api secret, and the token of of your
|
45
|
+
project for every environment you want to run Mixpanel in, like so:
|
45
46
|
|
46
47
|
```yaml
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
production:
|
49
|
+
api_key: 383340bfea74ab839ebb667ab3c59fa3
|
50
|
+
api_secret: 3990703d6d73d2b7fd78a1d19de66605
|
51
|
+
token: 735cc06a1b1ded4827d7faff385ad6fc
|
50
52
|
```
|
51
53
|
|
52
|
-
Enable the Mixpanel Middleware by
|
54
|
+
Enable the Mixpanel Middleware by adding it in the [necessary environments](example/config/environments/production.rb#L68):
|
53
55
|
|
54
56
|
```ruby
|
55
|
-
|
57
|
+
config.middleware.use Mixpanel::Middleware, AbPanel::Mixpanel::Config.token, persist: true
|
56
58
|
```
|
57
59
|
|
58
60
|
See [Mixpanel Gem docs](https://github.com/zevarito/mixpanel#rack-middleware) on the Middleware for more info.
|
@@ -61,7 +63,7 @@ In your application controller:
|
|
61
63
|
|
62
64
|
```ruby
|
63
65
|
class ApplicationController < ActionController::Base
|
64
|
-
initialize_ab_panel!
|
66
|
+
before_filter :initialize_ab_panel!
|
65
67
|
end
|
66
68
|
```
|
67
69
|
|
@@ -69,9 +71,9 @@ Then track any event you want from your controller:
|
|
69
71
|
|
70
72
|
```ruby
|
71
73
|
class CoursesController < ApplicationController
|
72
|
-
|
73
|
-
|
74
|
-
|
74
|
+
def show
|
75
|
+
track_action '[visits] Course', { :course => :id }
|
76
|
+
end
|
75
77
|
end
|
76
78
|
```
|
77
79
|
|
@@ -83,7 +85,7 @@ def show
|
|
83
85
|
track_variable :id, params[:id]
|
84
86
|
|
85
87
|
# Or a hash with variables
|
86
|
-
track_variables params
|
88
|
+
track_variables { id: params[:id], email: current_user.email }
|
87
89
|
end
|
88
90
|
```
|
89
91
|
|
data/ab_panel.gemspec
CHANGED
@@ -6,8 +6,8 @@ require 'ab_panel/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "ab_panel"
|
8
8
|
spec.version = AbPanel::VERSION
|
9
|
-
spec.authors = ["Wouter de Vos"]
|
10
|
-
spec.email = ["wouter@springest.com"]
|
9
|
+
spec.authors = ["Wouter de Vos", "Mark Mulder"]
|
10
|
+
spec.email = ["wouter@springest.com", "markmulder@gmail.com"]
|
11
11
|
spec.description = %q{Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.}
|
12
12
|
spec.summary = %q{Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.}
|
13
13
|
spec.homepage = "https://github.com/Springest/ab_panel"
|
@@ -1,46 +1,37 @@
|
|
1
1
|
class PostsController < ApplicationController
|
2
|
-
track_action '[visits] post', :post => :id, :only => [ :show ]
|
3
|
-
|
4
|
-
# GET /posts
|
5
|
-
# GET /posts.json
|
6
2
|
def index
|
7
3
|
@posts = Post.all
|
8
4
|
|
9
5
|
respond_to do |format|
|
10
|
-
format.html
|
6
|
+
format.html
|
11
7
|
format.json { render json: @posts }
|
12
8
|
end
|
13
9
|
end
|
14
10
|
|
15
|
-
# GET /posts/1
|
16
|
-
# GET /posts/1.json
|
17
11
|
def show
|
18
12
|
@post = Post.find(params[:id])
|
19
13
|
|
20
14
|
respond_to do |format|
|
21
|
-
format.html
|
15
|
+
format.html
|
22
16
|
format.json { render json: @post }
|
23
17
|
end
|
18
|
+
|
19
|
+
track_action '[visits] post', :post => :id
|
24
20
|
end
|
25
21
|
|
26
|
-
# GET /posts/new
|
27
|
-
# GET /posts/new.json
|
28
22
|
def new
|
29
23
|
@post = Post.new
|
30
24
|
|
31
25
|
respond_to do |format|
|
32
|
-
format.html
|
26
|
+
format.html
|
33
27
|
format.json { render json: @post }
|
34
28
|
end
|
35
29
|
end
|
36
30
|
|
37
|
-
# GET /posts/1/edit
|
38
31
|
def edit
|
39
32
|
@post = Post.find(params[:id])
|
40
33
|
end
|
41
34
|
|
42
|
-
# POST /posts
|
43
|
-
# POST /posts.json
|
44
35
|
def create
|
45
36
|
@post = Post.new(params[:post])
|
46
37
|
|
@@ -55,8 +46,6 @@ class PostsController < ApplicationController
|
|
55
46
|
end
|
56
47
|
end
|
57
48
|
|
58
|
-
# PUT /posts/1
|
59
|
-
# PUT /posts/1.json
|
60
49
|
def update
|
61
50
|
@post = Post.find(params[:id])
|
62
51
|
|
@@ -71,8 +60,6 @@ class PostsController < ApplicationController
|
|
71
60
|
end
|
72
61
|
end
|
73
62
|
|
74
|
-
# DELETE /posts/1
|
75
|
-
# DELETE /posts/1.json
|
76
63
|
def destroy
|
77
64
|
@post = Post.find(params[:id])
|
78
65
|
@post.destroy
|
@@ -64,4 +64,6 @@ Example::Application.configure do
|
|
64
64
|
# Log the query plan for queries taking more than this (works
|
65
65
|
# with SQLite, MySQL, and PostgreSQL)
|
66
66
|
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
67
|
+
|
68
|
+
config.middleware.use Mixpanel::Middleware, AbPanel::Mixpanel::Config.token, persist: true
|
67
69
|
end
|
data/example/config/mixpanel.yml
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
development:
|
2
|
+
api_key: 383340bfea74ab839ebb667ab3c59fa3
|
3
|
+
api_secret: 3990703d6d73d2b7fd78a1d19de66605
|
4
|
+
token: 735cc06a1b1ded4827d7faff385ad6fc
|
@@ -26,114 +26,94 @@ module AbPanel
|
|
26
26
|
# own implementation, e.g.:
|
27
27
|
#
|
28
28
|
# `current_user.id` for logged in users.
|
29
|
-
def
|
30
|
-
session['
|
29
|
+
def distinct_id
|
30
|
+
session['distinct_id'] ||=
|
31
31
|
(0..4).map { |i| i.even? ? ('A'..'Z').to_a[rand(26)] : rand(10) }.join
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
def ab_panel_options
|
35
|
+
@ab_panel_options ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Initializes AbPanel's environment.
|
35
39
|
#
|
36
|
-
#
|
37
|
-
#
|
40
|
+
# Typically, this would go in a global before filter.
|
41
|
+
#
|
42
|
+
# class ApplicationController < ActionController::Base
|
43
|
+
# before_filter :initialize_ab_panel!
|
44
|
+
# end
|
38
45
|
#
|
39
|
-
#
|
40
|
-
|
46
|
+
# This makes sure an ab_panel session is re-initialized on every
|
47
|
+
# request. Experiment conditions and unique user id are preserved
|
48
|
+
# in the user's session.
|
49
|
+
def initialize_ab_panel!(options = {})
|
50
|
+
AbPanel.reset!
|
51
|
+
AbPanel.conditions = session['ab_panel_conditions']
|
52
|
+
session['ab_panel_conditions'] = AbPanel.conditions
|
53
|
+
|
41
54
|
{
|
42
|
-
'
|
43
|
-
'
|
44
|
-
'
|
45
|
-
|
46
|
-
|
47
|
-
|
55
|
+
'distinct_id' => distinct_id,
|
56
|
+
'rack.session' => request['rack.session'],
|
57
|
+
'ip' => request.remote_ip
|
58
|
+
}.each do |key, value|
|
59
|
+
AbPanel.set_env(key, value)
|
60
|
+
end
|
48
61
|
end
|
49
62
|
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
# Track controller actions visits.
|
64
|
+
#
|
65
|
+
# name - The name of the event in Mixpanel.
|
66
|
+
# properties - The properties to be associated with the event.
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
#
|
70
|
+
# def show
|
71
|
+
# track_action '[visits] Course', { :course => :id }
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# This will track the event with the given name on CoursesController#show
|
75
|
+
# and assign an options hash:
|
76
|
+
#
|
77
|
+
# { 'course_id' => @course.id }
|
78
|
+
def track_action(name, properties = {})
|
79
|
+
funnel = properties.delete(:funnel)
|
80
|
+
AbPanel.funnels << funnel if funnel.present?
|
81
|
+
|
82
|
+
options = {
|
83
|
+
distinct_id: distinct_id,
|
84
|
+
ip: request.remote_ip,
|
85
|
+
time: Time.now.utc,
|
86
|
+
}
|
53
87
|
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
# Typically, this would go in the ApplicationController.
|
58
|
-
#
|
59
|
-
# class ApplicationController < ActionController::Base
|
60
|
-
# initialize_ab_panel!
|
61
|
-
# end
|
62
|
-
#
|
63
|
-
# This makes sure an ab_panel session is re-initialized on every
|
64
|
-
# request. Experiment conditions and unique user id are preserved
|
65
|
-
# in the user's session.
|
66
|
-
def initialize_ab_panel!(options={})
|
67
|
-
self.before_filter(options.slice(:only, :except)) do |controller|
|
68
|
-
# Persist the conditions.
|
69
|
-
AbPanel.conditions = controller.session['ab_panel_conditions']
|
70
|
-
controller.session['ab_panel_conditions'] = AbPanel.conditions
|
71
|
-
|
72
|
-
{
|
73
|
-
'ab_panel_id' => controller.ab_panel_id
|
74
|
-
}.merge(controller.ab_panel_env).each do |key, val|
|
75
|
-
AbPanel.env_set key, val
|
76
|
-
end
|
77
|
-
end
|
88
|
+
AbPanel.funnels.each do |funnel|
|
89
|
+
options["funnel_#{funnel}"] = true
|
78
90
|
end
|
79
91
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
AbPanel.funnels << funnel if funnel.present?
|
99
|
-
|
100
|
-
options = {
|
101
|
-
distinct_id: controller.ab_panel_id,
|
102
|
-
ip: controller.request.remote_ip,
|
103
|
-
time: Time.now.utc,
|
104
|
-
}
|
105
|
-
|
106
|
-
AbPanel.funnels.each do |funnel|
|
107
|
-
options["funnel_#{funnel}"] = true
|
108
|
-
end
|
109
|
-
|
110
|
-
AbPanel.experiments.each do |exp|
|
111
|
-
options[exp] = AbPanel.conditions.send(exp).condition rescue nil
|
112
|
-
end
|
113
|
-
|
114
|
-
properties.each do |key, val|
|
115
|
-
if controller.respond_to?(key)
|
116
|
-
inst = controller.send(key)
|
117
|
-
elsif controller.instance_variable_defined?("@#{key}")
|
118
|
-
inst = controller.instance_variable_get("@#{key}")
|
119
|
-
else
|
120
|
-
options[key] = val
|
121
|
-
next
|
122
|
-
end
|
123
|
-
|
124
|
-
val = *val
|
125
|
-
|
126
|
-
val.each do |m|
|
127
|
-
options["#{key}_#{m}"] = inst.send(m)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
AbPanel.identify(controller.ab_panel_id)
|
132
|
-
AbPanel.track name, options.merge(controller.ab_panel_options)
|
133
|
-
|
134
|
-
controller.session['mixpanel_events'] ||= AbPanel.env['rack.session']['mixpanel_events'] rescue []
|
92
|
+
AbPanel.experiments.each do |exp|
|
93
|
+
options[exp] = AbPanel.conditions.send(exp).condition rescue nil
|
94
|
+
end
|
95
|
+
|
96
|
+
properties.each do |key, val|
|
97
|
+
if respond_to?(key)
|
98
|
+
inst = send(key)
|
99
|
+
elsif instance_variable_defined?("@#{key}")
|
100
|
+
inst = instance_variable_get("@#{key}")
|
101
|
+
else
|
102
|
+
options[key] = val
|
103
|
+
next
|
104
|
+
end
|
105
|
+
|
106
|
+
val = *val
|
107
|
+
|
108
|
+
val.each do |m|
|
109
|
+
options["#{key}_#{m}"] = inst.send(m)
|
135
110
|
end
|
136
111
|
end
|
112
|
+
|
113
|
+
AbPanel.identify(distinct_id)
|
114
|
+
AbPanel.track(name, options.merge(ab_panel_options))
|
115
|
+
|
116
|
+
session['mixpanel_events'] ||= AbPanel.env['rack.session']['mixpanel_events'] rescue []
|
137
117
|
end
|
138
118
|
end
|
139
119
|
end
|
data/lib/ab_panel/javascript.rb
CHANGED
data/lib/ab_panel/mixpanel.rb
CHANGED
@@ -3,13 +3,14 @@ require 'mixpanel'
|
|
3
3
|
module AbPanel
|
4
4
|
module Mixpanel
|
5
5
|
class Tracker < ::Mixpanel::Tracker
|
6
|
-
def initialize(options={})
|
6
|
+
def initialize(options = {})
|
7
|
+
return if !should_track?
|
8
|
+
|
7
9
|
@tracker = ::Mixpanel::Tracker.new Config.token, ab_panel_options.merge(options)
|
8
10
|
end
|
9
11
|
|
10
12
|
def ab_panel_options
|
11
13
|
opts = {
|
12
|
-
api_key: Config.api_key,
|
13
14
|
env: AbPanel.env,
|
14
15
|
persist: true
|
15
16
|
}
|
@@ -22,26 +23,42 @@ module AbPanel
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def track(event_name, properties)
|
26
|
+
return if !should_track?
|
27
|
+
|
25
28
|
@tracker.append_track event_name, properties
|
26
29
|
end
|
27
30
|
|
28
31
|
def identify(distinct_id)
|
32
|
+
return if !should_track?
|
33
|
+
|
29
34
|
@tracker.append_identify distinct_id
|
30
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def should_track?
|
40
|
+
@should_track ||= Config.environments.include?(Rails.env)
|
41
|
+
end
|
31
42
|
end
|
32
43
|
|
33
44
|
class Config
|
34
|
-
def self.
|
35
|
-
config['
|
45
|
+
def self.token
|
46
|
+
config[Rails.env]['token']
|
36
47
|
end
|
37
48
|
|
38
|
-
def self.
|
39
|
-
config
|
49
|
+
def self.environments
|
50
|
+
config.keys
|
40
51
|
end
|
41
52
|
|
42
53
|
def self.config
|
43
|
-
@settings ||=
|
44
|
-
|
54
|
+
@settings ||= load_config
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def self.load_config
|
60
|
+
file = File.read(File.join(Rails.root, 'config', 'mixpanel.yml'))
|
61
|
+
YAML.load(file)
|
45
62
|
end
|
46
63
|
end
|
47
64
|
end
|
data/lib/ab_panel/version.rb
CHANGED
data/lib/ab_panel.rb
CHANGED
@@ -11,8 +11,8 @@ module AbPanel
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# Identify
|
14
|
-
def identify(
|
15
|
-
tracker.identify
|
14
|
+
def identify(distinct_id)
|
15
|
+
tracker.identify distinct_id
|
16
16
|
end
|
17
17
|
|
18
18
|
def conditions
|
@@ -36,20 +36,25 @@ module AbPanel
|
|
36
36
|
config.scenarios experiment
|
37
37
|
end
|
38
38
|
|
39
|
-
def env_set key, val
|
40
|
-
env[key] = val
|
41
|
-
end
|
42
|
-
|
43
|
-
def funnels
|
44
|
-
env['funnels'] ||= []
|
45
|
-
end
|
46
|
-
|
47
39
|
def env
|
48
40
|
@env ||= {
|
49
41
|
'conditions' => conditions
|
50
42
|
}
|
51
43
|
end
|
52
44
|
|
45
|
+
def reset!
|
46
|
+
@env = nil
|
47
|
+
@conditions = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_env(key, value)
|
51
|
+
env[key] = value
|
52
|
+
end
|
53
|
+
|
54
|
+
def funnels
|
55
|
+
env['funnels'] ||= []
|
56
|
+
end
|
57
|
+
|
53
58
|
private # ----------------------------------------------------------------------------
|
54
59
|
|
55
60
|
def assign_conditions!(already_assigned=nil)
|
metadata
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ab_panel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Wouter de Vos
|
8
|
+
- Mark Mulder
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
17
|
requirements:
|
19
18
|
- - ~>
|
20
19
|
- !ruby/object:Gem::Version
|
@@ -22,7 +21,6 @@ dependencies:
|
|
22
21
|
type: :development
|
23
22
|
prerelease: false
|
24
23
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
24
|
requirements:
|
27
25
|
- - ~>
|
28
26
|
- !ruby/object:Gem::Version
|
@@ -30,7 +28,6 @@ dependencies:
|
|
30
28
|
- !ruby/object:Gem::Dependency
|
31
29
|
name: rails
|
32
30
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
31
|
requirements:
|
35
32
|
- - ~>
|
36
33
|
- !ruby/object:Gem::Version
|
@@ -38,7 +35,6 @@ dependencies:
|
|
38
35
|
type: :development
|
39
36
|
prerelease: false
|
40
37
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
38
|
requirements:
|
43
39
|
- - ~>
|
44
40
|
- !ruby/object:Gem::Version
|
@@ -46,86 +42,77 @@ dependencies:
|
|
46
42
|
- !ruby/object:Gem::Dependency
|
47
43
|
name: rake
|
48
44
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
45
|
requirements:
|
51
|
-
- -
|
46
|
+
- - '>='
|
52
47
|
- !ruby/object:Gem::Version
|
53
48
|
version: '0'
|
54
49
|
type: :development
|
55
50
|
prerelease: false
|
56
51
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
52
|
requirements:
|
59
|
-
- -
|
53
|
+
- - '>='
|
60
54
|
- !ruby/object:Gem::Version
|
61
55
|
version: '0'
|
62
56
|
- !ruby/object:Gem::Dependency
|
63
57
|
name: fakeweb
|
64
58
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
59
|
requirements:
|
67
|
-
- -
|
60
|
+
- - '>='
|
68
61
|
- !ruby/object:Gem::Version
|
69
62
|
version: '0'
|
70
63
|
type: :development
|
71
64
|
prerelease: false
|
72
65
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
66
|
requirements:
|
75
|
-
- -
|
67
|
+
- - '>='
|
76
68
|
- !ruby/object:Gem::Version
|
77
69
|
version: '0'
|
78
70
|
- !ruby/object:Gem::Dependency
|
79
71
|
name: rspec
|
80
72
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
73
|
requirements:
|
83
|
-
- -
|
74
|
+
- - '>='
|
84
75
|
- !ruby/object:Gem::Version
|
85
76
|
version: '0'
|
86
77
|
type: :development
|
87
78
|
prerelease: false
|
88
79
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
80
|
requirements:
|
91
|
-
- -
|
81
|
+
- - '>='
|
92
82
|
- !ruby/object:Gem::Version
|
93
83
|
version: '0'
|
94
84
|
- !ruby/object:Gem::Dependency
|
95
85
|
name: debugger
|
96
86
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
87
|
requirements:
|
99
|
-
- -
|
88
|
+
- - '>='
|
100
89
|
- !ruby/object:Gem::Version
|
101
90
|
version: '0'
|
102
91
|
type: :development
|
103
92
|
prerelease: false
|
104
93
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
94
|
requirements:
|
107
|
-
- -
|
95
|
+
- - '>='
|
108
96
|
- !ruby/object:Gem::Version
|
109
97
|
version: '0'
|
110
98
|
- !ruby/object:Gem::Dependency
|
111
99
|
name: mixpanel
|
112
100
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
101
|
requirements:
|
115
|
-
- -
|
102
|
+
- - '>='
|
116
103
|
- !ruby/object:Gem::Version
|
117
104
|
version: '0'
|
118
105
|
type: :runtime
|
119
106
|
prerelease: false
|
120
107
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
108
|
requirements:
|
123
|
-
- -
|
109
|
+
- - '>='
|
124
110
|
- !ruby/object:Gem::Version
|
125
111
|
version: '0'
|
126
112
|
description: Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.
|
127
113
|
email:
|
128
114
|
- wouter@springest.com
|
115
|
+
- markmulder@gmail.com
|
129
116
|
executables: []
|
130
117
|
extensions: []
|
131
118
|
extra_rdoc_files: []
|
@@ -172,7 +159,6 @@ files:
|
|
172
159
|
- example/config/initializers/backtrace_silencers.rb
|
173
160
|
- example/config/initializers/inflections.rb
|
174
161
|
- example/config/initializers/mime_types.rb
|
175
|
-
- example/config/initializers/mixpanel_middleware.rb
|
176
162
|
- example/config/initializers/secret_token.rb
|
177
163
|
- example/config/initializers/session_store.rb
|
178
164
|
- example/config/initializers/wrap_parameters.rb
|
@@ -189,7 +175,6 @@ files:
|
|
189
175
|
- example/public/422.html
|
190
176
|
- example/public/500.html
|
191
177
|
- example/public/favicon.ico
|
192
|
-
- example/public/index.html
|
193
178
|
- example/public/robots.txt
|
194
179
|
- example/script/rails
|
195
180
|
- example/test/fixtures/.gitkeep
|
@@ -220,33 +205,26 @@ files:
|
|
220
205
|
homepage: https://github.com/Springest/ab_panel
|
221
206
|
licenses:
|
222
207
|
- MIT
|
208
|
+
metadata: {}
|
223
209
|
post_install_message:
|
224
210
|
rdoc_options: []
|
225
211
|
require_paths:
|
226
212
|
- lib
|
227
213
|
required_ruby_version: !ruby/object:Gem::Requirement
|
228
|
-
none: false
|
229
214
|
requirements:
|
230
|
-
- -
|
215
|
+
- - '>='
|
231
216
|
- !ruby/object:Gem::Version
|
232
217
|
version: '0'
|
233
|
-
segments:
|
234
|
-
- 0
|
235
|
-
hash: 4086507119517691462
|
236
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
|
-
none: false
|
238
219
|
requirements:
|
239
|
-
- -
|
220
|
+
- - '>='
|
240
221
|
- !ruby/object:Gem::Version
|
241
222
|
version: '0'
|
242
|
-
segments:
|
243
|
-
- 0
|
244
|
-
hash: 4086507119517691462
|
245
223
|
requirements: []
|
246
224
|
rubyforge_project:
|
247
|
-
rubygems_version:
|
225
|
+
rubygems_version: 2.0.3
|
248
226
|
signing_key:
|
249
|
-
specification_version:
|
227
|
+
specification_version: 4
|
250
228
|
summary: Run A/B test experiments on your Rails 3+ site using Mixpanel as a backend.
|
251
229
|
test_files:
|
252
230
|
- example/.gitignore
|
@@ -284,7 +262,6 @@ test_files:
|
|
284
262
|
- example/config/initializers/backtrace_silencers.rb
|
285
263
|
- example/config/initializers/inflections.rb
|
286
264
|
- example/config/initializers/mime_types.rb
|
287
|
-
- example/config/initializers/mixpanel_middleware.rb
|
288
265
|
- example/config/initializers/secret_token.rb
|
289
266
|
- example/config/initializers/session_store.rb
|
290
267
|
- example/config/initializers/wrap_parameters.rb
|
@@ -301,7 +278,6 @@ test_files:
|
|
301
278
|
- example/public/422.html
|
302
279
|
- example/public/500.html
|
303
280
|
- example/public/favicon.ico
|
304
|
-
- example/public/index.html
|
305
281
|
- example/public/robots.txt
|
306
282
|
- example/script/rails
|
307
283
|
- example/test/fixtures/.gitkeep
|
data/example/public/index.html
DELETED
@@ -1,241 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Ruby on Rails: Welcome aboard</title>
|
5
|
-
<style type="text/css" media="screen">
|
6
|
-
body {
|
7
|
-
margin: 0;
|
8
|
-
margin-bottom: 25px;
|
9
|
-
padding: 0;
|
10
|
-
background-color: #f0f0f0;
|
11
|
-
font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
|
12
|
-
font-size: 13px;
|
13
|
-
color: #333;
|
14
|
-
}
|
15
|
-
|
16
|
-
h1 {
|
17
|
-
font-size: 28px;
|
18
|
-
color: #000;
|
19
|
-
}
|
20
|
-
|
21
|
-
a {color: #03c}
|
22
|
-
a:hover {
|
23
|
-
background-color: #03c;
|
24
|
-
color: white;
|
25
|
-
text-decoration: none;
|
26
|
-
}
|
27
|
-
|
28
|
-
|
29
|
-
#page {
|
30
|
-
background-color: #f0f0f0;
|
31
|
-
width: 750px;
|
32
|
-
margin: 0;
|
33
|
-
margin-left: auto;
|
34
|
-
margin-right: auto;
|
35
|
-
}
|
36
|
-
|
37
|
-
#content {
|
38
|
-
float: left;
|
39
|
-
background-color: white;
|
40
|
-
border: 3px solid #aaa;
|
41
|
-
border-top: none;
|
42
|
-
padding: 25px;
|
43
|
-
width: 500px;
|
44
|
-
}
|
45
|
-
|
46
|
-
#sidebar {
|
47
|
-
float: right;
|
48
|
-
width: 175px;
|
49
|
-
}
|
50
|
-
|
51
|
-
#footer {
|
52
|
-
clear: both;
|
53
|
-
}
|
54
|
-
|
55
|
-
#header, #about, #getting-started {
|
56
|
-
padding-left: 75px;
|
57
|
-
padding-right: 30px;
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
#header {
|
62
|
-
background-image: url("assets/rails.png");
|
63
|
-
background-repeat: no-repeat;
|
64
|
-
background-position: top left;
|
65
|
-
height: 64px;
|
66
|
-
}
|
67
|
-
#header h1, #header h2 {margin: 0}
|
68
|
-
#header h2 {
|
69
|
-
color: #888;
|
70
|
-
font-weight: normal;
|
71
|
-
font-size: 16px;
|
72
|
-
}
|
73
|
-
|
74
|
-
|
75
|
-
#about h3 {
|
76
|
-
margin: 0;
|
77
|
-
margin-bottom: 10px;
|
78
|
-
font-size: 14px;
|
79
|
-
}
|
80
|
-
|
81
|
-
#about-content {
|
82
|
-
background-color: #ffd;
|
83
|
-
border: 1px solid #fc0;
|
84
|
-
margin-left: -55px;
|
85
|
-
margin-right: -10px;
|
86
|
-
}
|
87
|
-
#about-content table {
|
88
|
-
margin-top: 10px;
|
89
|
-
margin-bottom: 10px;
|
90
|
-
font-size: 11px;
|
91
|
-
border-collapse: collapse;
|
92
|
-
}
|
93
|
-
#about-content td {
|
94
|
-
padding: 10px;
|
95
|
-
padding-top: 3px;
|
96
|
-
padding-bottom: 3px;
|
97
|
-
}
|
98
|
-
#about-content td.name {color: #555}
|
99
|
-
#about-content td.value {color: #000}
|
100
|
-
|
101
|
-
#about-content ul {
|
102
|
-
padding: 0;
|
103
|
-
list-style-type: none;
|
104
|
-
}
|
105
|
-
|
106
|
-
#about-content.failure {
|
107
|
-
background-color: #fcc;
|
108
|
-
border: 1px solid #f00;
|
109
|
-
}
|
110
|
-
#about-content.failure p {
|
111
|
-
margin: 0;
|
112
|
-
padding: 10px;
|
113
|
-
}
|
114
|
-
|
115
|
-
|
116
|
-
#getting-started {
|
117
|
-
border-top: 1px solid #ccc;
|
118
|
-
margin-top: 25px;
|
119
|
-
padding-top: 15px;
|
120
|
-
}
|
121
|
-
#getting-started h1 {
|
122
|
-
margin: 0;
|
123
|
-
font-size: 20px;
|
124
|
-
}
|
125
|
-
#getting-started h2 {
|
126
|
-
margin: 0;
|
127
|
-
font-size: 14px;
|
128
|
-
font-weight: normal;
|
129
|
-
color: #333;
|
130
|
-
margin-bottom: 25px;
|
131
|
-
}
|
132
|
-
#getting-started ol {
|
133
|
-
margin-left: 0;
|
134
|
-
padding-left: 0;
|
135
|
-
}
|
136
|
-
#getting-started li {
|
137
|
-
font-size: 18px;
|
138
|
-
color: #888;
|
139
|
-
margin-bottom: 25px;
|
140
|
-
}
|
141
|
-
#getting-started li h2 {
|
142
|
-
margin: 0;
|
143
|
-
font-weight: normal;
|
144
|
-
font-size: 18px;
|
145
|
-
color: #333;
|
146
|
-
}
|
147
|
-
#getting-started li p {
|
148
|
-
color: #555;
|
149
|
-
font-size: 13px;
|
150
|
-
}
|
151
|
-
|
152
|
-
|
153
|
-
#sidebar ul {
|
154
|
-
margin-left: 0;
|
155
|
-
padding-left: 0;
|
156
|
-
}
|
157
|
-
#sidebar ul h3 {
|
158
|
-
margin-top: 25px;
|
159
|
-
font-size: 16px;
|
160
|
-
padding-bottom: 10px;
|
161
|
-
border-bottom: 1px solid #ccc;
|
162
|
-
}
|
163
|
-
#sidebar li {
|
164
|
-
list-style-type: none;
|
165
|
-
}
|
166
|
-
#sidebar ul.links li {
|
167
|
-
margin-bottom: 5px;
|
168
|
-
}
|
169
|
-
|
170
|
-
.filename {
|
171
|
-
font-style: italic;
|
172
|
-
}
|
173
|
-
</style>
|
174
|
-
<script type="text/javascript">
|
175
|
-
function about() {
|
176
|
-
info = document.getElementById('about-content');
|
177
|
-
if (window.XMLHttpRequest)
|
178
|
-
{ xhr = new XMLHttpRequest(); }
|
179
|
-
else
|
180
|
-
{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
|
181
|
-
xhr.open("GET","rails/info/properties",false);
|
182
|
-
xhr.send("");
|
183
|
-
info.innerHTML = xhr.responseText;
|
184
|
-
info.style.display = 'block'
|
185
|
-
}
|
186
|
-
</script>
|
187
|
-
</head>
|
188
|
-
<body>
|
189
|
-
<div id="page">
|
190
|
-
<div id="sidebar">
|
191
|
-
<ul id="sidebar-items">
|
192
|
-
<li>
|
193
|
-
<h3>Browse the documentation</h3>
|
194
|
-
<ul class="links">
|
195
|
-
<li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
|
196
|
-
<li><a href="http://api.rubyonrails.org/">Rails API</a></li>
|
197
|
-
<li><a href="http://www.ruby-doc.org/core/">Ruby core</a></li>
|
198
|
-
<li><a href="http://www.ruby-doc.org/stdlib/">Ruby standard library</a></li>
|
199
|
-
</ul>
|
200
|
-
</li>
|
201
|
-
</ul>
|
202
|
-
</div>
|
203
|
-
|
204
|
-
<div id="content">
|
205
|
-
<div id="header">
|
206
|
-
<h1>Welcome aboard</h1>
|
207
|
-
<h2>You’re riding Ruby on Rails!</h2>
|
208
|
-
</div>
|
209
|
-
|
210
|
-
<div id="about">
|
211
|
-
<h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3>
|
212
|
-
<div id="about-content" style="display: none"></div>
|
213
|
-
</div>
|
214
|
-
|
215
|
-
<div id="getting-started">
|
216
|
-
<h1>Getting started</h1>
|
217
|
-
<h2>Here’s how to get rolling:</h2>
|
218
|
-
|
219
|
-
<ol>
|
220
|
-
<li>
|
221
|
-
<h2>Use <code>rails generate</code> to create your models and controllers</h2>
|
222
|
-
<p>To see all available options, run it without parameters.</p>
|
223
|
-
</li>
|
224
|
-
|
225
|
-
<li>
|
226
|
-
<h2>Set up a default route and remove <span class="filename">public/index.html</span></h2>
|
227
|
-
<p>Routes are set up in <span class="filename">config/routes.rb</span>.</p>
|
228
|
-
</li>
|
229
|
-
|
230
|
-
<li>
|
231
|
-
<h2>Create your database</h2>
|
232
|
-
<p>Run <code>rake db:create</code> to create your database. If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p>
|
233
|
-
</li>
|
234
|
-
</ol>
|
235
|
-
</div>
|
236
|
-
</div>
|
237
|
-
|
238
|
-
<div id="footer"> </div>
|
239
|
-
</div>
|
240
|
-
</body>
|
241
|
-
</html>
|