vanity 1.4.0 → 1.5.0.beta
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.
- data/CHANGELOG +19 -0
- data/Gemfile +2 -2
- data/README.rdoc +8 -27
- data/Rakefile +6 -3
- data/lib/vanity.rb +4 -10
- data/lib/vanity/adapters/active_record_adapter.rb +304 -0
- data/lib/vanity/adapters/{mongo_adapter.rb → mongodb_adapter.rb} +3 -3
- data/lib/vanity/adapters/redis_adapter.rb +1 -1
- data/lib/vanity/commands/report.rb +7 -3
- data/lib/vanity/experiment/base.rb +3 -2
- data/lib/vanity/frameworks/rails.rb +51 -25
- data/lib/vanity/metric/active_record.rb +1 -1
- data/lib/vanity/playground.rb +9 -7
- data/lib/vanity/templates/_ab_test.erb +1 -1
- data/lib/vanity/templates/_experiment.erb +2 -2
- data/lib/vanity/templates/_experiments.erb +1 -1
- data/lib/vanity/templates/_metric.erb +6 -6
- data/lib/vanity/templates/_metrics.erb +3 -2
- data/lib/vanity/templates/_report.erb +6 -6
- data/lib/vanity/version.rb +11 -0
- data/test/metric/active_record_test.rb +2 -6
- data/test/myapp/log/production.log +265 -0
- data/test/rails_test.rb +36 -2
- data/test/test_helper.rb +8 -31
- data/vanity.gemspec +5 -2
- metadata +16 -11
@@ -18,7 +18,7 @@ module Vanity
|
|
18
18
|
def initialize(options)
|
19
19
|
@mongo = Mongo::Connection.new(options[:host], options[:port], :connect=>false)
|
20
20
|
@options = options.clone
|
21
|
-
@options[:database] ||= (@options[:path] && @options[:path].split("/")[1])
|
21
|
+
@options[:database] ||= (@options[:path] && @options[:path].split("/")[1]) || "vanity"
|
22
22
|
connect!
|
23
23
|
end
|
24
24
|
|
@@ -38,7 +38,7 @@ module Vanity
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def connect!
|
41
|
-
@mongo.
|
41
|
+
@mongo.connect
|
42
42
|
database = @mongo.db(@options[:database])
|
43
43
|
database.authenticate @options[:username], @options[:password], true if @options[:username]
|
44
44
|
@metrics = database.collection("vanity.metrics")
|
@@ -49,7 +49,7 @@ module Vanity
|
|
49
49
|
|
50
50
|
def to_s
|
51
51
|
userinfo = @options.values_at(:username, :password).join(":") if @options[:username]
|
52
|
-
URI::Generic.build(:scheme=>"
|
52
|
+
URI::Generic.build(:scheme=>"mongodb", :userinfo=>userinfo, :host=>@options[:host], :port=>@options[:port], :path=>"/#{@options[:database]}").to_s
|
53
53
|
end
|
54
54
|
|
55
55
|
def flushdb
|
@@ -16,7 +16,7 @@ module Vanity
|
|
16
16
|
class RedisAdapter < AbstractAdapter
|
17
17
|
def initialize(options)
|
18
18
|
@options = options.clone
|
19
|
-
@options[:db]
|
19
|
+
@options[:db] ||= @options[:database] || (@options[:path] && @options[:path].split("/")[1].to_i)
|
20
20
|
@options[:thread_safe] = true
|
21
21
|
connect!
|
22
22
|
end
|
@@ -22,12 +22,16 @@ module Vanity
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Escape HTML.
|
25
|
-
def
|
26
|
-
CGI.escapeHTML(html)
|
25
|
+
def vanity_h(html)
|
26
|
+
CGI.escapeHTML(html.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def vanity_html_safe(text)
|
30
|
+
text
|
27
31
|
end
|
28
32
|
|
29
33
|
# Dumbed down from Rails' simple_format.
|
30
|
-
def
|
34
|
+
def vanity_simple_format(text, options={})
|
31
35
|
open = "<p #{options.map { |k,v| "#{k}=\"#{CGI.escapeHTML v}\"" }.join(" ")}>"
|
32
36
|
text = open + text.gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
|
33
37
|
gsub(/\n\n+/, "</p>\n\n#{open}"). # 2+ newline -> paragraph
|
@@ -81,7 +81,9 @@ module Vanity
|
|
81
81
|
attr_reader :id
|
82
82
|
|
83
83
|
# Time stamp when experiment was created.
|
84
|
-
|
84
|
+
def created_at
|
85
|
+
@created_at ||= connection.get_experiment_created_at(@id)
|
86
|
+
end
|
85
87
|
|
86
88
|
# Time stamp when experiment was completed.
|
87
89
|
attr_reader :completed_at
|
@@ -166,7 +168,6 @@ module Vanity
|
|
166
168
|
def save
|
167
169
|
return unless @playground.collecting?
|
168
170
|
connection.set_experiment_created_at @id, Time.now
|
169
|
-
@created_at = connection.get_experiment_created_at(@id)
|
170
171
|
end
|
171
172
|
|
172
173
|
protected
|
@@ -1,5 +1,16 @@
|
|
1
1
|
module Vanity
|
2
2
|
module Rails #:nodoc:
|
3
|
+
def self.load!
|
4
|
+
Vanity.playground.load_path = ::Rails.root + Vanity.playground.load_path
|
5
|
+
Vanity.playground.logger ||= Rails.logger
|
6
|
+
|
7
|
+
# Do this at the very end of initialization, allowing you to change
|
8
|
+
# connection adapter, turn collection on/off, etc.
|
9
|
+
::Rails.configuration.after_initialize do
|
10
|
+
Vanity.playground.load!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
3
14
|
# The use_vanity method will setup the controller to allow testing and
|
4
15
|
# tracking of the current user.
|
5
16
|
module UseVanity
|
@@ -7,7 +18,7 @@ module Vanity
|
|
7
18
|
#
|
8
19
|
# Call with the name of a method that returns an object whose identity
|
9
20
|
# will be used as the Vanity identity. Confusing? Let's try by example:
|
10
|
-
#
|
21
|
+
#
|
11
22
|
# class ApplicationController < ActionController::Base
|
12
23
|
# use_vanity :current_user
|
13
24
|
#
|
@@ -15,7 +26,7 @@ module Vanity
|
|
15
26
|
# User.find(session[:user_id])
|
16
27
|
# end
|
17
28
|
# end
|
18
|
-
#
|
29
|
+
#
|
19
30
|
# If that method (current_user in this example) returns nil, Vanity will
|
20
31
|
# set the identity for you (using a cookie to remember it across
|
21
32
|
# requests). It also uses this mechanism if you don't provide an
|
@@ -69,7 +80,7 @@ module Vanity
|
|
69
80
|
# intercepted, the alternative is chosen, and the user redirected to the
|
70
81
|
# same request URL sans _vanity parameter. This only works for GET
|
71
82
|
# requests.
|
72
|
-
#
|
83
|
+
#
|
73
84
|
# For example, if the user requests the page
|
74
85
|
# http://example.com/?_vanity=2907dac4de, the first alternative of the
|
75
86
|
# :null_abc experiment is chosen and the user redirected to
|
@@ -80,7 +91,7 @@ module Vanity
|
|
80
91
|
Vanity.playground.experiments.each do |id, experiment|
|
81
92
|
if experiment.respond_to?(:alternatives)
|
82
93
|
experiment.alternatives.each do |alt|
|
83
|
-
if hash = hashes.delete(experiment.fingerprint(alt))
|
94
|
+
if hash = hashes.delete(experiment.fingerprint(alt))
|
84
95
|
experiment.chooses alt.value
|
85
96
|
break
|
86
97
|
end
|
@@ -120,11 +131,11 @@ module Vanity
|
|
120
131
|
# def index
|
121
132
|
# render action: ab_test(:new_page)
|
122
133
|
# end
|
123
|
-
# @example A/B test inside ERB template (condition)
|
134
|
+
# @example A/B test inside ERB template (condition)
|
124
135
|
# <%= if ab_test(:banner) %>100% less complexity!<% end %>
|
125
|
-
# @example A/B test inside ERB template (value)
|
136
|
+
# @example A/B test inside ERB template (value)
|
126
137
|
# <%= ab_test(:greeting) %> <%= current_user.name %>
|
127
|
-
# @example A/B test inside ERB template (capture)
|
138
|
+
# @example A/B test inside ERB template (capture)
|
128
139
|
# <% ab_test :features do |count| %>
|
129
140
|
# <%= count %> features to choose from!
|
130
141
|
# <% end %>
|
@@ -137,6 +148,22 @@ module Vanity
|
|
137
148
|
value
|
138
149
|
end
|
139
150
|
end
|
151
|
+
|
152
|
+
def vanity_h(text)
|
153
|
+
h(text)
|
154
|
+
end
|
155
|
+
|
156
|
+
def vanity_html_safe(text)
|
157
|
+
if text.respond_to?(:html_safe!)
|
158
|
+
text.html_safe!
|
159
|
+
else
|
160
|
+
text
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def vanity_simple_format(text, html_options={})
|
165
|
+
vanity_html_safe(simple_format(text, html_options))
|
166
|
+
end
|
140
167
|
end
|
141
168
|
|
142
169
|
|
@@ -151,13 +178,13 @@ module Vanity
|
|
151
178
|
# Step 3: Open your browser to http://localhost:3000/vanity
|
152
179
|
module Dashboard
|
153
180
|
def index
|
154
|
-
render :
|
181
|
+
render :file=>Vanity.template("_report"), :content_type=>Mime::HTML, :layout=>false
|
155
182
|
end
|
156
183
|
|
157
184
|
def chooses
|
158
185
|
exp = Vanity.playground.experiment(params[:e])
|
159
186
|
exp.chooses(exp.alternatives[params[:a].to_i].value)
|
160
|
-
render :
|
187
|
+
render :file=>Vanity.template("_experiment"), :locals=>{:experiment=>exp}
|
161
188
|
end
|
162
189
|
end
|
163
190
|
end
|
@@ -179,7 +206,7 @@ if defined?(ActionController)
|
|
179
206
|
# Sets Vanity.context to the current controller, so you can do things like:
|
180
207
|
# experiment(:simple).chooses(:green)
|
181
208
|
def setup_controller_request_and_response
|
182
|
-
setup_controller_request_and_response_without_vanity
|
209
|
+
setup_controller_request_and_response_without_vanity
|
183
210
|
Vanity.context = @controller
|
184
211
|
end
|
185
212
|
end
|
@@ -187,18 +214,17 @@ if defined?(ActionController)
|
|
187
214
|
end
|
188
215
|
|
189
216
|
|
190
|
-
# Automatically configure Vanity.
|
217
|
+
# Automatically configure Vanity.
|
191
218
|
if defined?(Rails)
|
192
|
-
Rails.
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
# connection adapter, turn collection on/off, etc.
|
219
|
+
if Rails.const_defined?(:Railtie) # Rails 3
|
220
|
+
class Plugin < Rails::Railtie # :nodoc:
|
221
|
+
initializer "vanity.require" do |app|
|
222
|
+
Vanity::Rails.load!
|
223
|
+
end
|
224
|
+
end
|
225
|
+
else
|
200
226
|
Rails.configuration.after_initialize do
|
201
|
-
Vanity.
|
227
|
+
Vanity::Rails.load!
|
202
228
|
end
|
203
229
|
end
|
204
230
|
end
|
@@ -206,13 +232,13 @@ end
|
|
206
232
|
|
207
233
|
# Reconnect whenever we fork under Passenger.
|
208
234
|
if defined?(PhusionPassenger)
|
209
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
210
|
-
if forked
|
235
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
236
|
+
if forked
|
211
237
|
begin
|
212
238
|
Vanity.playground.establish_connection if Vanity.playground.collecting?
|
213
239
|
rescue Exception=>ex
|
214
|
-
Rails.logger.error "Error reconnecting: #{ex.to_s}"
|
240
|
+
Rails.logger.error "Error reconnecting: #{ex.to_s}"
|
215
241
|
end
|
216
|
-
end
|
217
|
-
end
|
242
|
+
end
|
243
|
+
end
|
218
244
|
end
|
@@ -57,7 +57,7 @@ module Vanity
|
|
57
57
|
def values(sdate, edate)
|
58
58
|
query = { :conditions=>{ @ar_timestamp=>(sdate.to_time...(edate + 1).to_time) },
|
59
59
|
:group=>"date(#{@ar_scoped.connection.quote_column_name @ar_timestamp})" }
|
60
|
-
grouped = @ar_column ? @ar_scoped.
|
60
|
+
grouped = @ar_column ? @ar_scoped.send(@ar_aggregate, @ar_column, query) : @ar_scoped.count(query)
|
61
61
|
(sdate..edate).inject([]) { |ordered, date| ordered << (grouped[date.to_s] || 0) }
|
62
62
|
end
|
63
63
|
|
data/lib/vanity/playground.rb
CHANGED
@@ -9,7 +9,7 @@ module Vanity
|
|
9
9
|
# puts Vanity.playground.map(&:name)
|
10
10
|
class Playground
|
11
11
|
|
12
|
-
DEFAULTS = { :load_path=>"experiments" }
|
12
|
+
DEFAULTS = { :collecting => true, :load_path=>"experiments" }
|
13
13
|
|
14
14
|
# Created new Playground. Unless you need to, use the global
|
15
15
|
# Vanity.playground.
|
@@ -40,7 +40,7 @@ module Vanity
|
|
40
40
|
@logger.level = Logger::ERROR
|
41
41
|
end
|
42
42
|
@loading = []
|
43
|
-
@collecting =
|
43
|
+
@collecting = @options[:collecting]
|
44
44
|
end
|
45
45
|
|
46
46
|
# Deprecated. Use redis.server instead.
|
@@ -141,7 +141,7 @@ module Vanity
|
|
141
141
|
Dir[File.join(load_path, "metrics/*.rb")].each do |file|
|
142
142
|
Metric.load self, @loading, file
|
143
143
|
end
|
144
|
-
if File.exist?("config/vanity.yml") && remote = YAML.
|
144
|
+
if File.exist?("config/vanity.yml") && remote = YAML.load(ERB.new(File.read("config/vanity.yml")).result)["metrics"]
|
145
145
|
remote.each do |id, url|
|
146
146
|
fail "Metric #{id} already defined in playground" if metrics[id.to_sym]
|
147
147
|
metric = Metric.new(self, id)
|
@@ -195,19 +195,19 @@ module Vanity
|
|
195
195
|
when nil
|
196
196
|
if File.exists?("config/vanity.yml")
|
197
197
|
env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
198
|
-
spec = YAML.
|
198
|
+
spec = YAML.load(ERB.new(File.read("config/vanity.yml")).result)[env]
|
199
199
|
fail "No configuration for #{env}" unless spec
|
200
200
|
establish_connection spec
|
201
201
|
elsif File.exists?("config/redis.yml")
|
202
202
|
env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
203
|
-
redis = YAML.
|
203
|
+
redis = YAML.load(ERB.new(File.read("config/redis.yml")).result)[env]
|
204
204
|
fail "No configuration for #{env}" unless redis
|
205
205
|
establish_connection "redis://" + redis
|
206
206
|
else
|
207
207
|
establish_connection :adapter=>"redis"
|
208
208
|
end
|
209
209
|
when Symbol
|
210
|
-
spec = YAML.
|
210
|
+
spec = YAML.load(ERB.new(File.read("config/vanity.yml")).result)[spec.to_s]
|
211
211
|
establish_connection spec
|
212
212
|
when String
|
213
213
|
uri = URI.parse(spec)
|
@@ -283,7 +283,9 @@ module Vanity
|
|
283
283
|
|
284
284
|
end
|
285
285
|
|
286
|
-
|
286
|
+
# In the case of Rails, use the Rails logger and collect only for
|
287
|
+
# production environment by default.
|
288
|
+
@playground = Playground.new(defined?(Rails) ? { :logger => Rails.logger, :collecting => Rails.env.production? } : {})
|
287
289
|
class << self
|
288
290
|
|
289
291
|
# The playground instance.
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<% score.alts.each do |alt| %>
|
6
6
|
<tr class="<%= "choice" if score.choice == alt %>">
|
7
7
|
<td class="option"><%= alt.name.gsub(/^o/, "O") %>:</td>
|
8
|
-
<td class="value"><code><%=
|
8
|
+
<td class="value"><code><%=vanity_h alt.value.to_s %></code></td>
|
9
9
|
<td>
|
10
10
|
<%= "%.1f%%" % [alt.conversion_rate * 100] %>
|
11
11
|
<%= "(%d%% better than %s)" % [alt.difference, score.least.name] if alt.difference && alt.difference >= 1 %>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<h3><%=
|
2
|
-
<%= experiment.description.to_s.split(/\n\s*\n/).map { |para| %{<p class="description">#{
|
1
|
+
<h3><%=vanity_h experiment.name %> <span class="type">(<%= experiment.class.friendly_name %>)</span></h3>
|
2
|
+
<%= experiment.description.to_s.split(/\n\s*\n/).map { |para| vanity_html_safe(%{<p class="description">#{vanity_h para}</p>}) }.join %>
|
3
3
|
<%= render Vanity.template(experiment.type), :experiment=>experiment %>
|
4
4
|
<p class="meta">Started <%= experiment.created_at.strftime("%a, %b %d") %>
|
5
5
|
<%= " | Completed #{experiment.completed_at.strftime("%a, %b %d")}" unless experiment.active? %></p>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<ul class="experiments">
|
2
2
|
<% experiments.sort_by { |id, experiment| experiment.created_at }.reverse.each do |id, experiment| %>
|
3
|
-
<li class="experiment <%= experiment.type %>" id="experiment_<%=
|
3
|
+
<li class="experiment <%= experiment.type %>" id="experiment_<%=vanity_h id.to_s %>">
|
4
4
|
<%= render Vanity.template("experiment"), :id=>id, :experiment=>experiment %>
|
5
5
|
</li>
|
6
6
|
<% end %>
|
@@ -1,14 +1,14 @@
|
|
1
|
-
<h3><%=
|
2
|
-
<%=
|
1
|
+
<h3><%=vanity_h metric.name %></h3>
|
2
|
+
<%= vanity_simple_format vanity_h(Vanity::Metric.description(metric).to_s), :class=>"description" %>
|
3
3
|
<%=
|
4
4
|
begin
|
5
5
|
data = Vanity::Metric.data(metric)
|
6
6
|
min, max = data.map(&:last).minmax
|
7
7
|
js = data.map { |date,value| "['#{date.to_time.httpdate}',#{value}]" }.join(",")
|
8
|
-
%{<div class="chart"></div>
|
8
|
+
vanity_html_safe(%{<div class="chart"></div>
|
9
9
|
<script type="text/javascript">
|
10
|
-
$(function(){Vanity.metric("#{
|
11
|
-
</script>}
|
10
|
+
$(function(){Vanity.metric("#{vanity_h id.to_s}").plot([{label:"#{vanity_h metric.name}", data: [#{js}]}])})
|
11
|
+
</script>})
|
12
12
|
rescue Exception=>ex
|
13
|
-
%{<div class="error">#{
|
13
|
+
%{<div class="error">#{vanity_h ex.message}</div>}
|
14
14
|
end %>
|
@@ -1,13 +1,14 @@
|
|
1
1
|
<ul class="metrics">
|
2
2
|
<% metrics.sort_by { |id, metric| metric.name }.each do |id, metric| %>
|
3
3
|
<li class="metric" id="metric_<%= id %>">
|
4
|
-
<%= render Vanity.template("
|
4
|
+
<%= render :file=>Vanity.template("_metric"), :locals=>{:id=>id, :metric=>metric} %>
|
5
|
+
<%= render :file=>Vanity.template("_metric"), :locals=>{:id=>id, :metric=>metric} %>
|
5
6
|
</li>
|
6
7
|
<% end %>
|
7
8
|
</ul>
|
8
9
|
<form id="milestones">
|
9
10
|
<% experiments.each do |id, experiment| %>
|
10
11
|
<label><input type="checkbox" name="milestone" data-start="<%= experiment.created_at.httpdate %>"
|
11
|
-
data-end="<%= (experiment.completed_at || Time.now).httpdate %>"><%=
|
12
|
+
data-end="<%= (experiment.completed_at || Time.now).httpdate %>"><%=vanity_h experiment.name %></label>
|
12
13
|
<% end %>
|
13
14
|
</form>
|
@@ -4,22 +4,22 @@
|
|
4
4
|
<style>
|
5
5
|
.vanity { margin: 2em auto; width: 40em; font-family: "Helvetica Neue", "Helvetica", "Verdana", sans-serif }
|
6
6
|
.vanity h1 { margin: 1em 0; border-bottom: 3px solid #ccc }
|
7
|
-
<%= File.read(Vanity.template("vanity.css")) %>
|
7
|
+
<%= vanity_html_safe(File.read(Vanity.template("vanity.css"))) %>
|
8
8
|
</style>
|
9
|
-
<script type="text/javascript"><%= File.read(Vanity.template("jquery.min.js")) %></script>
|
10
|
-
<script type="text/javascript"><%= File.read(Vanity.template("flot.min.js")) %></script>
|
11
|
-
<script type="text/javascript"><%= File.read(Vanity.template("vanity.js")) %></script>
|
9
|
+
<script type="text/javascript"><%= vanity_html_safe(File.read(Vanity.template("jquery.min.js"))) %></script>
|
10
|
+
<script type="text/javascript"><%= vanity_html_safe(File.read(Vanity.template("flot.min.js"))) %></script>
|
11
|
+
<script type="text/javascript"><%= vanity_html_safe(File.read(Vanity.template("vanity.js"))) %></script>
|
12
12
|
<% if respond_to?(:form_authenticity_token) %><script type="text/javascript">document.auth_token = "<%= form_authenticity_token %>"</script><% end %>
|
13
13
|
</head>
|
14
14
|
<body>
|
15
15
|
<div class="vanity">
|
16
16
|
<% experiments = Vanity.playground.experiments ; unless experiments.empty? %>
|
17
17
|
<h2>Experiments</h2>
|
18
|
-
<%= render Vanity.template("
|
18
|
+
<%= render :file=>Vanity.template("_experiments"), :locals=>{:experiments=>experiments} %>
|
19
19
|
<% end %>
|
20
20
|
<% metrics = Vanity.playground.metrics ; unless metrics.empty? %>
|
21
21
|
<h2>Metrics</h2>
|
22
|
-
<%= render Vanity.template("
|
22
|
+
<%= render :file=>Vanity.template("_metrics"), :locals=>{:metrics=>metrics, :experiments=>experiments} %>
|
23
23
|
<% end %>
|
24
24
|
<p class="footer">Generated by <a href="http://vanity.labnotes.org">Vanity</a></p>
|
25
25
|
</div>
|
@@ -42,7 +42,6 @@ context "ActiveRecord Metric" do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
test "record average" do
|
45
|
-
Sky.aggregates
|
46
45
|
File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
|
47
46
|
f.write <<-RUBY
|
48
47
|
metric "Sky is limit" do
|
@@ -51,13 +50,12 @@ context "ActiveRecord Metric" do
|
|
51
50
|
RUBY
|
52
51
|
end
|
53
52
|
Vanity.playground.metrics
|
54
|
-
Sky.create! :height=>
|
53
|
+
Sky.create! :height=>8
|
55
54
|
Sky.create! :height=>2
|
56
|
-
assert_equal
|
55
|
+
assert_equal 5, Vanity::Metric.data(metric(:sky_is_limit)).last.last
|
57
56
|
end
|
58
57
|
|
59
58
|
test "record minimum" do
|
60
|
-
Sky.aggregates
|
61
59
|
File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
|
62
60
|
f.write <<-RUBY
|
63
61
|
metric "Sky is limit" do
|
@@ -72,7 +70,6 @@ context "ActiveRecord Metric" do
|
|
72
70
|
end
|
73
71
|
|
74
72
|
test "record maximum" do
|
75
|
-
Sky.aggregates
|
76
73
|
File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
|
77
74
|
f.write <<-RUBY
|
78
75
|
metric "Sky is limit" do
|
@@ -108,7 +105,6 @@ context "ActiveRecord Metric" do
|
|
108
105
|
end
|
109
106
|
|
110
107
|
test "with scope" do
|
111
|
-
Sky.aggregates
|
112
108
|
File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
|
113
109
|
f.write <<-RUBY
|
114
110
|
metric "Sky is limit" do
|