vanity 2.2.10 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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