vanity 1.9.0 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -9
- data/CHANGELOG +10 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +2 -3
- data/README.rdoc +38 -12
- data/Rakefile +10 -54
- data/doc/rails.textile +0 -22
- data/gemfiles/rails3.gemfile +0 -1
- data/gemfiles/rails3.gemfile.lock +2 -3
- data/gemfiles/rails31.gemfile +0 -1
- data/gemfiles/rails31.gemfile.lock +2 -3
- data/gemfiles/rails32.gemfile +0 -1
- data/gemfiles/rails32.gemfile.lock +2 -3
- data/gemfiles/rails4.gemfile +0 -1
- data/gemfiles/rails4.gemfile.lock +2 -3
- data/generators/templates/vanity_migration.rb +1 -0
- data/lib/generators/templates/vanity_migration.rb +1 -0
- data/lib/vanity/adapters/abstract_adapter.rb +1 -1
- data/lib/vanity/adapters/active_record_adapter.rb +25 -16
- data/lib/vanity/adapters/redis_adapter.rb +4 -4
- data/lib/vanity/autoconnect.rb +1 -0
- data/lib/vanity/commands/report.rb +6 -2
- data/lib/vanity/experiment/ab_test.rb +2 -1
- data/lib/vanity/frameworks/rails.rb +5 -4
- data/lib/vanity/helpers.rb +11 -3
- data/lib/vanity/metric/base.rb +3 -3
- data/lib/vanity/templates/_report.erb +7 -7
- data/lib/vanity/templates/_vanity.js.erb +1 -1
- data/lib/vanity/version.rb +1 -1
- data/test/adapters/redis_adapter_test.rb +6 -0
- data/test/experiment/ab_test.rb +18 -5
- data/test/helper_test.rb +14 -0
- data/test/metric/active_record_test.rb +1 -0
- data/test/metric/base_test.rb +1 -1
- data/test/passenger_test.rb +1 -1
- data/test/rails_dashboard_test.rb +16 -16
- data/test/test_helper.rb +12 -17
- data/vanity.gemspec +2 -0
- metadata +42 -41
data/.travis.yml
CHANGED
@@ -11,8 +11,7 @@ rvm:
|
|
11
11
|
env:
|
12
12
|
- DB=mongodb
|
13
13
|
- DB=redis
|
14
|
-
- DB=
|
15
|
-
#- DB=postgres
|
14
|
+
- DB=active_record
|
16
15
|
gemfile:
|
17
16
|
- Gemfile
|
18
17
|
- gemfiles/rails3.gemfile
|
@@ -22,8 +21,6 @@ gemfile:
|
|
22
21
|
before_script:
|
23
22
|
- 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc' # skip installing docs for gems
|
24
23
|
- if [[ "`basename $BUNDLE_GEMFILE`" == "Gemfile" ]]; then rvm rubygems 1.8.25; fi # Rubygems 2.0.x fails with Rails 2.3
|
25
|
-
- if [[ "$DB" == "mysql" ]]; then mysql -e 'create database vanity_test;' >/dev/null; fi
|
26
|
-
#- if [[ "$DB" == "pgsql" ]]; then psql -c 'create database vanity_test;' -U postgres >/dev/null; fi
|
27
24
|
matrix:
|
28
25
|
exclude:
|
29
26
|
# Rails 2 is not officially supported on Ruby 1.9.3
|
@@ -34,7 +31,7 @@ matrix:
|
|
34
31
|
env: DB=redis
|
35
32
|
gemfile: Gemfile
|
36
33
|
- rvm: 1.9.3
|
37
|
-
env: DB=
|
34
|
+
env: DB=active_record
|
38
35
|
gemfile: Gemfile
|
39
36
|
# Rails <= 3.2 is not officially supported on Ruby 2.0.0
|
40
37
|
- rvm: 2.0.0
|
@@ -44,7 +41,7 @@ matrix:
|
|
44
41
|
env: DB=redis
|
45
42
|
gemfile: Gemfile
|
46
43
|
- rvm: 2.0.0
|
47
|
-
env: DB=
|
44
|
+
env: DB=active_record
|
48
45
|
gemfile: Gemfile
|
49
46
|
- rvm: 2.0.0
|
50
47
|
env: DB=mongodb
|
@@ -53,7 +50,7 @@ matrix:
|
|
53
50
|
env: DB=redis
|
54
51
|
gemfile: gemfiles/rails3.gemfile
|
55
52
|
- rvm: 2.0.0
|
56
|
-
env: DB=
|
53
|
+
env: DB=active_record
|
57
54
|
gemfile: gemfiles/rails3.gemfile
|
58
55
|
# Rails >=4 officially supports >= Ruby 1.9.3
|
59
56
|
- rvm: 1.8.7
|
@@ -63,7 +60,7 @@ matrix:
|
|
63
60
|
env: DB=redis
|
64
61
|
gemfile: gemfiles/rails4.gemfile
|
65
62
|
- rvm: 1.8.7
|
66
|
-
env: DB=
|
63
|
+
env: DB=active_record
|
67
64
|
gemfile: gemfiles/rails4.gemfile
|
68
65
|
allow_failures:
|
69
66
|
- rvm: ruby-head
|
@@ -74,5 +71,5 @@ matrix:
|
|
74
71
|
env: DB=redis
|
75
72
|
gemfile: gemfiles/rails31.gemfile
|
76
73
|
- rvm: 2.0.0
|
77
|
-
env: DB=
|
74
|
+
env: DB=active_record
|
78
75
|
gemfile: gemfiles/rails31.gemfile
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 1.9.0 (2014-04-20)
|
2
|
+
|
3
|
+
Include db:reset in blacklist for autoconnect. (@phillbaker)
|
4
|
+
Add grace period to Vanity::Metric updated_at (@stangel)
|
5
|
+
Add timestamps to vanity_participants (@inkredabull)
|
6
|
+
Use sqlite3 for all active record adapter tests & updates to test tasks (@phillbaker)
|
7
|
+
Fix ActiveRecord participant retrieval with non-primitive identities. (@phillbaker)
|
8
|
+
Replace instance variables with locals to fix CLI. (@phillbaker)
|
9
|
+
Replace js encoding with server-side call. (@phillbaker)
|
10
|
+
|
1
11
|
== 1.9.0 (2014-01-18)
|
2
12
|
|
3
13
|
Change order of preference for vanity identity, from highest to lowest: URL param, cookie, method call, assignment. (@phillbaker)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
vanity (1.9.
|
4
|
+
vanity (1.9.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -55,7 +55,6 @@ GEM
|
|
55
55
|
metaclass (~> 0.0.1)
|
56
56
|
mongo (1.6.0)
|
57
57
|
bson (= 1.6.0)
|
58
|
-
mysql (2.8.1)
|
59
58
|
passenger (2.2.15)
|
60
59
|
fastthread (>= 1.0.1)
|
61
60
|
rack
|
@@ -97,12 +96,12 @@ DEPENDENCIES
|
|
97
96
|
appraisal (>= 1.0.0.beta2)
|
98
97
|
backports
|
99
98
|
bson_ext
|
99
|
+
bundler (>= 1.0.0)
|
100
100
|
garb
|
101
101
|
integration
|
102
102
|
jekyll
|
103
103
|
mocha
|
104
104
|
mongo
|
105
|
-
mysql
|
106
105
|
passenger (~> 2.0)
|
107
106
|
rack
|
108
107
|
rails (~> 2.3.8)
|
data/README.rdoc
CHANGED
@@ -33,7 +33,7 @@ Add to your Gemfile:
|
|
33
33
|
|
34
34
|
==== Step 1.2
|
35
35
|
|
36
|
-
Choose a datastore that best fits your needs and preferences for storing experiment results. Choose one of: Redis, MongoDB or an SQL database. While Redis is usually faster, it may add additional complexity to your stack.
|
36
|
+
Choose a datastore that best fits your needs and preferences for storing experiment results. Choose one of: Redis, MongoDB or an SQL database. While Redis is usually faster, it may add additional complexity to your stack. Datastores should be configured using a <code>config/vanity.yml</code>.
|
37
37
|
|
38
38
|
===== Redis Setup
|
39
39
|
|
@@ -42,6 +42,8 @@ Add to your Gemfile:
|
|
42
42
|
gem "redis", ">= 2.1"
|
43
43
|
gem "redis-namespace", ">= 1.1.0"
|
44
44
|
|
45
|
+
By default Vanity is configured to use Redis on localhost port 6379 with database 0.
|
46
|
+
|
45
47
|
===== MongoDB Setup
|
46
48
|
|
47
49
|
Add to your Gemfile:
|
@@ -49,12 +51,39 @@ Add to your Gemfile:
|
|
49
51
|
gem "bson_ext"
|
50
52
|
gem "mongo"
|
51
53
|
|
54
|
+
A sample <code>config/vanity.yml</code> might look like:
|
55
|
+
|
56
|
+
development:
|
57
|
+
adapter: mongodb
|
58
|
+
database: analytics
|
59
|
+
test:
|
60
|
+
collecting: false
|
61
|
+
production:
|
62
|
+
adapter: mongodb
|
63
|
+
database: analytics
|
64
|
+
|
65
|
+
|
52
66
|
===== SQL Database Setup
|
53
67
|
|
54
68
|
Vanity supports multiple SQL stores (like MySQL, MariaDB, Postgres, Sqlite, etc.) using ActiveRecord, which is built into Rails. If you're using DataMapper, Sequel or another persistence framework, add to your Gemfile:
|
55
69
|
|
56
70
|
gem "active_record"
|
57
71
|
|
72
|
+
A sample <code>config/vanity.yml</code> might look like:
|
73
|
+
|
74
|
+
development:
|
75
|
+
adapter: active_record
|
76
|
+
active_record_adapter: sqlite3
|
77
|
+
database: db/development.sqlite3
|
78
|
+
test:
|
79
|
+
collecting: false
|
80
|
+
production:
|
81
|
+
adapter: active_record
|
82
|
+
active_record_adapter: mysql
|
83
|
+
database: vanity_test
|
84
|
+
pool: 5
|
85
|
+
timeout: 5000
|
86
|
+
|
58
87
|
If you're going to store data in the database, run the generator and migrations to create the database schema:
|
59
88
|
|
60
89
|
$ rails generate vanity
|
@@ -113,7 +142,7 @@ Conversions are created via the <code>track!</code> method. For example:
|
|
113
142
|
|
114
143
|
To view metrics and experiment results with the dashboard in Rails 3 & Rails 4:
|
115
144
|
|
116
|
-
rails generate controller Vanity
|
145
|
+
rails generate controller --helper=false Vanity
|
117
146
|
|
118
147
|
In <code>config/routes.rb</code>, add:
|
119
148
|
|
@@ -127,15 +156,13 @@ The controller should look like:
|
|
127
156
|
|
128
157
|
== Registering participants with Javascript
|
129
158
|
|
130
|
-
If robots or spiders make up a significant portion of your sites traffic they can affect your conversion rate. Vanity can optionally add participants to the experiments using asynchronous javascript callbacks, which will keep
|
159
|
+
If robots or spiders make up a significant portion of your sites traffic they can affect your conversion rate. Vanity can optionally add participants to the experiments using asynchronous javascript callbacks, which will keep many robots out. For those robots that do execute Javascript and are well-behaved (like Googlebot), Vanity filters out requests based on their user-agent string.
|
160
|
+
|
161
|
+
To set this up simply do the following:
|
131
162
|
|
132
163
|
* Add <code>Vanity.playground.use_js!</code>
|
133
164
|
* Set <code>Vanity.playground.add_participant_path = '/path/to/vanity/action'</code>, this should point to the add_participant path that is added with Vanity::Rails::Dashboard, make sure that this action is accessible by all users (ie does not require authentication).
|
134
|
-
* Add <code><%= vanity_js %></code> to any page that
|
135
|
-
|
136
|
-
=== <b>Update regarding using AJAX registration to avoid robots</b>
|
137
|
-
|
138
|
-
As of January 2014, as reported in {issue 175}[https://github.com/assaf/vanity/issues/175], Googlebot is now executing AJAX requests to the original domain of the page, which includes the current implementation of the JS callback. This means that Googlebot-originating requests may be included in experiments, greatly skewing results. A fix is being worked on, please follow the issue for further updates.
|
165
|
+
* Add <code><%= vanity_js %></code> to any page that XX an ab_test. <code>vanity_js</code> 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 <code>vanity_js</code> to the bottom of your layouts is a good option. Keep in mind that if you call <code>use_js!</code> and don't include <code>vanity_js</code> in your view no participants will be recorded.
|
139
166
|
|
140
167
|
== Compatibility
|
141
168
|
|
@@ -160,11 +187,10 @@ For view tests/specs or integration testing, it's handy to set the outcome of an
|
|
160
187
|
== Contributing
|
161
188
|
|
162
189
|
* Fork the project
|
163
|
-
* Please use a
|
164
|
-
* To set up the test suite run
|
190
|
+
* Please use a feature branch to make your changes, it's easier to test them that way
|
191
|
+
* To set up the test suite run `bundle`, then run `appraisal install` to prepare the test suite to run against multiple versions of Rails
|
165
192
|
* Fix, patch, enhance, document, improve, sprinkle pixie dust
|
166
|
-
*
|
167
|
-
* Tests. Please. Run rake test, of if you can, rake test:all
|
193
|
+
* Tests. Please. Run `appraisal rake test`, of if you can, `rake test:all`. (This project uses Travis CI where the test suite is run against multiple versions of ruby, rails and backends.)
|
168
194
|
* Send a pull request on GitHub
|
169
195
|
|
170
196
|
|
data/Rakefile
CHANGED
@@ -1,29 +1,5 @@
|
|
1
1
|
require "rake/testtask"
|
2
|
-
|
3
|
-
# -- Building stuff --
|
4
|
-
|
5
|
-
spec = Gem::Specification.load(Dir["*.gemspec"].first)
|
6
|
-
|
7
|
-
desc "Build the Gem"
|
8
|
-
task :build do
|
9
|
-
sh "gem build #{spec.name}.gemspec"
|
10
|
-
end
|
11
|
-
|
12
|
-
desc "Install #{spec.name} locally"
|
13
|
-
task :install=>:build do
|
14
|
-
sudo = "sudo" unless File.writable?( Gem::ConfigMap[:bindir])
|
15
|
-
sh "#{sudo} gem install #{spec.name}-#{spec.version}.gem"
|
16
|
-
end
|
17
|
-
|
18
|
-
desc "Push new release to gemcutter and git tag"
|
19
|
-
task :push=>["build"] do
|
20
|
-
sh "git push"
|
21
|
-
puts "Tagging version #{spec.version} .."
|
22
|
-
sh "git tag v#{spec.version}"
|
23
|
-
sh "git push --tag"
|
24
|
-
puts "Building and pushing gem .."
|
25
|
-
sh "gem push #{spec.name}-#{spec.version}.gem"
|
26
|
-
end
|
2
|
+
require "bundler/gem_tasks"
|
27
3
|
|
28
4
|
|
29
5
|
# -- Testing stuff --
|
@@ -70,7 +46,7 @@ task "test:setup" do
|
|
70
46
|
end
|
71
47
|
|
72
48
|
# These are all the adapters we're going to test with.
|
73
|
-
ADAPTERS = %w{redis mongodb
|
49
|
+
ADAPTERS = %w{redis mongodb active_record}
|
74
50
|
|
75
51
|
desc "Test using different back-ends"
|
76
52
|
task "test:adapters", :adapter do |t, args|
|
@@ -80,7 +56,7 @@ task "test:adapters", :adapter do |t, args|
|
|
80
56
|
adapters = args.adapter ? [args.adapter] : ADAPTERS
|
81
57
|
adapters.each do |adapter|
|
82
58
|
puts "** Testing #{adapter} adapter"
|
83
|
-
sh "
|
59
|
+
sh "bundle exec appraisal rake test DB=#{adapter} #{'--trace' if Rake.application.options.trace}"
|
84
60
|
end
|
85
61
|
rescue LoadError
|
86
62
|
warn "The appraisal gem must be available"
|
@@ -107,40 +83,20 @@ end
|
|
107
83
|
task(:clobber) { rm_rf "tmp" }
|
108
84
|
|
109
85
|
|
110
|
-
# -- Documenting stuff --
|
111
|
-
|
112
|
-
begin
|
113
|
-
require "yard"
|
114
|
-
YARD::Rake::YardocTask.new(:yardoc) do |task|
|
115
|
-
task.files = FileList["lib/**/*.rb"].exclude("lib/vanity/backport.rb")
|
116
|
-
task.options = "--output", "html/api", "--title", "Vanity #{spec.version}", "--main", "README.rdoc", "--files", "CHANGELOG"
|
117
|
-
end
|
118
|
-
rescue LoadError
|
119
|
-
end
|
86
|
+
# -- Documenting stuff -- #TODO make sure works under 1.9/2.0
|
120
87
|
|
121
88
|
desc "Jekyll generates the main documentation (sans API)"
|
122
89
|
task(:jekyll) { sh "jekyll", "doc", "html" }
|
123
|
-
file "html/vanity.pdf"=>:jekyll do |t|
|
124
|
-
pages = %w{index metrics ab_testing rails email identity configuring contributing}.map{ |p| "html/#{p}.html" }
|
125
|
-
args = %w{--disable-javascript --outline --title Vanity --header-html doc/_layouts/_header.html --print-media-type}
|
126
|
-
args.concat %w{--margin-left 20 --margin-right 20 --margin-top 20 --margin-bottom 20 --header-spacing 5}
|
127
|
-
args.concat pages << t.name
|
128
|
-
sh "wkhtmltopdf", *args
|
129
|
-
end
|
130
90
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
end
|
136
|
-
desc "Create documentation in docs directory (including API)"
|
137
|
-
task :docs=>[:jekyll, :yardoc, "html/vanity-api.zip", "html/vanity.pdf"]
|
91
|
+
desc "Create documentation in docs directory"
|
92
|
+
task :docs=>[:jekyll]
|
93
|
+
|
138
94
|
desc "Remove temporary files and directories"
|
139
|
-
task(:clobber) { rm_rf "html"
|
95
|
+
task(:clobber) { rm_rf "html" }
|
140
96
|
|
141
|
-
desc "Publish documentation to vanity.labnotes.org"
|
97
|
+
desc "Publish documentation to vanity.labnotes.org via Github Pages on gh-pages git branch"
|
142
98
|
task :publish=>[:clobber, :docs] do
|
143
|
-
|
99
|
+
# TODO
|
144
100
|
end
|
145
101
|
|
146
102
|
|
data/doc/rails.textile
CHANGED
@@ -7,7 +7,6 @@ title: Using with Rails
|
|
7
7
|
# "Installing Vanity":#install
|
8
8
|
# "Configuring Vanity":#config
|
9
9
|
# "Test Environment":#test
|
10
|
-
# "Dashboard":#dashboard
|
11
10
|
# "Unicorn and Forking Servers":#fork
|
12
11
|
</div>
|
13
12
|
|
@@ -78,27 +77,6 @@ h4. Enabling/disable collection
|
|
78
77
|
When collection is off, Vanity doesn't connect to the database server, so there's no need to set a database configuration for these environments.
|
79
78
|
|
80
79
|
|
81
|
-
h3(#dashboard). Dashboard
|
82
|
-
|
83
|
-
Start by adding a new resource in @config/routes.rb@:
|
84
|
-
|
85
|
-
<pre>
|
86
|
-
map.vanity "/vanity/:action/:id", :controller=>:vanity
|
87
|
-
</pre>
|
88
|
-
|
89
|
-
Create a new controller for Vanity:
|
90
|
-
|
91
|
-
<pre>
|
92
|
-
class VanityController < ApplicationController
|
93
|
-
include Vanity::Rails::Dashboard
|
94
|
-
end
|
95
|
-
</pre>
|
96
|
-
|
97
|
-
Now open your browser to "http://localhost:3000/vanity":http://localhost:3000/vanity.
|
98
|
-
|
99
|
-
The Dashboard renders complete HTML pages with CSS and all necessary JavaScript libraries. Thankfully, HTML is forgiving enough that it will render correctly even with your existing application layout. You can decide to keep your layout, or tell the controller to set @layout false@.
|
100
|
-
|
101
|
-
|
102
80
|
h3(#fork). Unicorn and Forking Servers
|
103
81
|
|
104
82
|
Unicorn forks the master process to create worker processes efficiently. Since the master processes opens a connection to the database, all workers end up sharing that connection, resulting in ugly contention issues.
|
data/gemfiles/rails3.gemfile
CHANGED
@@ -7,7 +7,7 @@ GIT
|
|
7
7
|
PATH
|
8
8
|
remote: ..
|
9
9
|
specs:
|
10
|
-
vanity (1.9.
|
10
|
+
vanity (1.9.1)
|
11
11
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
@@ -90,7 +90,6 @@ GEM
|
|
90
90
|
metaclass (~> 0.0.1)
|
91
91
|
mongo (1.6.0)
|
92
92
|
bson (= 1.6.0)
|
93
|
-
mysql (2.8.1)
|
94
93
|
passenger (3.0.11)
|
95
94
|
daemon_controller (>= 0.2.5)
|
96
95
|
fastthread (>= 1.0.1)
|
@@ -151,13 +150,13 @@ DEPENDENCIES
|
|
151
150
|
appraisal (>= 1.0.0.beta2)
|
152
151
|
backports
|
153
152
|
bson_ext
|
153
|
+
bundler (>= 1.0.0)
|
154
154
|
fastthread!
|
155
155
|
garb
|
156
156
|
integration
|
157
157
|
jekyll
|
158
158
|
mocha
|
159
159
|
mongo
|
160
|
-
mysql
|
161
160
|
passenger (~> 3.0)
|
162
161
|
rack
|
163
162
|
rails (= 3.0.11)
|
data/gemfiles/rails31.gemfile
CHANGED
@@ -7,7 +7,7 @@ GIT
|
|
7
7
|
PATH
|
8
8
|
remote: ..
|
9
9
|
specs:
|
10
|
-
vanity (1.9.
|
10
|
+
vanity (1.9.1)
|
11
11
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
@@ -90,7 +90,6 @@ GEM
|
|
90
90
|
mongo (1.6.0)
|
91
91
|
bson (= 1.6.0)
|
92
92
|
multi_json (1.1.0)
|
93
|
-
mysql (2.8.1)
|
94
93
|
passenger (3.0.11)
|
95
94
|
daemon_controller (>= 0.2.5)
|
96
95
|
fastthread (>= 1.0.1)
|
@@ -160,13 +159,13 @@ DEPENDENCIES
|
|
160
159
|
appraisal (>= 1.0.0.beta2)
|
161
160
|
backports
|
162
161
|
bson_ext
|
162
|
+
bundler (>= 1.0.0)
|
163
163
|
fastthread!
|
164
164
|
garb
|
165
165
|
integration
|
166
166
|
jekyll
|
167
167
|
mocha
|
168
168
|
mongo
|
169
|
-
mysql
|
170
169
|
passenger (~> 3.0)
|
171
170
|
rack
|
172
171
|
rails (= 3.1.3)
|
data/gemfiles/rails32.gemfile
CHANGED
@@ -7,7 +7,7 @@ GIT
|
|
7
7
|
PATH
|
8
8
|
remote: ..
|
9
9
|
specs:
|
10
|
-
vanity (1.9.
|
10
|
+
vanity (1.9.1)
|
11
11
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
@@ -91,7 +91,6 @@ GEM
|
|
91
91
|
mongo (1.6.0)
|
92
92
|
bson (= 1.6.0)
|
93
93
|
multi_json (1.1.0)
|
94
|
-
mysql (2.8.1)
|
95
94
|
passenger (3.0.11)
|
96
95
|
daemon_controller (>= 0.2.5)
|
97
96
|
fastthread (>= 1.0.1)
|
@@ -160,13 +159,13 @@ DEPENDENCIES
|
|
160
159
|
appraisal (>= 1.0.0.beta2)
|
161
160
|
backports
|
162
161
|
bson_ext
|
162
|
+
bundler (>= 1.0.0)
|
163
163
|
fastthread!
|
164
164
|
garb
|
165
165
|
integration
|
166
166
|
jekyll
|
167
167
|
mocha
|
168
168
|
mongo
|
169
|
-
mysql
|
170
169
|
passenger (~> 3.0)
|
171
170
|
rack
|
172
171
|
rails (= 3.2.1)
|
data/gemfiles/rails4.gemfile
CHANGED
@@ -7,7 +7,7 @@ GIT
|
|
7
7
|
PATH
|
8
8
|
remote: ..
|
9
9
|
specs:
|
10
|
-
vanity (1.9.
|
10
|
+
vanity (1.9.1)
|
11
11
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
@@ -88,7 +88,6 @@ GEM
|
|
88
88
|
mongo (1.9.2)
|
89
89
|
bson (~> 1.9.2)
|
90
90
|
multi_json (1.8.2)
|
91
|
-
mysql (2.9.1)
|
92
91
|
passenger (3.0.21)
|
93
92
|
daemon_controller (>= 1.0.0)
|
94
93
|
fastthread (>= 1.0.1)
|
@@ -158,13 +157,13 @@ DEPENDENCIES
|
|
158
157
|
appraisal (>= 1.0.0.beta2)
|
159
158
|
backports
|
160
159
|
bson_ext
|
160
|
+
bundler (>= 1.0.0)
|
161
161
|
fastthread!
|
162
162
|
garb
|
163
163
|
integration
|
164
164
|
jekyll
|
165
165
|
mocha
|
166
166
|
mongo
|
167
|
-
mysql
|
168
167
|
passenger (~> 3.0)
|
169
168
|
rack
|
170
169
|
rails (= 4.0.0)
|
@@ -35,6 +35,7 @@ class VanityMigration < ActiveRecord::Migration
|
|
35
35
|
t.integer :shown
|
36
36
|
t.integer :seen
|
37
37
|
t.integer :converted
|
38
|
+
t.timestamps
|
38
39
|
end
|
39
40
|
add_index :vanity_participants, [:experiment_id]
|
40
41
|
add_index :vanity_participants, [:experiment_id, :identity], :name => "by_experiment_id_and_identity"
|
@@ -35,6 +35,7 @@ class VanityMigration < ActiveRecord::Migration
|
|
35
35
|
t.integer :shown
|
36
36
|
t.integer :seen
|
37
37
|
t.integer :converted
|
38
|
+
t.timestamps
|
38
39
|
end
|
39
40
|
add_index :vanity_participants, [:experiment_id]
|
40
41
|
add_index :vanity_participants, [:experiment_id, :identity], :name => "by_experiment_id_and_identity"
|
@@ -4,7 +4,7 @@ module Vanity
|
|
4
4
|
class << self
|
5
5
|
# Creates new connection to underlying datastore and returns suitable
|
6
6
|
# adapter (adapter object extends AbstractAdapter and wraps the
|
7
|
-
# connection). Vanity.
|
7
|
+
# connection). Vanity.playground.establish_connection uses this.
|
8
8
|
#
|
9
9
|
# @since 1.4.0
|
10
10
|
def establish_connection(spec)
|
@@ -34,12 +34,24 @@ module Vanity
|
|
34
34
|
|
35
35
|
# Metric model
|
36
36
|
class VanityMetric < VanityRecord
|
37
|
+
UPDATED_AT_GRACE_PERIOD = 1.minute
|
37
38
|
self.table_name = :vanity_metrics
|
38
39
|
has_many :vanity_metric_values
|
39
40
|
|
40
41
|
def self.retrieve(metric)
|
41
42
|
rails_agnostic_find_or_create_by(:metric_id, metric.to_s)
|
42
43
|
end
|
44
|
+
|
45
|
+
def touch_with_grace_period
|
46
|
+
now = Time.now
|
47
|
+
self.updated_at = now if updated_before_grace_period?(now)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def updated_before_grace_period?(now)
|
53
|
+
now - updated_at >= UPDATED_AT_GRACE_PERIOD
|
54
|
+
end
|
43
55
|
end
|
44
56
|
|
45
57
|
# Metric value
|
@@ -78,24 +90,21 @@ module Vanity
|
|
78
90
|
self.table_name = :vanity_participants
|
79
91
|
attr_accessible :experiment_id, :identity, :seen, :shown, :converted if needs_attr_accessible?
|
80
92
|
|
81
|
-
# Finds the participant by experiment and identity. If
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# update the found participant.
|
93
|
+
# Finds the participant by experiment and identity. If create is true
|
94
|
+
# then it will create the participant if not found. If a hash is
|
95
|
+
# passed then this will be passed to create if creating, or will be
|
96
|
+
# used to update the found participant.
|
86
97
|
def self.retrieve(experiment, identity, create = true, update_with = nil)
|
87
98
|
if record = VanityParticipant.first(:conditions=>{ :experiment_id=>experiment.to_s, :identity=>identity.to_s })
|
88
99
|
record.update_attributes(update_with) if update_with
|
89
100
|
elsif create
|
90
|
-
record = VanityParticipant.create({ :experiment_id=>experiment.to_s, :identity=>identity }.merge(update_with || {}))
|
101
|
+
record = VanityParticipant.create({ :experiment_id=>experiment.to_s, :identity=>identity.to_s }.merge(update_with || {}))
|
91
102
|
end
|
92
103
|
record
|
93
104
|
end
|
94
105
|
end
|
95
106
|
|
96
107
|
def initialize(options)
|
97
|
-
|
98
|
-
|
99
108
|
@options = options.inject({}) { |h,kv| h[kv.first.to_s] = kv.last ; h }
|
100
109
|
if @options["active_record_adapter"] && (@options["active_record_adapter"] != "default")
|
101
110
|
@options["adapter"] = @options["active_record_adapter"]
|
@@ -136,7 +145,7 @@ module Vanity
|
|
136
145
|
record.vanity_metric_values.create(:date => timestamp.to_date.to_s, :index => index, :value => value)
|
137
146
|
end
|
138
147
|
|
139
|
-
record.
|
148
|
+
record.touch_with_grace_period
|
140
149
|
record.save
|
141
150
|
end
|
142
151
|
|
@@ -150,10 +159,10 @@ module Vanity
|
|
150
159
|
group_by = "#{connection.quote_column_name('date')}"
|
151
160
|
|
152
161
|
values = record.vanity_metric_values.all(
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
162
|
+
:select => select,
|
163
|
+
:conditions => conditions,
|
164
|
+
:order => order,
|
165
|
+
:group => group_by
|
157
166
|
)
|
158
167
|
|
159
168
|
dates.map do |date|
|
@@ -211,9 +220,9 @@ module Vanity
|
|
211
220
|
conversions = record.vanity_conversions.sum(:conversions, :conditions => {:alternative => alternative})
|
212
221
|
|
213
222
|
{
|
214
|
-
|
215
|
-
|
216
|
-
|
223
|
+
:participants => participants,
|
224
|
+
:converted => converted,
|
225
|
+
:conversions => conversions
|
217
226
|
}
|
218
227
|
end
|
219
228
|
|
@@ -155,9 +155,9 @@ module Vanity
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def ab_add_participant(experiment, alternative, identity)
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
call_redis_with_failover(experiment, alternative, identity) do
|
159
|
+
@experiments.sadd "#{experiment}:alts:#{alternative}:participants", identity
|
160
|
+
end
|
161
161
|
end
|
162
162
|
|
163
163
|
def ab_seen(experiment, identity, alternative)
|
@@ -177,7 +177,7 @@ module Vanity
|
|
177
177
|
if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
|
178
178
|
return alternative.id
|
179
179
|
end
|
180
|
-
|
180
|
+
end
|
181
181
|
nil
|
182
182
|
end
|
183
183
|
end
|
data/lib/vanity/autoconnect.rb
CHANGED
@@ -15,7 +15,7 @@ module Vanity
|
|
15
15
|
path_or_options[:locals]
|
16
16
|
)
|
17
17
|
else
|
18
|
-
|
18
|
+
render_erb(path_or_options, locals)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -69,7 +69,11 @@ module Vanity
|
|
69
69
|
# Generate an HTML report. Outputs to the named file, or stdout with no
|
70
70
|
# arguments.
|
71
71
|
def report(output = nil)
|
72
|
-
html = render(Vanity.template("report")
|
72
|
+
html = render(Vanity.template("report"),
|
73
|
+
:experiments=>Vanity.playground.experiments,
|
74
|
+
:experiments_persisted=>Vanity.playground.experiments_persisted?,
|
75
|
+
:metrics=>Vanity.playground.metrics
|
76
|
+
)
|
73
77
|
if output
|
74
78
|
File.open output, 'w' do |file|
|
75
79
|
file.write html
|
@@ -460,10 +460,11 @@ module Vanity
|
|
460
460
|
end
|
461
461
|
end
|
462
462
|
|
463
|
-
# Called
|
463
|
+
# Called via a hook by the associated metric.
|
464
464
|
def track!(metric_id, timestamp, count, *args)
|
465
465
|
return unless active?
|
466
466
|
identity = identity() rescue nil
|
467
|
+
identity ||= args.last[:identity] if args.last.is_a?(Hash) && args.last[:identity]
|
467
468
|
if identity
|
468
469
|
return if connection.ab_showing(@id, identity)
|
469
470
|
index = alternative_for(identity)
|
@@ -292,10 +292,11 @@ module Vanity
|
|
292
292
|
# Step 3: Open your browser to http://localhost:3000/vanity
|
293
293
|
module Dashboard
|
294
294
|
def index
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
295
|
+
render :file=>Vanity.template("_report"),:content_type=>Mime::HTML, :locals=>{
|
296
|
+
:experiments=>Vanity.playground.experiments,
|
297
|
+
:experiments_persisted=>Vanity.playground.experiments_persisted?,
|
298
|
+
:metrics=>Vanity.playground.metrics
|
299
|
+
}
|
299
300
|
end
|
300
301
|
|
301
302
|
def participant
|
data/lib/vanity/helpers.rb
CHANGED
@@ -52,13 +52,21 @@ module Vanity
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
# Tracks an action associated with a metric.
|
55
|
+
# Tracks an action associated with a metric. Useful for calling from a
|
56
|
+
# Rack handler. Note that a user should already be added to an experiment
|
57
|
+
# via #ab_test before this is called - otherwise, the conversion will be
|
58
|
+
# tracked, but the user will not be added to the experiment.
|
56
59
|
#
|
57
60
|
# @example
|
58
61
|
# track! :invitation
|
62
|
+
# @example
|
63
|
+
# track! :click, { :identity=>Identity.new(env['rack.session']), :values=>[1] }
|
64
|
+
#
|
65
|
+
# @param count_or_options Defaults to a count of 1. Also accepts a hash
|
66
|
+
# of options passed (eventually) to AbTest#track!.
|
59
67
|
# @since 1.2.0
|
60
|
-
def track!(name,
|
61
|
-
Vanity.playground.track! name,
|
68
|
+
def track!(name, count_or_options = 1)
|
69
|
+
Vanity.playground.track! name, count_or_options
|
62
70
|
end
|
63
71
|
end
|
64
72
|
end
|
data/lib/vanity/metric/base.rb
CHANGED
@@ -152,12 +152,12 @@ module Vanity
|
|
152
152
|
when Numeric
|
153
153
|
values = [args]
|
154
154
|
end
|
155
|
-
|
155
|
+
identity ||= Vanity.context.vanity_identity rescue nil
|
156
156
|
[timestamp || Time.now, identity, values || [1]]
|
157
157
|
end
|
158
158
|
protected :track_args
|
159
159
|
|
160
|
-
# Metric definitions use this to introduce tracking
|
160
|
+
# Metric definitions use this to introduce tracking hooks. The hook is
|
161
161
|
# called with metric identifier, timestamp, count and possibly additional
|
162
162
|
# arguments.
|
163
163
|
#
|
@@ -235,7 +235,7 @@ module Vanity
|
|
235
235
|
|
236
236
|
def call_hooks(timestamp, identity, values)
|
237
237
|
@hooks.each do |hook|
|
238
|
-
hook.call @id, timestamp, values.first || 1
|
238
|
+
hook.call @id, timestamp, values.first || 1, :identity=>identity
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
@@ -14,23 +14,23 @@
|
|
14
14
|
<body>
|
15
15
|
<div class="vanity">
|
16
16
|
<% unless Vanity.playground.collecting? %>
|
17
|
-
<div class="alert">
|
17
|
+
<div class="alert collecting">
|
18
18
|
Vanity is currently not collecting data or metrics. To turn on data collection, set <span style='font-family: courier'>Vanity.playground.collecting = true;</span> in <span style='font-family: courier'>config/environments/[environment].rb</span>.
|
19
19
|
</div>
|
20
20
|
<% end %>
|
21
21
|
|
22
|
-
<% if
|
23
|
-
<% if
|
22
|
+
<% if experiments_persisted %>
|
23
|
+
<% if experiments.present? %>
|
24
24
|
<h2>Experiments</h2>
|
25
|
-
<%= render :file=>Vanity.template("_experiments"), :locals=>{:experiments
|
25
|
+
<%= render :file=>Vanity.template("_experiments"), :locals=>{:experiments=>experiments} %>
|
26
26
|
<% end %>
|
27
27
|
|
28
|
-
<% unless
|
28
|
+
<% unless metrics.empty? %>
|
29
29
|
<h2>Metrics</h2>
|
30
|
-
<%= render :file=>Vanity.template("_metrics"), :locals=>{:metrics
|
30
|
+
<%= render :file=>Vanity.template("_metrics"), :locals=>{:metrics=>metrics, :experiments=>experiments} %>
|
31
31
|
<% end %>
|
32
32
|
<% else %>
|
33
|
-
<div class="alert">
|
33
|
+
<div class="alert persistance">
|
34
34
|
Vanity's cached experiments are out of sync with those on the filesystem and/or those in the datastore. Please restart your server and/or turn on collecting.
|
35
35
|
</div>
|
36
36
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
var httpRequest;
|
2
2
|
<% @_vanity_experiments.each do |name, alternative| %>
|
3
|
-
var params = "e=<%= name %>&a=<%= alternative.id %>&authenticity_token
|
3
|
+
var params = "e=<%= name %>&a=<%= alternative.id %>&authenticity_token=<%= CGI.escape(form_authenticity_token) %>";
|
4
4
|
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
|
5
5
|
httpRequest = new XMLHttpRequest();
|
6
6
|
} else if (window.ActiveXObject) { // IE
|
data/lib/vanity/version.rb
CHANGED
@@ -29,6 +29,12 @@ class RedisAdapterTest < Test::Unit::TestCase
|
|
29
29
|
[redis_adapter, mocked_redis]
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_connect_to_existing_redis
|
33
|
+
mocked_redis = stub("Redis")
|
34
|
+
adapter = Vanity::Adapters.redis_connection(:redis => mocked_redis)
|
35
|
+
assert_equal mocked_redis, adapter.redis
|
36
|
+
end
|
37
|
+
|
32
38
|
def test_graceful_failure_metric_track
|
33
39
|
redis_adapter, mocked_redis = stub_redis
|
34
40
|
mocked_redis.stubs(:incrby).raises(RuntimeError)
|
data/test/experiment/ab_test.rb
CHANGED
@@ -225,18 +225,31 @@ class AbTestTest < ActionController::TestCase
|
|
225
225
|
assert_equal id, experiment(:foobar).playground.connection.ab_assigned(experiment(:foobar).id, "6e98ec")
|
226
226
|
end
|
227
227
|
|
228
|
+
def test_ab_assigned
|
229
|
+
identity = { :a => :b }
|
230
|
+
new_ab_test :foobar do
|
231
|
+
alternatives "foo", "bar"
|
232
|
+
identify { identity }
|
233
|
+
metrics :coolness
|
234
|
+
end
|
235
|
+
assert_equal nil, experiment(:foobar).playground.connection.ab_assigned(experiment(:foobar).id, identity)
|
236
|
+
assert id = experiment(:foobar).choose.id
|
237
|
+
assert_equal id, experiment(:foobar).playground.connection.ab_assigned(experiment(:foobar).id, identity)
|
238
|
+
end
|
239
|
+
|
228
240
|
# -- Unequal probabilities --
|
229
241
|
|
230
242
|
def test_returns_the_same_alternative_consistently_when_using_probabilities
|
231
243
|
new_ab_test :foobar do
|
232
244
|
alternatives "foo", "bar"
|
233
245
|
identify { "6e98ec" }
|
234
|
-
rebalance_frequency
|
246
|
+
rebalance_frequency 10
|
235
247
|
metrics :coolness
|
236
248
|
end
|
237
|
-
|
249
|
+
value = experiment(:foobar).choose.value
|
250
|
+
assert value
|
238
251
|
assert_match /foo|bar/, value
|
239
|
-
|
252
|
+
100.times do
|
240
253
|
assert_equal value, experiment(:foobar).choose.value
|
241
254
|
end
|
242
255
|
end
|
@@ -252,9 +265,9 @@ class AbTestTest < ActionController::TestCase
|
|
252
265
|
altered_alts[0].probability=30
|
253
266
|
altered_alts[1].probability=70
|
254
267
|
experiment(:foobar).set_alternative_probabilities altered_alts
|
255
|
-
alts = Array.new(
|
268
|
+
alts = Array.new(600) { experiment(:foobar).choose.value }
|
256
269
|
assert_equal %w{bar foo}, alts.uniq.sort
|
257
|
-
assert_in_delta alts.select { |a| a == altered_alts[0].value }.size,
|
270
|
+
assert_in_delta alts.select { |a| a == altered_alts[0].value }.size, 200, 60 # this may fail, such is propability
|
258
271
|
end
|
259
272
|
|
260
273
|
# -- Rebalancing probabilities --
|
data/test/helper_test.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
context "Object#track!" do
|
4
|
+
test "identity option sets identity" do
|
5
|
+
metric "Coolness"
|
6
|
+
new_ab_test :foobar do
|
7
|
+
alternatives "foo", "bar"
|
8
|
+
metrics :coolness
|
9
|
+
end
|
10
|
+
track! :coolness, :identity=>'quux', :values=>[2]
|
11
|
+
|
12
|
+
assert_equal 2, experiment(:foobar).alternatives.sum(&:conversions)
|
13
|
+
end
|
14
|
+
end
|
data/test/metric/base_test.rb
CHANGED
@@ -81,7 +81,7 @@ context "Metric tracking" do
|
|
81
81
|
2.times { Vanity.playground.track! :cheers_sec }
|
82
82
|
yawns = Vanity.playground.metric(:yawns_sec).values(today, today).first
|
83
83
|
cheers = Vanity.playground.metric(:cheers_sec).values(today, today).first
|
84
|
-
assert yawns
|
84
|
+
assert yawns == 2 * cheers
|
85
85
|
end
|
86
86
|
|
87
87
|
test "can tell the time" do
|
data/test/passenger_test.rb
CHANGED
@@ -11,7 +11,7 @@ if !defined?(Rails::Railtie) && ActiveRecord::Base.connected?
|
|
11
11
|
@original = Vanity.playground.connection
|
12
12
|
File.unlink "test/myapp/config/vanity.yml" rescue nil
|
13
13
|
File.open("test/myapp/config/vanity.yml", "w") do |io|
|
14
|
-
|
14
|
+
io.write YAML.dump({ "production"=>DATABASE })
|
15
15
|
end
|
16
16
|
@server = PhusionPassenger::SpawnManager.new
|
17
17
|
@server.start
|
@@ -23,31 +23,31 @@ class RailsDashboardTest < ActionController::TestCase
|
|
23
23
|
get :index
|
24
24
|
assert_response :success
|
25
25
|
assert @response.body =~ %r{div class="vanity"}
|
26
|
+
assert @response.body =~ %r{<h2>Experiments</h2>}
|
27
|
+
assert @response.body =~ %r{<h2>Metrics</h2>}
|
26
28
|
end
|
27
29
|
|
28
|
-
def
|
30
|
+
def test_index_not_collecting
|
31
|
+
Vanity.playground.collecting = false
|
29
32
|
get :index
|
30
|
-
|
31
|
-
|
32
|
-
assert experiments.respond_to?(:keys)
|
33
|
-
assert experiments.keys.include?("food")
|
34
|
-
assert experiments.values.first.name == :food
|
33
|
+
assert_response :success
|
34
|
+
assert @response.body =~ %r{<div class="alert collecting">}
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
assert metrics.values.first.name == "sugar_high"
|
43
|
-
end
|
37
|
+
def test_index_not_persisted
|
38
|
+
name = 'Price'
|
39
|
+
id = :price
|
40
|
+
experiment = Vanity::Experiment::AbTest.new(Vanity.playground, id, name)
|
41
|
+
Vanity.playground.experiments[id] = experiment
|
44
42
|
|
45
|
-
def test_assigns_experiments_persisted
|
46
43
|
get :index
|
47
|
-
|
44
|
+
assert_response :success
|
45
|
+
assert @response.body =~ %r{<div class="alert persistance">}
|
46
|
+
|
47
|
+
Vanity.playground.experiments.delete(id)
|
48
48
|
end
|
49
49
|
|
50
|
-
# -- Actions used in non-admin actions --
|
50
|
+
# -- Actions used in non-admin actions, e.g. in JS --
|
51
51
|
|
52
52
|
def test_add_participant
|
53
53
|
xhr :post, :add_participant, :e => "food", :a => 0
|
data/test/test_helper.rb
CHANGED
@@ -56,8 +56,7 @@ module VanityTestHelpers
|
|
56
56
|
DATABASE = {
|
57
57
|
"redis"=>"redis://localhost/15",
|
58
58
|
"mongodb"=>"mongodb://localhost/vanity",
|
59
|
-
"
|
60
|
-
"postgres"=> { "adapter"=>"active_record", "active_record_adapter"=>"postgresql", "database"=>"vanity_test", "username"=>"postgres" },
|
59
|
+
"active_record"=> { "adapter"=>"active_record", "active_record_adapter"=>"sqlite3", "database"=>"vanity_test.sqlite3", "timeout" => 10000, "busy_timeout" => 1000 },
|
61
60
|
"mock"=>"mock:/"
|
62
61
|
}[ENV["DB"]] or raise "No support yet for #{ENV["DB"]}"
|
63
62
|
|
@@ -77,18 +76,11 @@ module VanityTestHelpers
|
|
77
76
|
WebMock.reset!
|
78
77
|
end
|
79
78
|
|
80
|
-
# Call this on teardown. It wipes put the playground and any state held in it
|
81
|
-
# (mostly experiments), resets vanity ID, and clears database of all experiments.
|
82
|
-
def nuke_playground
|
83
|
-
Vanity.playground.connection.flushdb
|
84
|
-
new_playground
|
85
|
-
end
|
86
|
-
|
87
79
|
# Call this if you need a new playground, e.g. to re-define the same experiment,
|
88
80
|
# or reload an experiment (saved by the previous playground).
|
89
81
|
def new_playground
|
90
82
|
Vanity.playground = Vanity::Playground.new(:logger=>$logger, :load_path=>"tmp/experiments")
|
91
|
-
Vanity.playground.establish_connection
|
83
|
+
Vanity.playground.establish_connection(DATABASE)
|
92
84
|
end
|
93
85
|
|
94
86
|
# Defines the specified metrics (one or more names). Returns metric, or array
|
@@ -151,6 +143,9 @@ if defined?(ActiveSupport::TestCase)
|
|
151
143
|
class ActiveSupport::TestCase
|
152
144
|
include WebMock::API
|
153
145
|
include VanityTestHelpers
|
146
|
+
|
147
|
+
self.use_instantiated_fixtures = false if respond_to?(:use_instantiated_fixtures)
|
148
|
+
self.use_transactional_fixtures = false if respond_to?(:use_transactional_fixtures)
|
154
149
|
end
|
155
150
|
end
|
156
151
|
|
@@ -168,17 +163,17 @@ if defined?(ActionController::TestCase)
|
|
168
163
|
end
|
169
164
|
end
|
170
165
|
|
171
|
-
if ENV["DB"] == "
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
ActiveRecord::Base.logger = $logger
|
166
|
+
if ENV["DB"] == "active_record"
|
167
|
+
connection = {}
|
168
|
+
connection[:adapter] = VanityTestHelpers::DATABASE['active_record_adapter']
|
169
|
+
connection[:database] = VanityTestHelpers::DATABASE['database']
|
170
|
+
ActiveRecord::Base.establish_connection(connection)
|
171
|
+
ActiveRecord::Base.logger = $logger
|
177
172
|
|
178
|
-
if ENV["DB"] == "mysql" || ENV["DB"] == "postgres"
|
179
173
|
require "generators/templates/vanity_migration"
|
180
174
|
VanityMigration.down rescue nil
|
181
175
|
VanityMigration.up
|
176
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
182
177
|
end
|
183
178
|
|
184
179
|
# test/spec/mini v3
|
data/vanity.gemspec
CHANGED
metadata
CHANGED
@@ -1,33 +1,41 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanity
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.9.1
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 9
|
9
|
-
- 0
|
10
|
-
version: 1.9.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Assaf Arkin
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2014-04-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.0
|
21
30
|
description: Mirror, mirror on the wall ...
|
22
31
|
email: assaf@labnotes.org
|
23
|
-
executables:
|
32
|
+
executables:
|
24
33
|
- vanity
|
25
34
|
extensions: []
|
26
|
-
|
27
|
-
extra_rdoc_files:
|
35
|
+
extra_rdoc_files:
|
28
36
|
- README.rdoc
|
29
37
|
- CHANGELOG
|
30
|
-
files:
|
38
|
+
files:
|
31
39
|
- .autotest
|
32
40
|
- .gitignore
|
33
41
|
- .travis.yml
|
@@ -149,6 +157,7 @@ files:
|
|
149
157
|
- test/experiments/metrics/signups.rb
|
150
158
|
- test/experiments/metrics/yawns.rb
|
151
159
|
- test/experiments/null_abc.rb
|
160
|
+
- test/helper_test.rb
|
152
161
|
- test/metric/active_record_test.rb
|
153
162
|
- test/metric/base_test.rb
|
154
163
|
- test/metric/google_analytics_test.rb
|
@@ -167,46 +176,37 @@ files:
|
|
167
176
|
- test/test_helper.rb
|
168
177
|
- vanity.gemspec
|
169
178
|
homepage: http://vanity.labnotes.org
|
170
|
-
licenses:
|
179
|
+
licenses:
|
171
180
|
- MIT
|
172
181
|
post_install_message: To get started run vanity --help
|
173
|
-
rdoc_options:
|
182
|
+
rdoc_options:
|
174
183
|
- --title
|
175
|
-
- Vanity 1.9.
|
184
|
+
- Vanity 1.9.1
|
176
185
|
- --main
|
177
186
|
- README.rdoc
|
178
187
|
- --webcvs
|
179
188
|
- http://github.com/assaf/vanity
|
180
|
-
require_paths:
|
189
|
+
require_paths:
|
181
190
|
- lib
|
182
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
183
192
|
none: false
|
184
|
-
requirements:
|
185
|
-
- -
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
hash: 57
|
188
|
-
segments:
|
189
|
-
- 1
|
190
|
-
- 8
|
191
|
-
- 7
|
193
|
+
requirements:
|
194
|
+
- - ! '>='
|
195
|
+
- !ruby/object:Gem::Version
|
192
196
|
version: 1.8.7
|
193
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
198
|
none: false
|
195
|
-
requirements:
|
196
|
-
- -
|
197
|
-
- !ruby/object:Gem::Version
|
198
|
-
|
199
|
-
segments:
|
200
|
-
- 0
|
201
|
-
version: "0"
|
199
|
+
requirements:
|
200
|
+
- - ! '>='
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
202
203
|
requirements: []
|
203
|
-
|
204
204
|
rubyforge_project:
|
205
|
-
rubygems_version: 1.8.
|
205
|
+
rubygems_version: 1.8.23
|
206
206
|
signing_key:
|
207
207
|
specification_version: 3
|
208
208
|
summary: Experience Driven Development framework for Ruby
|
209
|
-
test_files:
|
209
|
+
test_files:
|
210
210
|
- test/adapters/redis_adapter_test.rb
|
211
211
|
- test/autoconnect_test.rb
|
212
212
|
- test/cli_test.rb
|
@@ -242,6 +242,7 @@ test_files:
|
|
242
242
|
- test/experiments/metrics/signups.rb
|
243
243
|
- test/experiments/metrics/yawns.rb
|
244
244
|
- test/experiments/null_abc.rb
|
245
|
+
- test/helper_test.rb
|
245
246
|
- test/metric/active_record_test.rb
|
246
247
|
- test/metric/base_test.rb
|
247
248
|
- test/metric/google_analytics_test.rb
|