vanity 2.2.10 → 3.0.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.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +8 -10
  3. data/Appraisals +9 -19
  4. data/CHANGELOG +7 -1
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +20 -12
  7. data/README.md +11 -13
  8. data/gemfiles/rails42.gemfile +2 -2
  9. data/gemfiles/rails42.gemfile.lock +89 -84
  10. data/gemfiles/rails42_protected_attributes.gemfile +2 -2
  11. data/gemfiles/rails42_protected_attributes.gemfile.lock +84 -79
  12. data/gemfiles/{rails41.gemfile → rails51.gemfile} +3 -3
  13. data/gemfiles/rails51.gemfile.lock +262 -0
  14. data/gemfiles/{rails5.gemfile → rails52.gemfile} +2 -2
  15. data/gemfiles/rails52.gemfile.lock +270 -0
  16. data/lib/generators/templates/{add_participants_unique_index_migration.rb → add_participants_unique_index_migration.rb.erb} +1 -1
  17. data/lib/generators/templates/{add_unique_indexes_migration.rb → add_unique_indexes_migration.rb.erb} +1 -1
  18. data/lib/generators/templates/{vanity_migration.rb → vanity_migration.rb.erb} +1 -1
  19. data/lib/generators/vanity/migration_generator.rb +34 -0
  20. data/lib/vanity/adapters/redis_adapter.rb +18 -18
  21. data/lib/vanity/version.rb +1 -1
  22. data/test/adapters/redis_adapter_test.rb +8 -12
  23. data/test/adapters/shared_tests.rb +7 -6
  24. data/test/commands/report_test.rb +13 -1
  25. data/test/configuration_test.rb +15 -2
  26. data/test/dummy/app/mailers/vanity_mailer.rb +3 -1
  27. data/test/dummy/config/routes.rb +17 -3
  28. data/test/experiment/ab_test.rb +3 -3
  29. data/test/frameworks/rails/action_controller_test.rb +12 -6
  30. data/test/frameworks/rails/action_mailer_test.rb +0 -1
  31. data/test/metric/active_record_test.rb +8 -2
  32. data/test/test_helper.rb +57 -10
  33. data/test/web/rails/dashboard_test.rb +19 -10
  34. data/vanity.gemspec +1 -1
  35. metadata +14 -19
  36. data/gemfiles/rails32.gemfile +0 -36
  37. data/gemfiles/rails32.gemfile.lock +0 -242
  38. data/gemfiles/rails41.gemfile.lock +0 -230
  39. data/gemfiles/rails5.gemfile.lock +0 -256
  40. data/lib/generators/vanity/add_participants_unique_index_generator.rb +0 -15
  41. data/lib/generators/vanity/add_unique_indexes_generator.rb +0 -15
  42. data/lib/generators/vanity_generator.rb +0 -15
@@ -3,14 +3,14 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "rack"
6
- gem "redis", ">= 2.1"
6
+ gem "redis", ">= 3.2.1"
7
7
  gem "redis-namespace", ">= 1.1.0"
8
8
  gem "mongo", "~> 2.1"
9
9
  gem "integration", "<= 0.1.0"
10
10
  gem "rubystats", ">= 0.2.5"
11
11
  gem "garb", "< 0.9.2", :require => false
12
12
  gem "mocha", "~> 1.0", :require => false
13
- gem "rails", "5.0.0"
13
+ gem "rails", "~>5.2.0"
14
14
  gem "fastthread", :git => "git://github.com/zoltankiss/fastthread.git", :platforms => :mri_20
15
15
  gem "passenger", "~>3.0"
16
16
 
@@ -0,0 +1,270 @@
1
+ GIT
2
+ remote: git://github.com/zoltankiss/fastthread.git
3
+ revision: cefbca3009b9c68df5e473d840462ebcc7fa1504
4
+ specs:
5
+ fastthread (1.0.7)
6
+
7
+ PATH
8
+ remote: ..
9
+ specs:
10
+ vanity (3.0.0)
11
+ i18n
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ RedCloth (4.3.2)
17
+ actioncable (5.2.0)
18
+ actionpack (= 5.2.0)
19
+ nio4r (~> 2.0)
20
+ websocket-driver (>= 0.6.1)
21
+ actionmailer (5.2.0)
22
+ actionpack (= 5.2.0)
23
+ actionview (= 5.2.0)
24
+ activejob (= 5.2.0)
25
+ mail (~> 2.5, >= 2.5.4)
26
+ rails-dom-testing (~> 2.0)
27
+ actionpack (5.2.0)
28
+ actionview (= 5.2.0)
29
+ activesupport (= 5.2.0)
30
+ rack (~> 2.0)
31
+ rack-test (>= 0.6.3)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
34
+ actionview (5.2.0)
35
+ activesupport (= 5.2.0)
36
+ builder (~> 3.1)
37
+ erubi (~> 1.4)
38
+ rails-dom-testing (~> 2.0)
39
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
40
+ activejob (5.2.0)
41
+ activesupport (= 5.2.0)
42
+ globalid (>= 0.3.6)
43
+ activemodel (5.2.0)
44
+ activesupport (= 5.2.0)
45
+ activerecord (5.2.0)
46
+ activemodel (= 5.2.0)
47
+ activesupport (= 5.2.0)
48
+ arel (>= 9.0)
49
+ activestorage (5.2.0)
50
+ actionpack (= 5.2.0)
51
+ activerecord (= 5.2.0)
52
+ marcel (~> 0.3.1)
53
+ activesupport (5.2.0)
54
+ concurrent-ruby (~> 1.0, >= 1.0.2)
55
+ i18n (>= 0.7, < 2)
56
+ minitest (~> 5.1)
57
+ tzinfo (~> 1.1)
58
+ addressable (2.5.2)
59
+ public_suffix (>= 2.0.2, < 4.0)
60
+ appraisal (2.0.2)
61
+ bundler
62
+ rake
63
+ thor (>= 0.14.0)
64
+ arel (9.0.0)
65
+ blankslate (2.1.2.4)
66
+ bson (4.3.0)
67
+ builder (3.2.3)
68
+ classifier-reborn (2.2.0)
69
+ fast-stemmer (~> 1.0)
70
+ coderay (1.1.2)
71
+ coffee-script (2.4.1)
72
+ coffee-script-source
73
+ execjs
74
+ coffee-script-source (1.11.1)
75
+ colorator (0.1)
76
+ concurrent-ruby (1.0.5)
77
+ crack (0.4.3)
78
+ safe_yaml (~> 1.0.0)
79
+ crass (1.0.4)
80
+ daemon_controller (1.2.0)
81
+ erubi (1.7.1)
82
+ execjs (2.7.0)
83
+ fakefs (0.18.0)
84
+ faraday (0.15.2)
85
+ multipart-post (>= 1.2, < 3)
86
+ fast-stemmer (1.0.2)
87
+ ffi (1.9.25)
88
+ garb (0.9.1)
89
+ activesupport (>= 2.2.0)
90
+ crack (>= 0.1.6)
91
+ globalid (0.4.1)
92
+ activesupport (>= 4.2.0)
93
+ hashdiff (0.3.7)
94
+ i18n (1.0.1)
95
+ concurrent-ruby (~> 1.0)
96
+ integration (0.1.0)
97
+ jekyll (2.5.3)
98
+ classifier-reborn (~> 2.0)
99
+ colorator (~> 0.1)
100
+ jekyll-coffeescript (~> 1.0)
101
+ jekyll-gist (~> 1.0)
102
+ jekyll-paginate (~> 1.0)
103
+ jekyll-sass-converter (~> 1.0)
104
+ jekyll-watch (~> 1.1)
105
+ kramdown (~> 1.3)
106
+ liquid (~> 2.6.1)
107
+ mercenary (~> 0.3.3)
108
+ pygments.rb (~> 0.6.0)
109
+ redcarpet (~> 3.1)
110
+ safe_yaml (~> 1.0)
111
+ toml (~> 0.1.0)
112
+ jekyll-coffeescript (1.1.1)
113
+ coffee-script (~> 2.2)
114
+ coffee-script-source (~> 1.11.1)
115
+ jekyll-gist (1.5.0)
116
+ octokit (~> 4.2)
117
+ jekyll-paginate (1.1.0)
118
+ jekyll-sass-converter (1.5.2)
119
+ sass (~> 3.4)
120
+ jekyll-watch (1.5.1)
121
+ listen (~> 3.0)
122
+ kramdown (1.17.0)
123
+ liquid (2.6.3)
124
+ listen (3.1.5)
125
+ rb-fsevent (~> 0.9, >= 0.9.4)
126
+ rb-inotify (~> 0.9, >= 0.9.7)
127
+ ruby_dep (~> 1.2)
128
+ loofah (2.2.2)
129
+ crass (~> 1.0.2)
130
+ nokogiri (>= 1.5.9)
131
+ mail (2.7.0)
132
+ mini_mime (>= 0.1.1)
133
+ marcel (0.3.2)
134
+ mimemagic (~> 0.3.2)
135
+ mercenary (0.3.6)
136
+ metaclass (0.0.4)
137
+ method_source (0.9.0)
138
+ mimemagic (0.3.2)
139
+ mini_mime (1.0.0)
140
+ mini_portile2 (2.3.0)
141
+ minitest (5.11.3)
142
+ mocha (1.6.0)
143
+ metaclass (~> 0.0.1)
144
+ mongo (2.6.1)
145
+ bson (>= 4.3.0, < 5.0.0)
146
+ multipart-post (2.0.0)
147
+ nio4r (2.3.1)
148
+ nokogiri (1.8.4)
149
+ mini_portile2 (~> 2.3.0)
150
+ octokit (4.9.0)
151
+ sawyer (~> 0.8.0, >= 0.5.3)
152
+ parslet (1.5.0)
153
+ blankslate (~> 2.0)
154
+ passenger (3.0.21)
155
+ daemon_controller (>= 1.0.0)
156
+ fastthread (>= 1.0.1)
157
+ rack
158
+ rake (>= 0.8.1)
159
+ posix-spawn (0.3.13)
160
+ pry (0.11.3)
161
+ coderay (~> 1.1.0)
162
+ method_source (~> 0.9.0)
163
+ public_suffix (3.0.2)
164
+ pygments.rb (0.6.3)
165
+ posix-spawn (~> 0.3.6)
166
+ yajl-ruby (~> 1.2.0)
167
+ rack (2.0.5)
168
+ rack-test (1.1.0)
169
+ rack (>= 1.0, < 3)
170
+ rails (5.2.0)
171
+ actioncable (= 5.2.0)
172
+ actionmailer (= 5.2.0)
173
+ actionpack (= 5.2.0)
174
+ actionview (= 5.2.0)
175
+ activejob (= 5.2.0)
176
+ activemodel (= 5.2.0)
177
+ activerecord (= 5.2.0)
178
+ activestorage (= 5.2.0)
179
+ activesupport (= 5.2.0)
180
+ bundler (>= 1.3.0)
181
+ railties (= 5.2.0)
182
+ sprockets-rails (>= 2.0.0)
183
+ rails-dom-testing (2.0.3)
184
+ activesupport (>= 4.2.0)
185
+ nokogiri (>= 1.6)
186
+ rails-html-sanitizer (1.0.4)
187
+ loofah (~> 2.2, >= 2.2.2)
188
+ railties (5.2.0)
189
+ actionpack (= 5.2.0)
190
+ activesupport (= 5.2.0)
191
+ method_source
192
+ rake (>= 0.8.7)
193
+ thor (>= 0.18.1, < 2.0)
194
+ rake (12.3.1)
195
+ rb-fsevent (0.10.3)
196
+ rb-inotify (0.9.10)
197
+ ffi (>= 0.5.0, < 2)
198
+ redcarpet (3.4.0)
199
+ redis (4.0.1)
200
+ redis-namespace (1.6.0)
201
+ redis (>= 3.0.4)
202
+ ruby_dep (1.5.0)
203
+ rubystats (0.3.0)
204
+ safe_yaml (1.0.4)
205
+ sass (3.5.7)
206
+ sass-listen (~> 4.0.0)
207
+ sass-listen (4.0.0)
208
+ rb-fsevent (~> 0.9, >= 0.9.4)
209
+ rb-inotify (~> 0.9, >= 0.9.7)
210
+ sawyer (0.8.1)
211
+ addressable (>= 2.3.5, < 2.6)
212
+ faraday (~> 0.8, < 1.0)
213
+ sprockets (3.7.2)
214
+ concurrent-ruby (~> 1.0)
215
+ rack (> 1, < 3)
216
+ sprockets-rails (3.2.1)
217
+ actionpack (>= 4.0)
218
+ activesupport (>= 4.0)
219
+ sprockets (>= 3.0.0)
220
+ sqlite3 (1.3.13)
221
+ thor (0.20.0)
222
+ thread_safe (0.3.6)
223
+ timecop (0.9.1)
224
+ toml (0.1.2)
225
+ parslet (~> 1.5.0)
226
+ tzinfo (1.2.5)
227
+ thread_safe (~> 0.1)
228
+ webmock (3.4.2)
229
+ addressable (>= 2.3.6)
230
+ crack (>= 0.3.2)
231
+ hashdiff
232
+ websocket-driver (0.7.0)
233
+ websocket-extensions (>= 0.1.0)
234
+ websocket-extensions (0.1.3)
235
+ yajl-ruby (1.2.3)
236
+ yard (0.9.15)
237
+
238
+ PLATFORMS
239
+ ruby
240
+
241
+ DEPENDENCIES
242
+ RedCloth
243
+ activerecord-jdbc-adapter
244
+ appraisal (~> 2.0.0)
245
+ bundler (>= 1.8.0)
246
+ fakefs
247
+ fastthread!
248
+ garb (< 0.9.2)
249
+ integration (<= 0.1.0)
250
+ jdbc-sqlite3
251
+ jekyll (~> 2.5.3)
252
+ minitest (>= 4.2)
253
+ mocha (~> 1.0)
254
+ mongo (~> 2.1)
255
+ passenger (~> 3.0)
256
+ pry
257
+ rack
258
+ rails (~> 5.2.0)
259
+ rake
260
+ redis (>= 3.2.1)
261
+ redis-namespace (>= 1.1.0)
262
+ rubystats (>= 0.2.5)
263
+ sqlite3 (~> 1.3.10)
264
+ timecop
265
+ vanity!
266
+ webmock
267
+ yard
268
+
269
+ BUNDLED WITH
270
+ 1.16.2
@@ -1,6 +1,6 @@
1
1
  require "vanity/adapters/active_record_adapter"
2
2
 
3
- class AddParticipansUniqueIndexMigration < ActiveRecord::Migration
3
+ class AddParticipantsUniqueIndexMigration < ActiveRecord::Migration<%= migration_version %>
4
4
  # Helper methods to ensure we're connecting to the right database, see
5
5
  # https://github.com/assaf/vanity/issues/295.
6
6
 
@@ -1,6 +1,6 @@
1
1
  require "vanity/adapters/active_record_adapter"
2
2
 
3
- class AddVanityUniqueIndexes < ActiveRecord::Migration
3
+ class AddVanityUniqueIndexes < ActiveRecord::Migration<%= migration_version %>
4
4
  # Helper methods to ensure we're connecting to the right database, see
5
5
  # https://github.com/assaf/vanity/issues/295.
6
6
 
@@ -1,6 +1,6 @@
1
1
  require "vanity/adapters/active_record_adapter"
2
2
 
3
- class VanityMigration < ActiveRecord::Migration
3
+ class VanityMigration < ActiveRecord::Migration<%= migration_version %>
4
4
  # Helper methods to ensure we're connecting to the right database, see
5
5
  # https://github.com/assaf/vanity/issues/295.
6
6
 
@@ -0,0 +1,34 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record'
4
+
5
+ class VanityGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../../templates', __FILE__)
8
+
9
+ def self.next_migration_number(path)
10
+ ::ActiveRecord::Generators::Base.next_migration_number(path)
11
+ end
12
+
13
+ def create_migration_file
14
+ migration_template "vanity_migration.rb.erb", destination("vanity_migration.rb"), :migration_version=>migration_version
15
+ migration_template "add_unique_indexes_migration.rb.erb", destination("add_vanity_unique_indexes.rb"), :migration_version=>migration_version
16
+ migration_template "add_participants_unique_index_migration.rb.erb", destination("add_participants_unique_index_migration.rb"), :migration_version=>migration_version
17
+ end
18
+
19
+ private
20
+
21
+ def destination(name)
22
+ File.join(Rails.root, 'db', 'migrate', name)
23
+ end
24
+
25
+ def versioned?
26
+ ActiveRecord::VERSION::MAJOR >= 5
27
+ end
28
+
29
+ def migration_version
30
+ if versioned?
31
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
32
+ end
33
+ end
34
+ end
@@ -41,11 +41,7 @@ module Vanity
41
41
 
42
42
  def disconnect!
43
43
  if redis
44
- begin
45
- redis.client.disconnect
46
- rescue Exception => e
47
- Vanity.logger.warn("Error while disconnecting from redis: #{e.message}")
48
- end
44
+ redis.disconnect!
49
45
  end
50
46
  @redis = nil
51
47
  end
@@ -72,7 +68,7 @@ module Vanity
72
68
  # -- Metrics --
73
69
 
74
70
  def get_metric_last_update_at(metric)
75
- last_update_at = @metrics["#{metric}:last_update_at"]
71
+ last_update_at = @metrics.get("#{metric}:last_update_at")
76
72
  last_update_at && Time.at(last_update_at.to_i)
77
73
  end
78
74
 
@@ -81,7 +77,7 @@ module Vanity
81
77
  values.each_with_index do |v,i|
82
78
  @metrics.incrby "#{metric}:#{timestamp.to_date}:value:#{i}", v
83
79
  end
84
- @metrics["#{metric}:last_update_at"] = Time.now.to_i
80
+ @metrics.set("#{metric}:last_update_at", Time.now.to_i)
85
81
  end
86
82
  end
87
83
 
@@ -98,7 +94,7 @@ module Vanity
98
94
  # -- Experiments --
99
95
 
100
96
  def experiment_persisted?(experiment)
101
- !!@experiments["#{experiment}:created_at"]
97
+ !!@experiments.get("#{experiment}:created_at")
102
98
  end
103
99
 
104
100
  def set_experiment_created_at(experiment, time)
@@ -108,7 +104,7 @@ module Vanity
108
104
  end
109
105
 
110
106
  def get_experiment_created_at(experiment)
111
- created_at = @experiments["#{experiment}:created_at"]
107
+ created_at = @experiments.get("#{experiment}:created_at")
112
108
  created_at && Time.at(created_at.to_i)
113
109
  end
114
110
 
@@ -117,7 +113,7 @@ module Vanity
117
113
  end
118
114
 
119
115
  def get_experiment_completed_at(experiment)
120
- completed_at = @experiments["#{experiment}:completed_at"]
116
+ completed_at = @experiments.get("#{experiment}:completed_at")
121
117
  completed_at && Time.at(completed_at.to_i)
122
118
  end
123
119
 
@@ -134,7 +130,7 @@ module Vanity
134
130
  end
135
131
 
136
132
  def is_experiment_enabled?(experiment)
137
- value = @experiments["#{experiment}:enabled"]
133
+ value = @experiments.get("#{experiment}:enabled")
138
134
  if Vanity.configuration.experiments_start_enabled
139
135
  value != 'false'
140
136
  else
@@ -146,19 +142,19 @@ module Vanity
146
142
  {
147
143
  :participants => @experiments.scard("#{experiment}:alts:#{alternative}:participants").to_i,
148
144
  :converted => @experiments.scard("#{experiment}:alts:#{alternative}:converted").to_i,
149
- :conversions => @experiments["#{experiment}:alts:#{alternative}:conversions"].to_i
145
+ :conversions => @experiments.get("#{experiment}:alts:#{alternative}:conversions").to_i
150
146
  }
151
147
  end
152
148
 
153
149
  def ab_show(experiment, identity, alternative)
154
150
  call_redis_with_failover do
155
- @experiments["#{experiment}:participant:#{identity}:show"] = alternative
151
+ @experiments.set("#{experiment}:participant:#{identity}:show", alternative)
156
152
  end
157
153
  end
158
154
 
159
155
  def ab_showing(experiment, identity)
160
156
  call_redis_with_failover do
161
- alternative = @experiments["#{experiment}:participant:#{identity}:show"]
157
+ alternative = @experiments.get("#{experiment}:participant:#{identity}:show")
162
158
  alternative && alternative.to_i
163
159
  end
164
160
  end
@@ -212,7 +208,7 @@ module Vanity
212
208
  end
213
209
 
214
210
  def ab_get_outcome(experiment)
215
- alternative = @experiments["#{experiment}:outcome"]
211
+ alternative = @experiments.get("#{experiment}:outcome")
216
212
  alternative && alternative.to_i
217
213
  end
218
214
 
@@ -221,9 +217,13 @@ module Vanity
221
217
  end
222
218
 
223
219
  def destroy_experiment(experiment)
224
- @experiments.del "#{experiment}:outcome", "#{experiment}:created_at", "#{experiment}:completed_at"
225
- alternatives = @experiments.keys("#{experiment}:alts:*")
226
- @experiments.del(*alternatives) unless alternatives.empty?
220
+ cursor = nil
221
+
222
+ while cursor != "0" do
223
+ cursor, keys = @experiments.scan(cursor || "0", match: "#{experiment}:*")
224
+
225
+ @experiments.del(*keys) unless keys.empty?
226
+ end
227
227
  end
228
228
 
229
229
  protected