vanity 2.0.0.beta3 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vanity (2.0.0.beta3)
4
+ vanity (2.0.0.beta4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/bin/vanity CHANGED
@@ -16,7 +16,6 @@ opts = OptionParser.new("", 24, " ") do |opts|
16
16
  opts.banner << "Commands:\n"
17
17
  opts.banner << " list List all experiments and metrics\n"
18
18
  opts.banner << " report Report on all running experiments/metrics\n"
19
- opts.banner << " upgrade Upgrade your database when deploying new release\n"
20
19
 
21
20
  opts.separator ""
22
21
  opts.separator "Reporting options:"
@@ -29,13 +28,9 @@ opts = OptionParser.new("", 24, " ") do |opts|
29
28
  opts.on "--load_path PATH", "Path to experiments directory (default: #{playground.load_path})" do |path|
30
29
  playground.load_path = path
31
30
  end
32
- opts.on "-d", "--database url", "Database connection URL (e.g. redis:/localhost:6379)" do |conn|
31
+ opts.on "-d", "--database url", "Database connection URL (e.g. redis://localhost:6379)" do |conn|
33
32
  playground.establish_connection conn
34
33
  end
35
- opts.on "--redis HOST:PORT:DB", "DEPRECATED: Redis server host (default: localhost:6379)" do |redis|
36
- host, port, db = redis.split(":")
37
- playground.establish_connection "redis:/#{host}:#{port}/#{db}"
38
- end
39
34
  opts.on_tail "-h", "--help", "Show this message" do
40
35
  puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
41
36
  exit
@@ -60,9 +55,6 @@ ARGV.each do |cmd|
60
55
  when "list"
61
56
  require "vanity/commands/list"
62
57
  Vanity::Commands.list
63
- when "upgrade"
64
- require "vanity/commands/upgrade"
65
- Vanity::Commands.upgrade
66
58
  else puts "No such command: #{cmd}"
67
59
  end
68
60
  end
@@ -15,7 +15,7 @@
15
15
  </div>
16
16
  <div id="links">
17
17
  <a href="http://github.com/assaf/vanity">Source code</a> |
18
- <a href="http://groups.google.com/group/vanity-talk" title="vanity-talk google group">Google Group</a> |
18
+ <a href="http://stackoverflow.com/questions/tagged/vanity" title="stackoverflow vanity tag">StackOverflow Tag</a> |
19
19
  <a href="http://rdoc.info/gems/vanity">API reference</a>
20
20
  </div>
21
21
  <div id="sidebar">
@@ -15,7 +15,7 @@ By all means.
15
15
 
16
16
  h3(#contributing). How To Contribute
17
17
 
18
- Pick on an "open issue":http://github.com/assaf/vanity/issues, "experimental feature":experimental.html, suggestion from the "Google Group":http://groups.google.com/group/vanity-talk, or whatever you feel like contributing.
18
+ Pick on an "open issue":http://github.com/assaf/vanity/issues, "experimental feature":experimental.html, or whatever you feel like contributing.
19
19
 
20
20
  To contribute new code/changes:
21
21
  # "Fork the project":http://github.com/assaf/vanity
@@ -68,7 +68,7 @@ h3(#doc). Documentation
68
68
 
69
69
  Documentation is written in "Textile":http://redcloth.org/textile/writing-paragraph-text/, and converted to HTML using "Jekyll":http://jekyllrb.com/.
70
70
 
71
- API reference is "RDoc":http://rdoc.sourceforge.net/doc/index.html, converted to HTML using "Yardoc":http://yardoc.org/.
71
+ API reference is "RDoc":http://rdoc.sourceforge.net/doc/index.html, converted to HTML using "Yardoc":http://yardoc.org/.
72
72
 
73
73
  To build and view documentation:
74
74
 
data/doc/index.textile CHANGED
@@ -21,7 +21,7 @@ Also:
21
21
  * "Experiment Driven Development(Introduction to EDD and Vanity)":http://blog.labnotes.org/2009/11/19/vanity-experiment-driven-development-for-rails/
22
22
  * "Get the code(Official Github repository)":http://github.com/assaf/vanity
23
23
  * "API reference":api/index.html
24
- * "Join vanity-talk list":http://groups.google.com/group/vanity-talk
24
+ * "Ask questions on StackOverflow":http://stackoverflow.com/questions/tagged/vanity
25
25
  * "Contributing to Vanity":contributing.html
26
26
 
27
27
  h3(#intro). Introduction & setup
@@ -7,7 +7,7 @@ GIT
7
7
  PATH
8
8
  remote: ..
9
9
  specs:
10
- vanity (2.0.0.beta3)
10
+ vanity (2.0.0.beta4)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
@@ -7,7 +7,7 @@ GIT
7
7
  PATH
8
8
  remote: ..
9
9
  specs:
10
- vanity (2.0.0.beta3)
10
+ vanity (2.0.0.beta4)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
@@ -25,14 +25,6 @@ module Vanity
25
25
  send :"find_or_create_by_#{method}", value
26
26
  end
27
27
  end
28
-
29
- def self.rails_agnostic_find_first(conditions)
30
- if respond_to? :where
31
- where(conditions).first
32
- else
33
- find(:first, :conditions => conditions)
34
- end
35
- end
36
28
  end
37
29
 
38
30
  # Schema model
@@ -103,7 +95,7 @@ module Vanity
103
95
  # passed then this will be passed to create if creating, or will be
104
96
  # used to update the found participant.
105
97
  def self.retrieve(experiment, identity, create = true, update_with = nil)
106
- if record = VanityParticipant.rails_agnostic_find_first(:experiment_id=>experiment.to_s, :identity=>identity.to_s)
98
+ if record = VanityParticipant.where(:experiment_id=>experiment.to_s, :identity=>identity.to_s).first
107
99
  record.update_attributes(update_with) if update_with
108
100
  elsif create
109
101
  record = VanityParticipant.create({ :experiment_id=>experiment.to_s, :identity=>identity.to_s }.merge(update_with || {}))
@@ -220,7 +212,7 @@ module Vanity
220
212
  record = VanityExperiment.retrieve(experiment)
221
213
  participants = VanityParticipant.where(:experiment_id => experiment.to_s, :seen => alternative).count
222
214
  converted = VanityParticipant.where(:experiment_id => experiment.to_s, :converted => alternative).count
223
- conversions = record.vanity_conversions.sum(:conversions, :conditions => {:alternative => alternative})
215
+ conversions = record.vanity_conversions.where(:alternative => alternative).sum(:conversions)
224
216
 
225
217
  {
226
218
  :participants => participants,
@@ -39,15 +39,19 @@ module Vanity
39
39
  class_or_scope = class_or_scope.constantize if class_or_scope.is_a?(String)
40
40
  options = options || {}
41
41
  conditions = options.delete(:conditions)
42
- @ar_scoped = conditions ? class_or_scope.scoped(:conditions=>conditions) : class_or_scope
42
+
43
+ @ar_scoped = conditions ? class_or_scope.where(conditions) : class_or_scope
43
44
  @ar_aggregate = AGGREGATES.find { |key| options.has_key?(key) }
44
45
  @ar_column = options.delete(@ar_aggregate)
45
46
  fail "Cannot use multiple aggregates in a single metric" if AGGREGATES.find { |key| options.has_key?(key) }
47
+
46
48
  @ar_timestamp = options.delete(:timestamp) || :created_at
47
49
  @ar_timestamp, @ar_timestamp_table = @ar_timestamp.to_s.split('.').reverse
48
50
  @ar_timestamp_table ||= @ar_scoped.table_name
51
+
49
52
  fail "Unrecognized options: #{options.keys * ", "}" unless options.empty?
50
- @ar_scoped.after_create self
53
+
54
+ @ar_scoped.after_create(self)
51
55
  extend ActiveRecord
52
56
  end
53
57
  end
@@ -65,9 +69,16 @@ module Vanity
65
69
  sdate = sdate + difference
66
70
  edate = edate + difference
67
71
 
68
- query = { :conditions=> { @ar_timestamp_table => { @ar_timestamp => (sdate.to_time...(edate + 1).to_time) } },
69
- :group=>"date(#{@ar_scoped.quoted_table_name}.#{@ar_scoped.connection.quote_column_name @ar_timestamp})" }
70
- grouped = @ar_column ? @ar_scoped.send(@ar_aggregate, @ar_column, query) : @ar_scoped.count(query)
72
+ grouped = @ar_scoped
73
+ .where(@ar_timestamp_table => { @ar_timestamp => (sdate.to_time...(edate + 1).to_time) })
74
+ .group("date(#{@ar_scoped.quoted_table_name}.#{@ar_scoped.connection.quote_column_name(@ar_timestamp)})")
75
+
76
+ if @ar_column
77
+ grouped = grouped.send(@ar_aggregate, @ar_column)
78
+ else
79
+ grouped = grouped.count
80
+ end
81
+
71
82
  grouped = Hash[grouped.map {|k,v| [k.to_date, v] }]
72
83
  (sdate..edate).inject([]) { |ordered, date| ordered << (grouped[date] || 0) }
73
84
  end
@@ -79,6 +90,7 @@ module Vanity
79
90
  end
80
91
 
81
92
  def last_update_at
93
+ # SELECT created_at FROM "skies" ORDER BY created_at DESC LIMIT 1
82
94
  record = @ar_scoped.find(:first, :order=>"#@ar_timestamp DESC", :limit=>1, :select=>@ar_timestamp)
83
95
  record && record.send(@ar_timestamp)
84
96
  end
@@ -1,5 +1,5 @@
1
1
  module Vanity
2
- VERSION = "2.0.0.beta3"
2
+ VERSION = "2.0.0.beta4"
3
3
 
4
4
  module Version
5
5
  version = VERSION.to_s.split(".").map { |i| i.to_i }
data/test/cli_test.rb CHANGED
@@ -37,10 +37,10 @@ describe "bin/vanity" do
37
37
  end
38
38
 
39
39
  it "responds to unknown commands" do
40
- require "vanity/commands/upgrade"
41
- Vanity::Commands.expects(:upgrade)
42
- ARGV.clear
43
- ARGV << 'upgrade'
44
- load "bin/vanity"
40
+ assert_output("No such command: upgrade\n") do
41
+ ARGV.clear
42
+ ARGV << 'upgrade'
43
+ load "bin/vanity"
44
+ end
45
45
  end
46
46
  end
@@ -5,3 +5,4 @@
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
7
  Dummy::Application.config.secret_token = '33ccbc9a29f3b02e87c08904505b1c9a3a1e97dd01f02e598e65ee9e7b96fff2ca4a6d0dd7c4a8d3682d8c64f84d372661e141264e70697dc576c722c72d80d0'
8
+ Dummy::Application.config.secret_key_base = 'secret' if Dummy::Application.config.respond_to?(:secret_key_base=)
@@ -1,23 +1,22 @@
1
1
  require "test_helper"
2
2
 
3
3
  class Sky < ActiveRecord::Base
4
- if connected?
5
- connection.drop_table :skies if table_exists?
6
- connection.create_table :skies do |t|
4
+ scope :high, lambda { where("height >= 4") }
5
+ end
6
+
7
+ if ENV["DB"] == "active_record"
8
+
9
+ describe Vanity::Metric::ActiveRecord do
10
+
11
+ before do
12
+ Sky.connection.create_table(:skies) do |t|
7
13
  t.integer :height
8
14
  t.timestamps
9
15
  end
10
16
  end
11
17
 
12
- scope :high, lambda { { :conditions=>"height >= 4" } }
13
- end
14
-
15
- if ActiveRecord::Base.connected?
16
-
17
- describe "ActiveRecord Metric" do
18
-
19
18
  after do
20
- Sky.delete_all
19
+ Sky.connection.drop_table(:skies) if Sky.connection.table_exists?(Sky.table_name)
21
20
  Sky.reset_callbacks(:create)
22
21
  Sky.reset_callbacks(:save)
23
22
  end
@@ -236,7 +235,7 @@ describe "ActiveRecord Metric" do
236
235
  assert_equal 2, times
237
236
  end
238
237
 
239
- it "do it youself" do
238
+ it "do it yourself" do
240
239
  File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
241
240
  f.write <<-RUBY
242
241
  metric "Sky is limit" do
@@ -49,13 +49,15 @@ describe Vanity::Playground do
49
49
  end
50
50
  end
51
51
 
52
- describe "autoconnect" do
53
- it "reconnects with existing connection" do
52
+ describe "reconnect!" do
53
+ it "reconnects with the same configuration" do
54
54
  Vanity.playground.establish_connection "mock:/"
55
55
  Vanity.playground.reconnect!
56
56
  assert_equal Vanity.playground.connection.to_s, "mock:/"
57
57
  end
58
+ end
58
59
 
60
+ describe "autoconnect" do
59
61
  it "establishes connection by default with connection" do
60
62
  instance = Vanity::Playground.new(:connection=>"mock:/")
61
63
  assert instance.connected?
data/test/test_helper.rb CHANGED
@@ -70,7 +70,7 @@ module VanityTestHelpers
70
70
  # or reload an experiment (saved by the previous playground).
71
71
  def new_playground
72
72
  Vanity.playground = Vanity::Playground.new(:logger=>$logger, :load_path=>"tmp/experiments")
73
- Vanity.playground.establish_connection(DATABASE)
73
+ Vanity.playground.establish_connection(DATABASE) unless Vanity.playground.connected?
74
74
  end
75
75
 
76
76
  # Defines the specified metrics (one or more names). Returns metric, or array
@@ -107,7 +107,7 @@ module VanityTestHelpers
107
107
  end
108
108
 
109
109
  def dummy_request
110
- defined?(ActionDispatch) ? ActionDispatch::TestRequest.new() : ActionController::TestRequest.new()
110
+ ActionDispatch::TestRequest.new()
111
111
  end
112
112
 
113
113
  # Defining setup/tear down in a module and including it below doesn't
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vanity
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta3
4
+ version: 2.0.0.beta4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-19 00:00:00.000000000 Z
12
+ date: 2014-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -104,7 +104,6 @@ files:
104
104
  - lib/vanity/backport.rb
105
105
  - lib/vanity/commands/list.rb
106
106
  - lib/vanity/commands/report.rb
107
- - lib/vanity/commands/upgrade.rb
108
107
  - lib/vanity/experiment/ab_test.rb
109
108
  - lib/vanity/experiment/alternative.rb
110
109
  - lib/vanity/experiment/base.rb
@@ -163,11 +162,6 @@ files:
163
162
  - test/dummy/script/rails
164
163
  - test/experiment/ab_test.rb
165
164
  - test/experiment/base_test.rb
166
- - test/experiments/age_and_zipcode.rb
167
- - test/experiments/metrics/cheers.rb
168
- - test/experiments/metrics/signups.rb
169
- - test/experiments/metrics/yawns.rb
170
- - test/experiments/null_abc.rb
171
165
  - test/frameworks/rails/action_controller_test.rb
172
166
  - test/frameworks/rails/action_mailer_test.rb
173
167
  - test/frameworks/rails/action_view_test.rb
@@ -187,7 +181,7 @@ licenses:
187
181
  post_install_message: To get started run vanity --help
188
182
  rdoc_options:
189
183
  - --title
190
- - Vanity 2.0.0.beta3
184
+ - Vanity 2.0.0.beta4
191
185
  - --main
192
186
  - README.rdoc
193
187
  - --webcvs
@@ -244,11 +238,6 @@ test_files:
244
238
  - test/dummy/script/rails
245
239
  - test/experiment/ab_test.rb
246
240
  - test/experiment/base_test.rb
247
- - test/experiments/age_and_zipcode.rb
248
- - test/experiments/metrics/cheers.rb
249
- - test/experiments/metrics/signups.rb
250
- - test/experiments/metrics/yawns.rb
251
- - test/experiments/null_abc.rb
252
241
  - test/frameworks/rails/action_controller_test.rb
253
242
  - test/frameworks/rails/action_mailer_test.rb
254
243
  - test/frameworks/rails/action_view_test.rb
@@ -1,34 +0,0 @@
1
- module Vanity
2
- module Commands
3
- class << self
4
- # Upgrade to newer version of Vanity (this usually means doing magic in
5
- # the database)
6
- def upgrade
7
- if Vanity.playground.connection.respond_to?(:redis)
8
- redis = Vanity.playground.connection.redis
9
- # Upgrade metrics from 1.3 to 1.4
10
- keys = redis.keys("metrics:*")
11
- if keys.empty?
12
- puts "No metrics to upgrade"
13
- else
14
- puts "Updating #{keys.map { |name| name.split(":")[1] }.uniq.length} metrics"
15
- keys.each do |key|
16
- key << ":value:0" if key[/\d{4}-\d{2}-\d{2}$/]
17
- redis.renamenx key, "vanity:#{key}"
18
- end
19
- end
20
- # Upgrade experiments from 1.3 to 1.4
21
- keys = redis.keys("vanity:1:*")
22
- if keys.empty?
23
- puts "No experiments to upgrade"
24
- else
25
- puts "Updating #{keys.map { |name| name.split(":")[2] }.uniq.length} experiments"
26
- keys.each do |key|
27
- redis.renamenx key, key.gsub(":1:", ":experiments:")
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,19 +0,0 @@
1
- ab_test "Age and Zipcode" do
2
- description <<-TEXT
3
- Testing new registration form that asks for age and zipcode. Option A presents
4
- the existing form, and option B adds age and zipcode fields.
5
-
6
- We know option B will convert less, but higher quality leads. If we lose less
7
- than 20% conversions, we're going to switch to option B.
8
- TEXT
9
- metrics :signups
10
-
11
- complete_if do
12
- alternatives.all? { |alt| alt.participants > 100 }
13
- end
14
- outcome_is do
15
- one_field = alternative(false)
16
- three_fields = alternative(true)
17
- three_fields.conversion_rate >= 0.8 * one_field.conversion_rate ? three_fields : one_field
18
- end
19
- end
@@ -1,3 +0,0 @@
1
- metric "Cheers" do
2
- description "They love us, don't they?"
3
- end
@@ -1,2 +0,0 @@
1
- metric "Signups" do
2
- end
@@ -1,3 +0,0 @@
1
- metric "Yawns" do
2
- description "How many yawns/sec can our video-sharing micro-blogging social network elicit?"
3
- end
@@ -1,5 +0,0 @@
1
- ab_test "Null/ABC" do
2
- description "Testing three alternatives"
3
- alternatives nil, :red, :green, :blue
4
- metrics :signups
5
- end