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