vanity 2.2.8 → 2.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +104 -18
- data/gemfiles/rails32.gemfile.lock +1 -1
- data/gemfiles/rails41.gemfile.lock +1 -1
- data/gemfiles/rails42.gemfile.lock +1 -1
- data/gemfiles/rails42_protected_attributes.gemfile.lock +1 -1
- data/gemfiles/rails5.gemfile.lock +1 -1
- data/lib/generators/templates/add_unique_indexes_migration.rb +28 -0
- data/lib/generators/templates/vanity_migration.rb +4 -2
- data/lib/generators/vanity/add_unique_indexes_generator.rb +15 -0
- data/lib/vanity/adapters/active_record_adapter.rb +14 -4
- data/lib/vanity/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca984620557d326a44e57c76e179701e43c784aa
|
4
|
+
data.tar.gz: 3a27cad8226fbdf3e56709291b1ed2afc1793acd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e3a77b2540e8726b77bc6f5ec80226f39b7f499abd271d2e5bc20c51131998472e0dffa0879cdf799e1a4de7e7b6cc052e1ea2e87b85fc09bb584df21e8293c
|
7
|
+
data.tar.gz: 761fb69735eb0b02e8267a24243bb7cf923ccd8880a14ed691ae55f207aa73c4bed6e5c2566e6179aa264c6defacf519462db3c8106830e5a1432f53607d590c
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
== Unreleased
|
2
2
|
|
3
|
+
== 2.2.9 (2018-02-03)
|
4
|
+
|
5
|
+
* Fix race condition using the activerecord adapater when vanity creates experiments or rows in the conversions table (@fcheung)
|
6
|
+
|
3
7
|
== 2.2.8 (2017-09-26)
|
4
8
|
* Rails 5.1 compatibility (#326, #327, #330, @sebjacobs, @bensheldon, @terracatta)
|
5
9
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -9,13 +9,34 @@ Vanity is an A/B testing framework for Rails that is datastore agnostic.
|
|
9
9
|
|
10
10
|
[![Dashboard](doc/images/sidebar_test.png)](http://github.com/assaf/vanity)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
<!-- toc -->
|
13
|
+
|
14
|
+
- [Installation](#installation)
|
15
|
+
- [Setup](#setup)
|
16
|
+
* [Datastore](#datastore)
|
17
|
+
+ [Redis Setup](#redis-setup)
|
18
|
+
+ [MongoDB Setup](#mongodb-setup)
|
19
|
+
+ [SQL Database Setup](#sql-database-setup)
|
20
|
+
+ [Forking servers and reconnecting](#forking-servers-and-reconnecting)
|
21
|
+
* [Initialization](#initialization)
|
22
|
+
* [User identification](#user-identification)
|
23
|
+
+ [Rails](#rails)
|
24
|
+
+ [Other](#other)
|
25
|
+
* [Define a A/B test](#define-a-ab-test)
|
26
|
+
* [Present the different options to your users](#present-the-different-options-to-your-users)
|
27
|
+
* [Measure conversion](#measure-conversion)
|
28
|
+
* [Check the report](#check-the-report)
|
29
|
+
+ [Rails report dashboard](#rails-report-dashboard)
|
30
|
+
- [Registering participants with Javascript](#registering-participants-with-javascript)
|
31
|
+
- [Compatibility](#compatibility)
|
32
|
+
- [Testing](#testing)
|
33
|
+
- [Updating documentation](#updating-documentation)
|
34
|
+
- [Contributing](#contributing)
|
35
|
+
- [Credits/License](#creditslicense)
|
36
|
+
|
37
|
+
<!-- tocstop -->
|
38
|
+
|
39
|
+
## Installation
|
19
40
|
|
20
41
|
Add to your Gemfile:
|
21
42
|
|
@@ -26,14 +47,16 @@ gem "vanity"
|
|
26
47
|
(For support for older versions of Rails and Ruby 1.8, please see the [1.9.x
|
27
48
|
branch](https://github.com/assaf/vanity/tree/1-9-stable).)
|
28
49
|
|
29
|
-
|
50
|
+
## Setup
|
51
|
+
|
52
|
+
### Datastore
|
30
53
|
|
31
54
|
Choose a datastore that best fits your needs and preferences for storing
|
32
55
|
experiment results. Choose one of: Redis, MongoDB or an SQL database. While
|
33
56
|
Redis is usually faster, it may add additional complexity to your stack.
|
34
57
|
Datastores should be configured using a `config/vanity.yml`.
|
35
58
|
|
36
|
-
|
59
|
+
#### Redis Setup
|
37
60
|
|
38
61
|
Add to your Gemfile:
|
39
62
|
|
@@ -73,7 +96,7 @@ Vanity.connect!(
|
|
73
96
|
)
|
74
97
|
```
|
75
98
|
|
76
|
-
|
99
|
+
#### MongoDB Setup
|
77
100
|
|
78
101
|
Add to your Gemfile:
|
79
102
|
|
@@ -94,7 +117,7 @@ production:
|
|
94
117
|
database: analytics
|
95
118
|
```
|
96
119
|
|
97
|
-
|
120
|
+
#### SQL Database Setup
|
98
121
|
|
99
122
|
Vanity supports multiple SQL stores (like MySQL, MariaDB, Postgres, Sqlite,
|
100
123
|
etc.) using ActiveRecord, which is built into Rails. If you're using
|
@@ -133,7 +156,7 @@ $ rails generate vanity
|
|
133
156
|
$ rake db:migrate
|
134
157
|
```
|
135
158
|
|
136
|
-
|
159
|
+
#### Forking servers and reconnecting
|
137
160
|
|
138
161
|
If you're using a forking server (like Passenger or Unicorn), you should
|
139
162
|
reconnect after a new worker is created:
|
@@ -165,7 +188,25 @@ Vanity.connect!(
|
|
165
188
|
)
|
166
189
|
```
|
167
190
|
|
168
|
-
|
191
|
+
### Initialization
|
192
|
+
|
193
|
+
If you're using Rails, this is done automagically. Otherwise, some manual setup is required, for example on an app's booting:
|
194
|
+
|
195
|
+
```
|
196
|
+
$redis = Redis.new # or from elsewhere
|
197
|
+
Vanity.configure do |config|
|
198
|
+
# ... any config
|
199
|
+
end
|
200
|
+
Vanity.connect!(
|
201
|
+
adapter: :redis,
|
202
|
+
redis: $redis
|
203
|
+
)
|
204
|
+
Vanity.load!
|
205
|
+
```
|
206
|
+
|
207
|
+
### User identification
|
208
|
+
|
209
|
+
#### Rails
|
169
210
|
|
170
211
|
Turn Vanity on, and pass a reference to a method that identifies a user. For
|
171
212
|
example:
|
@@ -179,7 +220,28 @@ end
|
|
179
220
|
For more information, please see the [identity
|
180
221
|
documentation](http://vanity.labnotes.org/identity.html).
|
181
222
|
|
182
|
-
|
223
|
+
#### Other
|
224
|
+
|
225
|
+
Vanity pulls the identity from a "context" object that responds to `vanity_identity`, so we need to define a `Vanity.context` (this is how the [ActionMailer integration](https://github.com/assaf/vanity/blob/master/lib/vanity/frameworks/rails.rb#L107-L133) works):
|
226
|
+
|
227
|
+
```
|
228
|
+
class AVanityContext
|
229
|
+
def vanity_identity
|
230
|
+
"123"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
Vanity.context = AVanityContext.new() # Any object that responds to `#vanity_identity`
|
235
|
+
```
|
236
|
+
|
237
|
+
If you're using plain ruby objects, you could also alias something in your identity model to respond similarly and then set that as the vanity context:
|
238
|
+
```
|
239
|
+
class User
|
240
|
+
alias_method :vanity_identity, :id
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
### Define a A/B test
|
183
245
|
|
184
246
|
This experiment goes in the file `experiments/price_options.rb`:
|
185
247
|
|
@@ -200,15 +262,25 @@ metric "Signup (Activation)" do
|
|
200
262
|
end
|
201
263
|
```
|
202
264
|
|
203
|
-
###
|
265
|
+
### Present the different options to your users
|
266
|
+
|
267
|
+
In Rails' templates, this is straightforward:
|
204
268
|
|
205
269
|
```erb
|
206
270
|
<h2>Get started for only $<%= ab_test :price_options %> a month!</h2>
|
207
271
|
```
|
208
272
|
|
209
|
-
|
273
|
+
Outside of templates:
|
210
274
|
|
211
|
-
|
275
|
+
```
|
276
|
+
Vanity.ab_test(:invite_subject)
|
277
|
+
```
|
278
|
+
|
279
|
+
### Measure conversion
|
280
|
+
|
281
|
+
Conversions are created via the `Vanity.track!` method. A user should already be added to an experiment, via `ab_test` before this is called - otherwise, the conversion will be tracked, but the user will not be added to the experiment.
|
282
|
+
|
283
|
+
For example, in Rails:
|
212
284
|
|
213
285
|
```ruby
|
214
286
|
class SignupController < ApplicationController
|
@@ -224,12 +296,26 @@ class SignupController < ApplicationController
|
|
224
296
|
end
|
225
297
|
```
|
226
298
|
|
227
|
-
|
299
|
+
Outside of an Rails controller, for example in a Rack handler:
|
300
|
+
|
301
|
+
```
|
302
|
+
identity_object = Identity.new(env['rack.session'])
|
303
|
+
Vanity.track!(:click, {
|
304
|
+
# can be any object that responds to `to_s` with a string
|
305
|
+
# that contains the unique identifier or the string identifier itself
|
306
|
+
:identity=>identity_object,
|
307
|
+
:values=>[1] # optional
|
308
|
+
})
|
309
|
+
```
|
310
|
+
|
311
|
+
### Check the report
|
228
312
|
|
229
313
|
```sh
|
230
314
|
vanity report --output vanity.html
|
231
315
|
```
|
232
316
|
|
317
|
+
#### Rails report dashboard
|
318
|
+
|
233
319
|
To view metrics and experiment results with the dashboard in Rails 3 & Rails
|
234
320
|
4:
|
235
321
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "vanity/adapters/active_record_adapter"
|
2
|
+
|
3
|
+
class AddVanityUniqueIndexes < ActiveRecord::Migration
|
4
|
+
# Helper methods to ensure we're connecting to the right database, see
|
5
|
+
# https://github.com/assaf/vanity/issues/295.
|
6
|
+
|
7
|
+
def connection
|
8
|
+
@connection ||= ActiveRecord::Base.connection
|
9
|
+
end
|
10
|
+
alias_method :default_connection, :connection
|
11
|
+
|
12
|
+
def with_vanity_connection
|
13
|
+
@connection = Vanity::Adapters::ActiveRecordAdapter::VanityRecord.connection
|
14
|
+
yield
|
15
|
+
@connection = default_connection
|
16
|
+
end
|
17
|
+
|
18
|
+
def change
|
19
|
+
with_vanity_connection do
|
20
|
+
remove_index :vanity_experiments, [:experiment_id]
|
21
|
+
add_index :vanity_experiments, [:experiment_id], :unique => true
|
22
|
+
|
23
|
+
remove_index :vanity_conversions, :name => "by_experiment_id_and_alternative", :unique => true
|
24
|
+
add_index :vanity_conversions, [:vanity_experiment_id, :alternative], :name => "by_experiment_id_and_alternative", :unique => true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "vanity/adapters/active_record_adapter"
|
2
|
+
|
1
3
|
class VanityMigration < ActiveRecord::Migration
|
2
4
|
# Helper methods to ensure we're connecting to the right database, see
|
3
5
|
# https://github.com/assaf/vanity/issues/295.
|
@@ -36,14 +38,14 @@ class VanityMigration < ActiveRecord::Migration
|
|
36
38
|
t.datetime :created_at
|
37
39
|
t.datetime :completed_at
|
38
40
|
end
|
39
|
-
add_index :vanity_experiments, [:experiment_id]
|
41
|
+
add_index :vanity_experiments, [:experiment_id], :unique => true
|
40
42
|
|
41
43
|
create_table :vanity_conversions do |t|
|
42
44
|
t.integer :vanity_experiment_id
|
43
45
|
t.integer :alternative
|
44
46
|
t.integer :conversions
|
45
47
|
end
|
46
|
-
add_index :vanity_conversions, [:vanity_experiment_id, :alternative], :name => "by_experiment_id_and_alternative"
|
48
|
+
add_index :vanity_conversions, [:vanity_experiment_id, :alternative], :name => "by_experiment_id_and_alternative", :unique => true
|
47
49
|
|
48
50
|
create_table :vanity_participants do |t|
|
49
51
|
t.string :experiment_id
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class Vanity::AddUniqueIndexesGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
source_root File.expand_path('../../templates', __FILE__)
|
7
|
+
|
8
|
+
def self.next_migration_number(path)
|
9
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_model_file
|
13
|
+
migration_template "add_unique_indexes_migration.rb", "db/migrate/add_vanity_unique_indexes.rb"
|
14
|
+
end
|
15
|
+
end
|
@@ -19,10 +19,20 @@ module Vanity
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.rails_agnostic_find_or_create_by(method, value)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
retried = false
|
23
|
+
begin
|
24
|
+
if respond_to? :find_or_create_by
|
25
|
+
find_or_create_by(method => value)
|
26
|
+
else
|
27
|
+
send :"find_or_create_by_#{method}", value
|
28
|
+
end
|
29
|
+
rescue ActiveRecord::RecordNotUnique
|
30
|
+
if retried
|
31
|
+
raise
|
32
|
+
else
|
33
|
+
retried = true
|
34
|
+
retry
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
data/lib/vanity/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Assaf Arkin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -177,7 +177,9 @@ files:
|
|
177
177
|
- gemfiles/rails42_protected_attributes.gemfile.lock
|
178
178
|
- gemfiles/rails5.gemfile
|
179
179
|
- gemfiles/rails5.gemfile.lock
|
180
|
+
- lib/generators/templates/add_unique_indexes_migration.rb
|
180
181
|
- lib/generators/templates/vanity_migration.rb
|
182
|
+
- lib/generators/vanity/add_unique_indexes_generator.rb
|
181
183
|
- lib/generators/vanity/views_generator.rb
|
182
184
|
- lib/generators/vanity_generator.rb
|
183
185
|
- lib/vanity.rb
|
@@ -290,7 +292,7 @@ metadata: {}
|
|
290
292
|
post_install_message: To get started run vanity --help
|
291
293
|
rdoc_options:
|
292
294
|
- "--title"
|
293
|
-
- Vanity 2.2.
|
295
|
+
- Vanity 2.2.9
|
294
296
|
- "--main"
|
295
297
|
- README.md
|
296
298
|
- "--webcvs"
|