vanity 1.8.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,23 +1,65 @@
1
1
  language: ruby
2
2
  bundler_args: --without development
3
- script: 'rake appraisal test'
3
+ script: 'bundle exec rake test'
4
4
  services:
5
5
  - mongodb
6
6
  rvm:
7
7
  - 1.8.7
8
8
  - 1.9.3
9
9
  - 2.0.0
10
- - ruby-head
11
10
  env:
12
11
  - DB=mongodb
13
12
  - DB=redis
14
13
  - DB=mysql
15
14
  #- DB=postgres
15
+ gemfile:
16
+ - Gemfile
17
+ - gemfiles/rails3.gemfile
18
+ - gemfiles/rails31.gemfile
19
+ - gemfiles/rails32.gemfile
16
20
  before_script:
21
+ - if [[ "`basename $BUNDLE_GEMFILE`" == "Gemfile" ]]; then rvm rubygems 1.8.25; fi # Rubygems 2.0.x fails with Rails 2.3
17
22
  - "mysql -e 'create database vanity_test;' >/dev/null"
18
- - "rake appraisal:install"
19
- #- "psql -c 'create database vanity_test;' -U postgres >/dev/null"
23
+ #- if [[ "$DB" == "pgsql" ]]; then psql -c 'create database vanity_test;' -U postgres >/dev/null; fi
20
24
  matrix:
21
- allow_failures:
25
+ exclude:
26
+ # Rails 2 is not officially supported on Ruby 1.9.3
27
+ - rvm: 1.9.3
28
+ env: DB=mongodb
29
+ gemfile: Gemfile
30
+ - rvm: 1.9.3
31
+ env: DB=redis
32
+ gemfile: Gemfile
33
+ - rvm: 1.9.3
34
+ env: DB=mysql
35
+ gemfile: Gemfile
36
+ # Rails <= 3.2 is not officially supported on Ruby 2.0.0
37
+ - rvm: 2.0.0
38
+ env: DB=mongodb
39
+ gemfile: Gemfile
40
+ - rvm: 2.0.0
41
+ env: DB=redis
42
+ gemfile: Gemfile
43
+ - rvm: 2.0.0
44
+ env: DB=mysql
45
+ gemfile: Gemfile
46
+ - rvm: 2.0.0
47
+ env: DB=mongodb
48
+ gemfile: gemfiles/rails3.gemfile
22
49
  - rvm: 2.0.0
50
+ env: DB=redis
51
+ gemfile: gemfiles/rails3.gemfile
52
+ - rvm: 2.0.0
53
+ env: DB=mysql
54
+ gemfile: gemfiles/rails3.gemfile
55
+ allow_failures:
23
56
  - rvm: ruby-head
57
+ - rvm: 2.0.0
58
+ env: DB=mongodb
59
+ gemfile: gemfiles/rails31.gemfile
60
+ - rvm: 2.0.0
61
+ env: DB=redis
62
+ gemfile: gemfiles/rails31.gemfile
63
+ - rvm: 2.0.0
64
+ env: DB=mysql
65
+ gemfile: gemfiles/rails31.gemfile
data/Appraisals CHANGED
@@ -1,15 +1,17 @@
1
1
  appraise "rails3" do
2
2
  gem "rails", "3.0.11"
3
+ gem "fastthread", :git => "git://github.com/zoltankiss/fastthread.git", :platforms => :mri_20
3
4
  gem "passenger", "~>3.0"
4
5
  end
5
6
 
6
7
  appraise "rails31" do
7
8
  gem "rails", "3.1.3"
9
+ gem "fastthread", :git => "git://github.com/zoltankiss/fastthread.git", :platforms => :mri_20
8
10
  gem "passenger", "~>3.0"
9
11
  end
10
12
 
11
13
  appraise "rails32" do
12
14
  gem "rails", "3.2.1"
15
+ gem "fastthread", :git => "git://github.com/zoltankiss/fastthread.git", :platforms => :mri_20
13
16
  gem "passenger", "~>3.0"
14
17
  end
15
-
data/CHANGELOG CHANGED
@@ -1,8 +1,14 @@
1
+ == 1.8.2 (2013-10-27)
2
+
3
+ Optimize metric_values query (@zawaideh).
4
+ Add an on_assignment hook for experiments which is called when an identity is given an assignment in ab_test (@lotze)
5
+ Finish Ruby 2.0 compatiblity with testing setup and add ActionMailer test coverage (@phillbaker).
6
+
1
7
  == 1.8.1 (2013-10-05)
2
8
 
3
9
  Added vanity_experiments helper for rails to return read only copy of active experiments (@iceberg901).
4
10
  Fixed support for Mass Assignment on Rails 3.2 (@hcarver).
5
- Fixed commandlin usage (@phillbaker).
11
+ Fixed commandline usage (@phillbaker).
6
12
 
7
13
 
8
14
  == 1.8.0 (2012-03-12)
data/Gemfile CHANGED
@@ -1,22 +1,33 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem "appraisal"
4
+ # Frameworks
5
+ gem "rack"
6
+ gem "rails", "~>2.3.8"
7
+
8
+ # Servers
9
+ gem "passenger", "~>2.0"
10
+
11
+ # Persistence
5
12
  gem "bson_ext"
6
- gem "garb"
7
- gem "mocha"
8
13
  gem "mongo"
9
- gem "bson_ext"
10
14
  gem "mysql"
11
- gem "passenger", "~>2.0"
12
15
  gem "pg"
13
- gem "rails", "~>2.3.8"
14
- gem "rack"
15
- gem "shoulda"
16
- gem "timecop"
17
- gem "webmock"
16
+
17
+ # APIs
18
+ gem "garb"
19
+
20
+ # Compatibility
18
21
  gem "SystemTimer", "1.2.3", :platforms => :mri_18
19
22
 
23
+ # Testing
24
+ gem "appraisal"
25
+
26
+ gem "mocha", :require=>false
27
+ gem "shoulda", :require=>false # Requires test/unit
28
+ gem "timecop", :require=>false
29
+ gem "webmock", :require=>false
30
+
20
31
  group :development do
21
32
  gem "jekyll"
22
33
  gem "rake"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vanity (1.8.1)
4
+ vanity (1.8.2)
5
5
  redis (~> 2.0)
6
6
  redis-namespace (~> 1.0.0)
7
7
 
@@ -1,5 +1,5 @@
1
1
  = Vanity
2
- {<img src="https://travis-ci.org/assaf/vanity.png?branch=feature/readme-update" alt="Build Status" />}[https://travis-ci.org/assaf/vanity]
2
+ {<img src="https://travis-ci.org/assaf/vanity.png?branch=master" alt="Build Status" />}[https://travis-ci.org/assaf/vanity]
3
3
 
4
4
  Vanity is an Experiment Driven Development framework for Rails.
5
5
 
@@ -96,13 +96,16 @@ If robots or spiders make up a significant portion of your sites traffic they ca
96
96
 
97
97
  == Compatibility Matrix
98
98
 
99
- Running Rails 2 on Ruby 2? Vanity probably won't work for you. But here's what does:
99
+ Here's what's tested and known to work:
100
100
 
101
- Persistence: Redis, Mongo, ActiveRecord
102
- Rails: 2.3, 3, 3.1, 3.2
103
- Ruby: 1.8.7, 1.9.3
101
+ Ruby 1.8.7, 1.9.3
102
+ Persistence: Redis, Mongo, ActiveRecord
103
+ Rails: 2.3, 3, 3.1, 3.2
104
+ Ruby 2.0
105
+ Persistence: Redis, Mongo, ActiveRecord
106
+ Rails: 3.2
104
107
 
105
- NOTE: Support for Rails 4 and Ruby 2.0 are coming soon!
108
+ NOTE: Support for Rails 4 is coming soon!
106
109
 
107
110
  == Contributing
108
111
 
@@ -2,19 +2,20 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal"
6
- gem "garb"
7
- gem "mocha"
8
- gem "mongo"
5
+ gem "rack"
9
6
  gem "bson_ext"
7
+ gem "mongo"
10
8
  gem "mysql"
11
9
  gem "pg"
12
- gem "rack"
13
- gem "shoulda"
14
- gem "timecop"
15
- gem "webmock"
10
+ gem "garb"
16
11
  gem "SystemTimer", "1.2.3", :platforms=>:mri_18
12
+ gem "appraisal"
13
+ gem "mocha", :require=>false
14
+ gem "shoulda", :require=>false
15
+ gem "timecop", :require=>false
16
+ gem "webmock", :require=>false
17
17
  gem "rails", "3.0.11"
18
+ gem "fastthread", :git=>"git://github.com/zoltankiss/fastthread.git", :platforms=>:mri_20
18
19
  gem "passenger", "~>3.0"
19
20
 
20
21
  gemspec :path=>"../"
@@ -1,7 +1,13 @@
1
+ GIT
2
+ remote: git://github.com/zoltankiss/fastthread.git
3
+ revision: 56e6ce7c1780797a354d5befe9a9a9869bbc7e3e
4
+ specs:
5
+ fastthread (1.0.7)
6
+
1
7
  PATH
2
8
  remote: /Users/phill/Development/ruby/vanity
3
9
  specs:
4
- vanity (1.8.1)
10
+ vanity (1.8.2)
5
11
  redis (~> 2.0)
6
12
  redis-namespace (~> 1.0.0)
7
13
 
@@ -49,7 +55,6 @@ GEM
49
55
  daemon_controller (1.0.0)
50
56
  erubis (2.6.6)
51
57
  abstract (>= 1.0.0)
52
- fastthread (1.0.7)
53
58
  garb (0.9.1)
54
59
  activesupport (>= 2.2.0)
55
60
  crack (>= 0.1.6)
@@ -121,6 +126,7 @@ DEPENDENCIES
121
126
  SystemTimer (= 1.2.3)
122
127
  appraisal
123
128
  bson_ext
129
+ fastthread!
124
130
  garb
125
131
  mocha
126
132
  mongo
@@ -2,19 +2,20 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal"
6
- gem "garb"
7
- gem "mocha"
8
- gem "mongo"
5
+ gem "rack"
9
6
  gem "bson_ext"
7
+ gem "mongo"
10
8
  gem "mysql"
11
9
  gem "pg"
12
- gem "rack"
13
- gem "shoulda"
14
- gem "timecop"
15
- gem "webmock"
10
+ gem "garb"
16
11
  gem "SystemTimer", "1.2.3", :platforms=>:mri_18
12
+ gem "appraisal"
13
+ gem "mocha", :require=>false
14
+ gem "shoulda", :require=>false
15
+ gem "timecop", :require=>false
16
+ gem "webmock", :require=>false
17
17
  gem "rails", "3.1.3"
18
+ gem "fastthread", :git=>"git://github.com/zoltankiss/fastthread.git", :platforms=>:mri_20
18
19
  gem "passenger", "~>3.0"
19
20
 
20
21
  gemspec :path=>"../"
@@ -1,7 +1,13 @@
1
+ GIT
2
+ remote: git://github.com/zoltankiss/fastthread.git
3
+ revision: 56e6ce7c1780797a354d5befe9a9a9869bbc7e3e
4
+ specs:
5
+ fastthread (1.0.7)
6
+
1
7
  PATH
2
8
  remote: /Users/phill/Development/ruby/vanity
3
9
  specs:
4
- vanity (1.8.1)
10
+ vanity (1.8.2)
5
11
  redis (~> 2.0)
6
12
  redis-namespace (~> 1.0.0)
7
13
 
@@ -49,7 +55,6 @@ GEM
49
55
  crack (0.3.1)
50
56
  daemon_controller (1.0.0)
51
57
  erubis (2.7.0)
52
- fastthread (1.0.7)
53
58
  garb (0.9.1)
54
59
  activesupport (>= 2.2.0)
55
60
  crack (>= 0.1.6)
@@ -132,6 +137,7 @@ DEPENDENCIES
132
137
  SystemTimer (= 1.2.3)
133
138
  appraisal
134
139
  bson_ext
140
+ fastthread!
135
141
  garb
136
142
  mocha
137
143
  mongo
@@ -2,19 +2,20 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal"
6
- gem "garb"
7
- gem "mocha"
8
- gem "mongo"
5
+ gem "rack"
9
6
  gem "bson_ext"
7
+ gem "mongo"
10
8
  gem "mysql"
11
9
  gem "pg"
12
- gem "rack"
13
- gem "shoulda"
14
- gem "timecop"
15
- gem "webmock"
10
+ gem "garb"
16
11
  gem "SystemTimer", "1.2.3", :platforms=>:mri_18
12
+ gem "appraisal"
13
+ gem "mocha", :require=>false
14
+ gem "shoulda", :require=>false
15
+ gem "timecop", :require=>false
16
+ gem "webmock", :require=>false
17
17
  gem "rails", "3.2.1"
18
+ gem "fastthread", :git=>"git://github.com/zoltankiss/fastthread.git", :platforms=>:mri_20
18
19
  gem "passenger", "~>3.0"
19
20
 
20
21
  gemspec :path=>"../"
@@ -1,7 +1,13 @@
1
+ GIT
2
+ remote: git://github.com/zoltankiss/fastthread.git
3
+ revision: 56e6ce7c1780797a354d5befe9a9a9869bbc7e3e
4
+ specs:
5
+ fastthread (1.0.7)
6
+
1
7
  PATH
2
8
  remote: /Users/phill/Development/ruby/vanity
3
9
  specs:
4
- vanity (1.8.1)
10
+ vanity (1.8.2)
5
11
  redis (~> 2.0)
6
12
  redis-namespace (~> 1.0.0)
7
13
 
@@ -48,7 +54,6 @@ GEM
48
54
  crack (0.3.1)
49
55
  daemon_controller (1.0.0)
50
56
  erubis (2.7.0)
51
- fastthread (1.0.7)
52
57
  garb (0.9.1)
53
58
  activesupport (>= 2.2.0)
54
59
  crack (>= 0.1.6)
@@ -130,6 +135,7 @@ DEPENDENCIES
130
135
  SystemTimer (= 1.2.3)
131
136
  appraisal
132
137
  bson_ext
138
+ fastthread!
133
139
  garb
134
140
  mocha
135
141
  mongo
@@ -31,6 +31,7 @@ require "vanity/adapters/mongodb_adapter"
31
31
  require "vanity/adapters/mock_adapter"
32
32
  # Playground.
33
33
  require "vanity/playground"
34
+ require "vanity/autoconnect"
34
35
  require "vanity/helpers"
35
36
  # Integration with various frameworks.
36
37
  require "vanity/frameworks"
@@ -110,6 +110,11 @@ module Vanity
110
110
  fail "Not implemented"
111
111
  end
112
112
 
113
+ # Determines if a participant already has seen this alternative in this experiment.
114
+ def ab_seen(experiment, identity, assignment)
115
+ fail "Not implemented"
116
+ end
117
+
113
118
  # Records a conversion in this experiment for the given alternative.
114
119
  # Associates a value with the conversion (default to 1). If implicit is
115
120
  # true, add particpant if not already recorded for this experiment. If
@@ -42,7 +42,7 @@ module Vanity
42
42
  class VanityExperiment < VanityRecord
43
43
  self.table_name = :vanity_experiments
44
44
  has_many :vanity_conversions, :dependent => :destroy
45
- attr_accessible :experiment_id if respond_to?(:attr_accessible)
45
+ attr_accessible :experiment_id if respond_to?(:attr_accessible)
46
46
 
47
47
  # Finds or creates the experiment
48
48
  def self.retrieve(experiment)
@@ -64,7 +64,7 @@ module Vanity
64
64
  # Participant model
65
65
  class VanityParticipant < VanityRecord
66
66
  self.table_name = :vanity_participants
67
- attr_accessible :experiment_id, :identity, :seen, :shown, :converted if respond_to?(:attr_accessible)
67
+ attr_accessible :experiment_id, :identity, :seen, :shown, :converted if respond_to?(:attr_accessible)
68
68
 
69
69
  # Finds the participant by experiment and identity. If
70
70
  # create is true then it will create the participant
@@ -127,7 +127,7 @@ module Vanity
127
127
  connection = VanityMetric.connection
128
128
  record = VanityMetric.retrieve(metric)
129
129
  dates = (from.to_date..to.to_date).map(&:to_s)
130
- conditions = [connection.quote_column_name('date') + ' IN (?)', dates]
130
+ conditions = [connection.quote_column_name('date') + ' BETWEEN ? AND ?', from.to_date, to.to_date]
131
131
  order = "#{connection.quote_column_name('date')}"
132
132
  select = "sum(#{connection.quote_column_name('value')}) AS value, #{connection.quote_column_name('date')}"
133
133
  group_by = "#{connection.quote_column_name('date')}"
@@ -216,12 +216,19 @@ module Vanity
216
216
  VanityParticipant.retrieve(experiment, identity, true, :seen => alternative)
217
217
  end
218
218
 
219
+ # Determines if a participant already has seen this alternative in this experiment.
220
+ def ab_seen(experiment, identity, alternative)
221
+ participant = VanityParticipant.retrieve(experiment, identity, false)
222
+ participant && participant.seen == alternative.id
223
+ end
224
+
219
225
  # Records a conversion in this experiment for the given alternative.
220
226
  # Associates a value with the conversion (default to 1). If implicit is
221
- # true, add particpant if not already recorded for this experiment. If
222
- # implicit is false (default), only add conversion is participant
227
+ # true, add participant if not already recorded for this experiment. If
228
+ # implicit is false (default), only add conversion if participant
223
229
  # previously recorded as participating in this experiment.
224
230
  def ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false)
231
+ participant = VanityParticipant.retrieve(experiment, identity, false)
225
232
  VanityParticipant.retrieve(experiment, identity, implicit, :converted => alternative)
226
233
  VanityExperiment.retrieve(experiment).increment_conversion(alternative, count)
227
234
  end
@@ -150,6 +150,12 @@ module Vanity
150
150
  @participants.update({ :experiment=>experiment, :identity=>identity }, { "$push"=>{ :seen=>alternative } }, :upsert=>true)
151
151
  end
152
152
 
153
+ # Determines if a participant already has seen this alternative in this experiment.
154
+ def ab_seen(experiment, identity, alternative)
155
+ participant = @participants.find_one({ :experiment=>experiment, :identity=>identity }, { :fields=>[:seen] })
156
+ participant && participant["seen"].first == alternative.id
157
+ end
158
+
153
159
  def ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false)
154
160
  if implicit
155
161
  @participants.update({ :experiment=>experiment, :identity=>identity }, { "$push"=>{ :seen=>alternative } }, :upsert=>true)