moses-vanity 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.autotest +22 -0
  2. data/.gitignore +7 -0
  3. data/.rvmrc +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG +374 -0
  6. data/Gemfile +28 -0
  7. data/MIT-LICENSE +21 -0
  8. data/README.rdoc +108 -0
  9. data/Rakefile +189 -0
  10. data/bin/vanity +16 -0
  11. data/doc/_config.yml +2 -0
  12. data/doc/_layouts/_header.html +34 -0
  13. data/doc/_layouts/page.html +47 -0
  14. data/doc/_metrics.textile +12 -0
  15. data/doc/ab_testing.textile +210 -0
  16. data/doc/configuring.textile +45 -0
  17. data/doc/contributing.textile +93 -0
  18. data/doc/credits.textile +23 -0
  19. data/doc/css/page.css +83 -0
  20. data/doc/css/print.css +43 -0
  21. data/doc/css/syntax.css +7 -0
  22. data/doc/email.textile +129 -0
  23. data/doc/experimental.textile +31 -0
  24. data/doc/faq.textile +8 -0
  25. data/doc/identity.textile +43 -0
  26. data/doc/images/ab_in_dashboard.png +0 -0
  27. data/doc/images/clear_winner.png +0 -0
  28. data/doc/images/price_options.png +0 -0
  29. data/doc/images/sidebar_test.png +0 -0
  30. data/doc/images/signup_metric.png +0 -0
  31. data/doc/images/vanity.png +0 -0
  32. data/doc/index.textile +91 -0
  33. data/doc/metrics.textile +231 -0
  34. data/doc/rails.textile +89 -0
  35. data/doc/site.js +27 -0
  36. data/generators/templates/vanity_migration.rb +53 -0
  37. data/generators/vanity_generator.rb +8 -0
  38. data/lib/generators/templates/vanity_migration.rb +53 -0
  39. data/lib/generators/vanity_generator.rb +15 -0
  40. data/lib/vanity.rb +36 -0
  41. data/lib/vanity/adapters/abstract_adapter.rb +140 -0
  42. data/lib/vanity/adapters/active_record_adapter.rb +248 -0
  43. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  44. data/lib/vanity/adapters/mongodb_adapter.rb +178 -0
  45. data/lib/vanity/adapters/redis_adapter.rb +160 -0
  46. data/lib/vanity/backport.rb +26 -0
  47. data/lib/vanity/commands/list.rb +21 -0
  48. data/lib/vanity/commands/report.rb +64 -0
  49. data/lib/vanity/commands/upgrade.rb +34 -0
  50. data/lib/vanity/experiment/ab_test.rb +507 -0
  51. data/lib/vanity/experiment/base.rb +214 -0
  52. data/lib/vanity/frameworks.rb +16 -0
  53. data/lib/vanity/frameworks/rails.rb +318 -0
  54. data/lib/vanity/helpers.rb +66 -0
  55. data/lib/vanity/images/x.gif +0 -0
  56. data/lib/vanity/metric/active_record.rb +85 -0
  57. data/lib/vanity/metric/base.rb +244 -0
  58. data/lib/vanity/metric/google_analytics.rb +83 -0
  59. data/lib/vanity/metric/remote.rb +53 -0
  60. data/lib/vanity/playground.rb +396 -0
  61. data/lib/vanity/templates/_ab_test.erb +28 -0
  62. data/lib/vanity/templates/_experiment.erb +5 -0
  63. data/lib/vanity/templates/_experiments.erb +7 -0
  64. data/lib/vanity/templates/_metric.erb +14 -0
  65. data/lib/vanity/templates/_metrics.erb +13 -0
  66. data/lib/vanity/templates/_report.erb +27 -0
  67. data/lib/vanity/templates/_vanity.js.erb +20 -0
  68. data/lib/vanity/templates/flot.min.js +1 -0
  69. data/lib/vanity/templates/jquery.min.js +19 -0
  70. data/lib/vanity/templates/vanity.css +26 -0
  71. data/lib/vanity/templates/vanity.js +82 -0
  72. data/lib/vanity/version.rb +11 -0
  73. data/test/adapters/redis_adapter_test.rb +17 -0
  74. data/test/experiment/ab_test.rb +771 -0
  75. data/test/experiment/base_test.rb +150 -0
  76. data/test/experiments/age_and_zipcode.rb +19 -0
  77. data/test/experiments/metrics/cheers.rb +3 -0
  78. data/test/experiments/metrics/signups.rb +2 -0
  79. data/test/experiments/metrics/yawns.rb +3 -0
  80. data/test/experiments/null_abc.rb +5 -0
  81. data/test/metric/active_record_test.rb +277 -0
  82. data/test/metric/base_test.rb +293 -0
  83. data/test/metric/google_analytics_test.rb +104 -0
  84. data/test/metric/remote_test.rb +109 -0
  85. data/test/myapp/app/controllers/application_controller.rb +2 -0
  86. data/test/myapp/app/controllers/main_controller.rb +7 -0
  87. data/test/myapp/config/boot.rb +110 -0
  88. data/test/myapp/config/environment.rb +10 -0
  89. data/test/myapp/config/environments/production.rb +0 -0
  90. data/test/myapp/config/routes.rb +3 -0
  91. data/test/passenger_test.rb +43 -0
  92. data/test/playground_test.rb +26 -0
  93. data/test/rails_dashboard_test.rb +37 -0
  94. data/test/rails_helper_test.rb +36 -0
  95. data/test/rails_test.rb +389 -0
  96. data/test/test_helper.rb +145 -0
  97. data/vanity.gemspec +26 -0
  98. metadata +202 -0
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class MainController < ApplicationController
2
+ def index
3
+ render :text=>"#{Vanity.playground.connection}\n#{Vanity.playground.connection.object_id}"
4
+ rescue Error=>ex
5
+ puts $!
6
+ end
7
+ end
@@ -0,0 +1,110 @@
1
+ # Don't change this file!
2
+ # Configure your app in config/environment.rb and config/environments/*.rb
3
+
4
+ RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5
+
6
+ module Rails
7
+ class << self
8
+ def boot!
9
+ unless booted?
10
+ preinitialize
11
+ pick_boot.run
12
+ end
13
+ end
14
+
15
+ def booted?
16
+ defined? Rails::Initializer
17
+ end
18
+
19
+ def pick_boot
20
+ (vendor_rails? ? VendorBoot : GemBoot).new
21
+ end
22
+
23
+ def vendor_rails?
24
+ File.exist?("#{RAILS_ROOT}/vendor/rails")
25
+ end
26
+
27
+ def preinitialize
28
+ load(preinitializer_path) if File.exist?(preinitializer_path)
29
+ end
30
+
31
+ def preinitializer_path
32
+ "#{RAILS_ROOT}/config/preinitializer.rb"
33
+ end
34
+ end
35
+
36
+ class Boot
37
+ def run
38
+ load_initializer
39
+ Rails::Initializer.run(:set_load_path)
40
+ end
41
+ end
42
+
43
+ class VendorBoot < Boot
44
+ def load_initializer
45
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
46
+ Rails::Initializer.run(:install_gem_spec_stubs)
47
+ Rails::GemDependency.add_frozen_gem_path
48
+ end
49
+ end
50
+
51
+ class GemBoot < Boot
52
+ def load_initializer
53
+ self.class.load_rubygems
54
+ load_rails_gem
55
+ require 'initializer'
56
+ end
57
+
58
+ def load_rails_gem
59
+ if version = self.class.gem_version
60
+ gem 'rails', version
61
+ else
62
+ gem 'rails'
63
+ end
64
+ rescue Gem::LoadError => load_error
65
+ $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
66
+ exit 1
67
+ end
68
+
69
+ class << self
70
+ def rubygems_version
71
+ Gem::RubyGemsVersion rescue nil
72
+ end
73
+
74
+ def gem_version
75
+ if defined? RAILS_GEM_VERSION
76
+ RAILS_GEM_VERSION
77
+ elsif ENV.include?('RAILS_GEM_VERSION')
78
+ ENV['RAILS_GEM_VERSION']
79
+ else
80
+ parse_gem_version(read_environment_rb)
81
+ end
82
+ end
83
+
84
+ def load_rubygems
85
+ min_version = '1.3.1'
86
+ require 'rubygems'
87
+ unless rubygems_version >= min_version
88
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
89
+ exit 1
90
+ end
91
+
92
+ rescue LoadError
93
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
94
+ exit 1
95
+ end
96
+
97
+ def parse_gem_version(text)
98
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
99
+ end
100
+
101
+ private
102
+ def read_environment_rb
103
+ File.read("#{RAILS_ROOT}/config/environment.rb")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # All that for this:
110
+ Rails.boot!
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+
3
+ Rails::Initializer.run do |config|
4
+ config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
5
+ config.action_controller.session = { :key=>"_myapp_session", :secret=>"Stay hungry. Stay foolish. -- Steve Jobs" }
6
+ config.after_initialize do
7
+ $:.unshift File.dirname(__FILE__) + "/../../../lib/"
8
+ require "vanity"
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect "/", :controller=>:main, :action=>:index
3
+ end
@@ -0,0 +1,43 @@
1
+ require "test/test_helper"
2
+ require "phusion_passenger/spawn_manager"
3
+
4
+ class PassengerTest < Test::Unit::TestCase
5
+ def setup
6
+ super
7
+ ActiveRecord::Base.connection.disconnect! # Otherwise AR metric tests fail
8
+ @original = Vanity.playground.connection
9
+ File.unlink "test/myapp/config/vanity.yml" rescue nil
10
+ File.open("test/myapp/config/vanity.yml", "w") do |io|
11
+ io.write YAML.dump({ "production"=>DATABASE })
12
+ end
13
+ @server = PhusionPassenger::SpawnManager.new
14
+ @server.start
15
+ Thread.pass until @server.started?
16
+ app_root = File.expand_path("myapp", File.dirname(__FILE__))
17
+ @app = @server.spawn_application "app_root"=>app_root, "spawn_method"=>"smart-lv2"
18
+ end
19
+
20
+ def test_reconnect
21
+ sleep 0.1
22
+ case @app.listen_socket_type
23
+ when "tcp" ; socket = TCPSocket.new(*@app.listen_socket_name.split(":"))
24
+ when "unix"; socket = UNIXSocket.new(@app.listen_socket_name)
25
+ else fail
26
+ end
27
+ channel = PhusionPassenger::MessageChannel.new(socket)
28
+ request = {"REQUEST_PATH"=>"/", "REQUEST_METHOD"=>"GET", "QUERY_STRING"=>" "}
29
+ channel.write_scalar request.to_a.join("\0")
30
+ response = socket.read.split("\r\n\r\n").last
31
+ socket.close
32
+ conn, obj_id = response.split("\n")
33
+ assert_equal @original.to_s, conn
34
+ assert_not_equal @original.object_id.to_s, obj_id
35
+ end
36
+
37
+ def teardown
38
+ super
39
+ @server.stop
40
+ File.unlink "test/myapp/config/vanity.yml"
41
+ end
42
+
43
+ end
@@ -0,0 +1,26 @@
1
+ require "test/test_helper"
2
+
3
+ class PlaygroundTest < Test::Unit::TestCase
4
+
5
+ def test_has_one_global_instance
6
+ assert instance = Vanity.playground
7
+ assert_equal instance, Vanity.playground
8
+ end
9
+
10
+ def test_be_use_js
11
+ assert !Vanity.playground.using_js?
12
+ Vanity.playground.use_js!
13
+ assert Vanity.playground.using_js?
14
+ end
15
+
16
+ def test_chooses_path_sets_default
17
+ assert_equal Vanity.playground.add_participant_path, Vanity::Playground::DEFAULT_ADD_PARTICIPANT_PATH
18
+ end
19
+
20
+ def test_reconnects_with_existing_connection
21
+ Vanity.playground.establish_connection "mock:/"
22
+ Vanity.playground.reconnect!
23
+ assert_equal Vanity.playground.connection.to_s, "mock:/"
24
+ end
25
+
26
+ end
@@ -0,0 +1,37 @@
1
+ require "test/test_helper"
2
+
3
+ class VanityController < ActionController::Base
4
+ include Vanity::Rails::Dashboard
5
+ end
6
+
7
+ # Pages accessible to everyone, e.g. sign in, community search.
8
+ class RailsDashboardTest < ActionController::TestCase
9
+ tests VanityController
10
+
11
+ def setup
12
+ Vanity.playground.collecting = true
13
+ metric :sugar_high
14
+ new_ab_test :food do
15
+ alternatives :apple, :orange
16
+ metrics :sugar_high
17
+ identify { '1' }
18
+ end
19
+ end
20
+
21
+ def test_add_participant
22
+ xhr :post, :add_participant, :e => "food", :a => 0
23
+ assert_response :success
24
+ assert @response.body.blank?
25
+ end
26
+
27
+ def test_add_participant_no_params
28
+ xhr :post, :add_participant
29
+ assert_response :not_found
30
+ assert @response.body.blank?
31
+ end
32
+
33
+ def test_chooses
34
+ xhr :post, :chooses, :e => "food", :a => 0
35
+ assert_response :success
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ require "test/test_helper"
2
+
3
+ class RailsHelperTest < ActionView::TestCase
4
+ include Vanity::Rails::Helpers
5
+
6
+ def setup
7
+ super
8
+ metric :sugar_high
9
+ new_ab_test :pie_or_cake do
10
+ metrics :sugar_high
11
+ identify { '1' }
12
+ alternatives :pie, :cake
13
+ end
14
+ end
15
+
16
+ def test_ab_test_returns_one_of_the_alternatives
17
+ assert [:pie, :cake].include?(ab_test(:pie_or_cake))
18
+ end
19
+
20
+ def test_ab_test_using_js_returns_the_same_alternative
21
+ Vanity.playground.use_js!
22
+ result = ab_test(:pie_or_cake)
23
+ assert [:pie, :cake].include?(result)
24
+ 10.times do
25
+ assert result == ab_test(:pie_or_cake)
26
+ end
27
+ end
28
+
29
+ def test_vanity_track_url_for_returns_url_with_identity_and_metrics
30
+ assert_equal vanity_track_url_for("123", :sugar_high, :controller => "controller", :action => "action"), "/controller/action?_identity=123&amp;_track=sugar_high"
31
+ end
32
+
33
+ def test_vanity_tracking_image
34
+ assert_equal vanity_tracking_image("123", :sugar_high, options = {}), image_tag("/vanity/image?_identity=123&amp;_track=sugar_high", :width => "1px", :height => "1px", :alt => "")
35
+ end
36
+ end
@@ -0,0 +1,389 @@
1
+ require "test/test_helper"
2
+
3
+ class UseVanityController < ActionController::Base
4
+ attr_accessor :current_user
5
+
6
+ def index
7
+ render :text=>ab_test(:pie_or_cake)
8
+ end
9
+ end
10
+
11
+ # Pages accessible to everyone, e.g. sign in, community search.
12
+ class UseVanityTest < ActionController::TestCase
13
+ tests UseVanityController
14
+
15
+ def setup
16
+ super
17
+ metric :sugar_high
18
+ new_ab_test :pie_or_cake do
19
+ metrics :sugar_high
20
+ end
21
+ UseVanityController.class_eval do
22
+ use_vanity :current_user
23
+ end
24
+ if ::Rails.respond_to?(:application) # Rails 3 configuration
25
+ ::Rails.application.config.session_options[:domain] = '.foo.bar'
26
+ end
27
+ end
28
+
29
+ def test_chooses_sets_alternatives_for_rails_tests
30
+ experiment(:pie_or_cake).chooses(true)
31
+ get :index
32
+ assert_equal 'true', @response.body
33
+
34
+ experiment(:pie_or_cake).chooses(false)
35
+ get :index
36
+ assert_equal 'false', @response.body
37
+ end
38
+
39
+
40
+ def test_vanity_cookie_is_persistent
41
+ get :index
42
+ assert cookie = @response["Set-Cookie"].find { |c| c[/^vanity_id=/] }
43
+ assert expires = cookie[/vanity_id=[a-f0-9]{32}; path=\/; expires=(.*)(;|$)/, 1]
44
+ assert_in_delta Time.parse(expires), Time.now + 1.month, 1.minute
45
+ end
46
+
47
+ def test_vanity_cookie_default_id
48
+ get :index
49
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
50
+ end
51
+
52
+ def test_vanity_cookie_retains_id
53
+ @request.cookies['vanity_id'] = "from_last_time"
54
+ get :index
55
+ assert_equal "from_last_time", cookies['vanity_id']
56
+ end
57
+
58
+ def test_vanity_identity_set_from_cookie
59
+ @request.cookies['vanity_id'] = "from_last_time"
60
+ get :index
61
+ assert_equal "from_last_time", @controller.send(:vanity_identity)
62
+ end
63
+
64
+ def test_vanity_identity_set_from_user
65
+ @controller.current_user = mock("user", :id=>"user_id")
66
+ get :index
67
+ assert_equal "user_id", @controller.send(:vanity_identity)
68
+ end
69
+
70
+ def test_vanity_identity_with_no_user_model
71
+ UseVanityController.class_eval do
72
+ use_vanity nil
73
+ end
74
+ @controller.current_user = Object.new
75
+ get :index
76
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
77
+ end
78
+
79
+ def test_vanity_identity_set_with_block
80
+ UseVanityController.class_eval do
81
+ attr_accessor :project_id
82
+ use_vanity { |controller| controller.project_id }
83
+ end
84
+ @controller.project_id = "576"
85
+ get :index
86
+ assert_equal "576", @controller.send(:vanity_identity)
87
+ end
88
+
89
+ def test_vanity_identity_set_with_indentity_paramater
90
+ get :index, :_identity => "id_from_params"
91
+ assert_equal "id_from_params", @controller.send(:vanity_identity)
92
+
93
+ @request.cookies['vanity_id'] = "old_id"
94
+ get :index, :_identity => "id_from_params"
95
+ assert_equal "id_from_params", @controller.send(:vanity_identity)
96
+ assert cookies['vanity_id'], "id_from_params"
97
+ end
98
+
99
+ # query parameter filter
100
+
101
+ def test_redirects_and_loses_vanity_query_parameter
102
+ get :index, :foo=>"bar", :_vanity=>"567"
103
+ assert_redirected_to "/use_vanity?foo=bar"
104
+ end
105
+
106
+ def test_sets_choices_from_vanity_query_parameter
107
+ first = experiment(:pie_or_cake).alternatives.first
108
+ fingerprint = experiment(:pie_or_cake).fingerprint(first)
109
+ 10.times do
110
+ @controller = nil ; setup_controller_request_and_response
111
+ get :index, :_vanity => fingerprint
112
+ assert_equal experiment(:pie_or_cake).choose, experiment(:pie_or_cake).alternatives.first
113
+ assert experiment(:pie_or_cake).showing?(first)
114
+ end
115
+ end
116
+
117
+ def test_does_nothing_with_vanity_query_parameter_for_posts
118
+ experiment(:pie_or_cake).chooses(experiment(:pie_or_cake).alternatives.last.value)
119
+ first = experiment(:pie_or_cake).alternatives.first
120
+ fingerprint = experiment(:pie_or_cake).fingerprint(first)
121
+ post :index, :foo => "bar", :_vanity => fingerprint
122
+ assert_response :success
123
+ assert !experiment(:pie_or_cake).showing?(first)
124
+ end
125
+
126
+ def test_track_param_tracks_a_metric
127
+ get :index, :_identity => "123", :_track => "sugar_high"
128
+ assert_equal experiment(:pie_or_cake).alternatives[0].converted, 1
129
+ end
130
+
131
+ def test_cookie_domain_from_rails_configuration
132
+ get :index
133
+ assert_equal cookies["vanity_id"][:domain], '.foo.bar' if ::Rails.respond_to?(:application)
134
+ end
135
+
136
+ # -- Load path --
137
+
138
+ def test_load_path
139
+ assert_equal File.expand_path("tmp/experiments"), load_rails(<<-RB)
140
+ initializer.after_initialize
141
+ $stdout << Vanity.playground.load_path
142
+ RB
143
+ end
144
+
145
+ def test_settable_load_path
146
+ assert_equal File.expand_path("tmp/predictions"), load_rails(<<-RB)
147
+ Vanity.playground.load_path = "predictions"
148
+ initializer.after_initialize
149
+ $stdout << Vanity.playground.load_path
150
+ RB
151
+ end
152
+
153
+ def test_absolute_load_path
154
+ assert_equal File.expand_path("/tmp/var"), load_rails(<<-RB)
155
+ Vanity.playground.load_path = "/tmp/var"
156
+ initializer.after_initialize
157
+ $stdout << Vanity.playground.load_path
158
+ RB
159
+ end
160
+
161
+
162
+ # -- Connection configuration --
163
+
164
+ def test_default_connection
165
+ assert_equal "redis://127.0.0.1:6379/0", load_rails(<<-RB)
166
+ initializer.after_initialize
167
+ $stdout << Vanity.playground.connection
168
+ RB
169
+ end
170
+
171
+ def test_connection_from_string
172
+ assert_equal "redis://192.168.1.1:6379/5", load_rails(<<-RB)
173
+ Vanity.playground.establish_connection "redis://192.168.1.1:6379/5"
174
+ initializer.after_initialize
175
+ $stdout << Vanity.playground.connection
176
+ RB
177
+ end
178
+
179
+ def test_connection_from_yaml
180
+ FileUtils.mkpath "tmp/config"
181
+ ENV["RAILS_ENV"] = "production"
182
+ File.open("tmp/config/vanity.yml", "w") do |io|
183
+ io.write <<-YML
184
+ production:
185
+ adapter: redis
186
+ host: somehost
187
+ database: 15
188
+ YML
189
+ end
190
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
191
+ initializer.after_initialize
192
+ $stdout << Vanity.playground.connection
193
+ RB
194
+ ensure
195
+ File.unlink "tmp/config/vanity.yml"
196
+ end
197
+
198
+ def test_mongo_connection_from_yaml
199
+ FileUtils.mkpath "tmp/config"
200
+ File.open("tmp/config/vanity.yml", "w") do |io|
201
+ io.write <<-YML
202
+ mongodb:
203
+ adapter: mongodb
204
+ host: localhost
205
+ port: 27017
206
+ database: vanity_test
207
+ YML
208
+ end
209
+
210
+ assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB, "mongodb")
211
+ initializer.after_initialize
212
+ $stdout << Vanity.playground.connection
213
+ RB
214
+ ensure
215
+ File.unlink "tmp/config/vanity.yml"
216
+ end
217
+
218
+ def test_mongodb_replica_set_connection
219
+ FileUtils.mkpath "tmp/config"
220
+ File.open("tmp/config/vanity.yml", "w") do |io|
221
+ io.write <<-YML
222
+ mongodb:
223
+ adapter: mongodb
224
+ hosts:
225
+ - localhost
226
+ port: 27017
227
+ database: vanity_test
228
+ YML
229
+ end
230
+
231
+ assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB, "mongodb")
232
+ initializer.after_initialize
233
+ $stdout << Vanity.playground.connection
234
+ RB
235
+
236
+ assert_equal "Mongo::ReplSetConnection", load_rails(<<-RB, "mongodb")
237
+ initializer.after_initialize
238
+ $stdout << Vanity.playground.connection.mongo.class
239
+ RB
240
+ ensure
241
+ File.unlink "tmp/config/vanity.yml"
242
+ end
243
+
244
+ def test_connection_from_yaml_url
245
+ FileUtils.mkpath "tmp/config"
246
+ ENV["RAILS_ENV"] = "production"
247
+ File.open("tmp/config/vanity.yml", "w") do |io|
248
+ io.write <<-YML
249
+ production: redis://somehost/15
250
+ YML
251
+ end
252
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
253
+ initializer.after_initialize
254
+ $stdout << Vanity.playground.connection
255
+ RB
256
+ ensure
257
+ File.unlink "tmp/config/vanity.yml"
258
+ end
259
+
260
+ def test_connection_from_yaml_missing
261
+ FileUtils.mkpath "tmp/config"
262
+ File.open("tmp/config/vanity.yml", "w") do |io|
263
+ io.write <<-YML
264
+ production:
265
+ adapter: redis
266
+ YML
267
+ end
268
+ assert_equal "No configuration for development", load_rails(<<-RB, "development")
269
+ initializer.after_initialize
270
+ $stdout << (Vanity.playground.connection rescue $!.message)
271
+ RB
272
+ ensure
273
+ File.unlink "tmp/config/vanity.yml"
274
+ end
275
+
276
+ def test_connection_from_yaml_with_erb
277
+ FileUtils.mkpath "tmp/config"
278
+ ENV["RAILS_ENV"] = "production"
279
+ # Pass storage URL through environment like heroku does
280
+ ENV["REDIS_URL"] = "redis://somehost:6379/15"
281
+ File.open("tmp/config/vanity.yml", "w") do |io|
282
+ io.write <<-YML
283
+ production: <%= ENV['REDIS_URL'] %>
284
+ YML
285
+ end
286
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
287
+ initializer.after_initialize
288
+ $stdout << Vanity.playground.connection
289
+ RB
290
+ ensure
291
+ File.unlink "tmp/config/vanity.yml"
292
+ end
293
+
294
+ def test_connection_from_redis_yml
295
+ FileUtils.mkpath "tmp/config"
296
+ yml = File.open("tmp/config/redis.yml", "w")
297
+ yml << "production: internal.local:6379\n"
298
+ yml.flush
299
+ assert_equal "redis://internal.local:6379/0", load_rails(<<-RB)
300
+ initializer.after_initialize
301
+ $stdout << Vanity.playground.connection
302
+ RB
303
+ ensure
304
+ File.unlink yml.path
305
+ end
306
+
307
+ def test_collection_from_vanity_yaml
308
+ FileUtils.mkpath "tmp/config"
309
+ File.open("tmp/config/vanity.yml", "w") do |io|
310
+ io.write <<-YML
311
+ production:
312
+ collecting: false
313
+ YML
314
+ end
315
+ assert_equal "false", load_rails(<<-RB)
316
+ initializer.after_initialize
317
+ $stdout << Vanity.playground.collecting?
318
+ RB
319
+ ensure
320
+ File.unlink "tmp/config/vanity.yml"
321
+ end
322
+
323
+ def test_collection_true_in_production_by_default
324
+ assert_equal "true", load_rails(<<-RB, "production")
325
+ initializer.after_initialize
326
+ $stdout << Vanity.playground.collecting?
327
+ RB
328
+ end
329
+
330
+ def test_collection_false_in_production_when_configured
331
+ assert_equal "false", load_rails(<<-RB, "production")
332
+ Vanity.playground.collecting = false
333
+ initializer.after_initialize
334
+ $stdout << Vanity.playground.collecting?
335
+ RB
336
+ end
337
+
338
+ def test_collection_false_in_development_by_default
339
+ assert_equal "false", load_rails(<<-RB, "development")
340
+ initializer.after_initialize
341
+ $stdout << Vanity.playground.collecting?
342
+ RB
343
+ end
344
+
345
+ def test_collection_true_in_development_when_configured
346
+ assert_equal "true", load_rails(<<-RB, "development")
347
+ Vanity.playground.collecting = true
348
+ initializer.after_initialize
349
+ $stdout << Vanity.playground.collecting?
350
+ RB
351
+ end
352
+
353
+ def test_collection_false_after_test!
354
+ assert_equal "false", load_rails(<<-RB, "production")
355
+ initializer.after_initialize
356
+ Vanity.playground.test!
357
+ $stdout << Vanity.playground.collecting?
358
+ RB
359
+ end
360
+
361
+ def load_rails(code, env = "production")
362
+ tmp = Tempfile.open("test.rb")
363
+ tmp.write <<-RB
364
+ $:.delete_if { |path| path[/gems\\/vanity-\\d/] }
365
+ $:.unshift File.expand_path("../lib")
366
+ RAILS_ROOT = File.expand_path(".")
367
+ RAILS_ENV = ENV['RACK_ENV'] = "#{env}"
368
+ require "initializer"
369
+ require "active_support"
370
+ Rails.configuration = Rails::Configuration.new
371
+ initializer = Rails::Initializer.new(Rails.configuration)
372
+ initializer.check_gem_dependencies
373
+ require "vanity"
374
+ RB
375
+ tmp.write code
376
+ tmp.flush
377
+ Dir.chdir "tmp" do
378
+ open("|ruby #{tmp.path}").read
379
+ end
380
+ rescue
381
+ tmp.close!
382
+ end
383
+
384
+
385
+ def teardown
386
+ super
387
+ UseVanityController.send(:filter_chain).clear
388
+ end
389
+ end