mountain-goat 0.1.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +119 -48
- data/generators/mg/mg_generator.rb +17 -9
- data/generators/mg/templates/create_mountain_goat_tables.rb +61 -25
- data/generators/mg/templates/mg.rb +1 -0
- data/generators/mg/templates/mountain-goat.yml +22 -3
- data/generators/mg/templates/mountain_goat_reports.rake +17 -0
- data/generators/mg/templates/update_mountain_goat_tables.rb +104 -0
- data/lib/mountain-goat.rb +21 -12
- data/lib/mountain-goat/analytics.rb +134 -0
- data/lib/mountain-goat/controllers/{mountain_goat/mountain_goat_converts_controller.rb → mg/converts_controller.rb} +12 -11
- data/lib/mountain-goat/controllers/{mountain_goat/mountain_goat_metric_variants_controller.rb → mg/metric_variants_controller.rb} +6 -5
- data/lib/mountain-goat/controllers/{mountain_goat/mountain_goat_metrics_controller.rb → mg/metrics_controller.rb} +8 -6
- data/lib/mountain-goat/controllers/mg/mg.rb +47 -0
- data/lib/mountain-goat/controllers/{mountain_goat → mg}/mountain_goat_controller.rb +5 -42
- data/lib/mountain-goat/controllers/mg/playground_controller.rb +8 -0
- data/lib/mountain-goat/controllers/{mountain_goat/mountain_goat_rallies_controller.rb → mg/rallies_controller.rb} +4 -26
- data/lib/mountain-goat/controllers/mg/report_items_controller.rb +82 -0
- data/lib/mountain-goat/controllers/mg/reports_controller.rb +90 -0
- data/lib/mountain-goat/m_g.rb +64 -0
- data/lib/mountain-goat/metric_tracking.rb +192 -74
- data/lib/mountain-goat/models/mg/ci_meta.rb +10 -0
- data/lib/mountain-goat/models/mg/convert.rb +147 -0
- data/lib/mountain-goat/models/mg/convert_meta_type.rb +20 -0
- data/lib/mountain-goat/models/mg/cs_meta.rb +10 -0
- data/lib/mountain-goat/models/{metric.rb → mg/metric.rb} +3 -5
- data/lib/mountain-goat/models/mg/metric_variant.rb +25 -0
- data/lib/mountain-goat/models/mg/mountain_goat.rb +3 -0
- data/lib/mountain-goat/models/{rally.rb → mg/rally.rb} +4 -3
- data/lib/mountain-goat/models/mg/report.rb +11 -0
- data/lib/mountain-goat/models/mg/report_item.rb +24 -0
- data/lib/mountain-goat/models/mg/report_mailer.rb +18 -0
- data/lib/mountain-goat/public/g-bar-min.js +7 -0
- data/lib/mountain-goat/public/g-dot-min.js +7 -0
- data/lib/mountain-goat/public/g-line-min.js +7 -0
- data/lib/mountain-goat/public/g-pie-min.js +1 -0
- data/lib/mountain-goat/public/g-raphael-min.js +7 -0
- data/lib/mountain-goat/public/jqModel.css +41 -0
- data/lib/mountain-goat/public/jqModel.js +69 -0
- data/lib/mountain-goat/public/jquery.raphael.js +208 -0
- data/lib/mountain-goat/public/mg.css +135 -26
- data/lib/mountain-goat/public/mg.js +53 -1
- data/lib/mountain-goat/public/raphael-min.js +7 -0
- data/lib/mountain-goat/public/utils.js +520 -0
- data/lib/mountain-goat/switch_variant.rb +4 -4
- data/lib/mountain-goat/version.rb +1 -1
- data/lib/mountain-goat/views/mountain_goat/layouts/_pdf.html.erb +15 -0
- data/lib/mountain-goat/views/mountain_goat/layouts/mountain_goat.html.erb +17 -5
- data/lib/mountain-goat/views/mountain_goat/layouts/xhr.html.erb +2 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_converts → mg/converts}/.tmp_show.html.erb.4433~ +0 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_converts → mg/converts}/_convert_form.html.erb +0 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_converts → mg/converts}/_convert_meta_type_form.html.erb +0 -0
- data/lib/mountain-goat/views/mountain_goat/mg/converts/edit.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/mg/converts/index.html.erb +25 -0
- data/lib/mountain-goat/views/mountain_goat/mg/converts/new.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_converts → mg/converts}/show.html.erb +3 -28
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metric_variants → mg/metric_variants}/_metric_variant_form.html.erb +0 -4
- data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/edit.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metric_variants → mg/metric_variants}/index.html.erb +3 -3
- data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/new.html.erb +15 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metric_variants → mg/metric_variants}/show.html.erb +4 -5
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metrics → mg/metrics}/.tmp_show.html.erb.21270~ +0 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metrics → mg/metrics}/_metric_form.html.erb +0 -2
- data/lib/mountain-goat/views/mountain_goat/mg/metrics/edit.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/mg/metrics/index.html.erb +14 -0
- data/lib/mountain-goat/views/mountain_goat/mg/metrics/new.html.erb +14 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_metrics → mg/metrics}/show.html.erb +7 -8
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat → mg/mountain_goat}/login.html.erb +0 -0
- data/lib/mountain-goat/views/mountain_goat/mg/playground/test.html.erb +14 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_rallies → mg/rallies}/.tmp__rally.html.erb.40484~ +0 -0
- data/lib/mountain-goat/views/mountain_goat/mg/rallies/_rallies.html.erb +5 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_rallies → mg/rallies}/_rallies_form.html.erb +0 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_rallies → mg/rallies}/_rally.html.erb +0 -0
- data/lib/mountain-goat/views/mountain_goat/mg/rallies/edit.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_rallies → mg/rallies}/index.html.erb +1 -1
- data/lib/mountain-goat/views/mountain_goat/mg/rallies/new.html.erb +13 -0
- data/lib/mountain-goat/views/mountain_goat/{mountain_goat_rallies → mg/rallies}/show.html.erb +1 -1
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/_chart.html.erb +18 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_form.html.erb +10 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_pivot_form.html.erb +14 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/_show.html.erb +29 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/_svg_chart.html.erb +4 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/edit.html.erb +19 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_items/new.html.erb +17 -0
- data/lib/mountain-goat/views/mountain_goat/mg/report_mailer/report.html.erb +27 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/_report.html.erb +22 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/_report_form.html.erb +21 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/_report_report_items.html.erb +5 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/edit.html.erb +36 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/index.html.erb +26 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/new.html.erb +17 -0
- data/lib/mountain-goat/views/mountain_goat/mg/reports/show.html.erb +21 -0
- data/test/fixtures/{ci_metas.yml → mg_ci_metas.yml} +0 -0
- data/test/fixtures/{convert_meta_types.yml → mg_convert_meta_types.yml} +0 -0
- data/test/fixtures/{converts.yml → mg_converts.yml} +5 -0
- data/test/fixtures/{cs_metas.yml → mg_cs_metas.yml} +0 -0
- data/test/fixtures/mg_deliveries.yml +9 -0
- data/test/fixtures/{metric_variants.yml → mg_metric_variants.yml} +0 -0
- data/test/fixtures/{metrics.yml → mg_metrics.yml} +2 -3
- data/test/fixtures/{rallies.yml → mg_rallies.yml} +6 -2
- data/test/fixtures/mg_report_items.yml +13 -0
- data/test/fixtures/mg_reports.yml +15 -0
- data/test/mg_convert_test.rb +32 -0
- data/test/mg_converts_controller_test.rb +47 -0
- data/test/mg_metric_variants_controller_test.rb +46 -0
- data/test/mg_metrics_controller_test.rb +52 -0
- data/test/mg_mountain_goat_controller_test.rb +45 -0
- data/test/mg_mountain_goat_test.rb +392 -0
- data/test/mg_playground_controller_test.rb +11 -0
- data/test/mg_rallies_controller_test.rb +36 -0
- data/test/mg_report_item_test.rb +7 -0
- data/test/mg_report_items_controller_test.rb +31 -0
- data/test/mg_report_test.rb +18 -0
- data/test/mg_reports_controller_test.rb +50 -0
- data/test/test_helper.rb +203 -0
- metadata +108 -55
- data/lib/mountain-goat/models/ci_meta.rb +0 -9
- data/lib/mountain-goat/models/convert.rb +0 -70
- data/lib/mountain-goat/models/convert_meta_type.rb +0 -19
- data/lib/mountain-goat/models/cs_meta.rb +0 -9
- data/lib/mountain-goat/models/metric_variant.rb +0 -22
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_converts/edit.html.erb +0 -13
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_converts/index.html.erb +0 -48
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_converts/new.html.erb +0 -13
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_metric_variants/edit.html.erb +0 -13
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_metric_variants/new.html.erb +0 -15
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/edit.html.erb +0 -13
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/index.html.erb +0 -14
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/new.html.erb +0 -14
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/_rallies.html.erb +0 -5
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/edit.html.erb +0 -13
- data/lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/new.html.erb +0 -13
- data/test/ocelot_converts_controller_test.rb +0 -45
- data/test/ocelot_metric_variants_controller_test.rb +0 -45
- data/test/ocelot_metrics_controller_test.rb +0 -45
- data/test/ocelot_rallies_controller_test.rb +0 -8
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
class Mg < ActionController::Base
|
3
|
+
|
4
|
+
layout 'mountain_goat'
|
5
|
+
|
6
|
+
before_filter :verify_access
|
7
|
+
|
8
|
+
self.prepend_view_path File.join([File.dirname(__FILE__), '../../views/mountain_goat/'])
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def store_location(url = nil)
|
13
|
+
if url.nil?
|
14
|
+
if request.method == :post && request.params.count > 0
|
15
|
+
session[:mg_return_to] = "#{request.request_uri}?" + encode_parameters(request.params)
|
16
|
+
else
|
17
|
+
session[:mg_return_to] = request.request_uri
|
18
|
+
end
|
19
|
+
else
|
20
|
+
session[:mg_return_to] = url
|
21
|
+
end
|
22
|
+
|
23
|
+
logger.warn "Storing location: #{session[:mg_return_to]}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def redirect_back_or_default(default)
|
27
|
+
redirect_to(session[:mg_return_to] || default)
|
28
|
+
session[:mg_return_to] = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify_access
|
32
|
+
return if session[:mg_access] == true
|
33
|
+
store_location
|
34
|
+
redirect_to mg_login_url and return
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.password_digest(password, salt)
|
38
|
+
site_key = '1e9532ea39233e1e2786d80fde90d708c0918d2d'
|
39
|
+
stretches = 10
|
40
|
+
digest = site_key
|
41
|
+
stretches.times do
|
42
|
+
digest = secure_digest(digest, salt, password, site_key)
|
43
|
+
end
|
44
|
+
digest
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -1,15 +1,14 @@
|
|
1
1
|
|
2
|
-
class MountainGoatController <
|
3
|
-
|
4
|
-
layout 'mountain_goat'
|
2
|
+
class Mg::MountainGoatController < Mg
|
5
3
|
|
6
4
|
before_filter :verify_access, :except => [ :login, :login_create, :fetch ]
|
7
|
-
|
8
|
-
self.prepend_view_path File.join([File.dirname(__FILE__), '../../views/mountain_goat/'])
|
9
5
|
|
10
6
|
def fetch
|
11
7
|
ct = { :png => 'image/png', :css => 'text/css', :html => 'text/html', :js => 'text/javascript' }
|
12
8
|
|
9
|
+
raise ArgumentError, "Invalid fetch file" if params[:file].match(/(([_][_])|([^a-z0-9_]))/ix) #extra security
|
10
|
+
|
11
|
+
#We will only serve files located in the public directory for security reasons
|
13
12
|
Dir.open(File.join([File.dirname(__FILE__), '../../public/'])).each do |file|
|
14
13
|
if file == params[:file].gsub('_','.')
|
15
14
|
if file =~ /[.]([a-z0-9]+)$/
|
@@ -21,13 +20,7 @@ class MountainGoatController < ActionController::Base
|
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
render :file => "#{
|
25
|
-
end
|
26
|
-
|
27
|
-
def verify_access
|
28
|
-
return if session.has_key?(:mg_access) && session[:mg_access] == true
|
29
|
-
store_location
|
30
|
-
redirect_to '/mg/login' and return
|
23
|
+
render :file => "#{RAILS_ROOT}/public/404.html", :status => :not_found
|
31
24
|
end
|
32
25
|
|
33
26
|
def login
|
@@ -70,34 +63,4 @@ class MountainGoatController < ActionController::Base
|
|
70
63
|
end
|
71
64
|
end
|
72
65
|
|
73
|
-
def store_location(url = nil)
|
74
|
-
if url.nil?
|
75
|
-
if request.method == :post && request.params.count > 0
|
76
|
-
session[:mg_return_to] = "#{request.request_uri}?" + encode_parameters(request.params)
|
77
|
-
else
|
78
|
-
session[:mg_return_to] = request.request_uri
|
79
|
-
end
|
80
|
-
else
|
81
|
-
session[:mg_return_to] = url
|
82
|
-
end
|
83
|
-
|
84
|
-
logger.warn "Storing location: #{session[:mg_return_to]}"
|
85
|
-
end
|
86
|
-
|
87
|
-
def redirect_back_or_default(default)
|
88
|
-
redirect_to(session[:mg_return_to] || default)
|
89
|
-
session[:mg_return_to] = nil
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def self.password_digest(password, salt)
|
95
|
-
site_key = '1e9532ea39233e1e2786d80fde90d708c0918d2d'
|
96
|
-
stretches = 10
|
97
|
-
digest = site_key
|
98
|
-
stretches.times do
|
99
|
-
digest = secure_digest(digest, salt, password, site_key)
|
100
|
-
end
|
101
|
-
digest
|
102
|
-
end
|
103
66
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
class Mg::RalliesController < Mg
|
2
3
|
|
3
4
|
def index
|
4
|
-
|
5
5
|
@page = !params[:page].nil? ? params[:page].to_i : 1
|
6
|
-
@convert = Convert.find(params[:
|
6
|
+
@convert = Convert.find(params[:convert_id]) if !params[:convert_id].nil?
|
7
7
|
|
8
8
|
if @convert
|
9
9
|
@rallies = @convert.rallies.find(:all, :conditions => { }, :order => "created_at DESC", :limit => 100, :offset => ( @page - 1 ) * 100 )
|
@@ -28,7 +28,7 @@ class MountainGoatRalliesController < MountainGoatController
|
|
28
28
|
|
29
29
|
if @rallies.count > 0
|
30
30
|
render :json => { :success => true,
|
31
|
-
:result => render_to_string(:partial => '
|
31
|
+
:result => render_to_string(:partial => 'mg/rallies/rallies', :locals => { :rallies => @rallies } ),
|
32
32
|
:recent_rally_id => @rallies.first.id }
|
33
33
|
else
|
34
34
|
render :json => { :success => false }
|
@@ -40,26 +40,4 @@ class MountainGoatRalliesController < MountainGoatController
|
|
40
40
|
@rally = Rally.find(params[:id])
|
41
41
|
end
|
42
42
|
|
43
|
-
def new
|
44
|
-
if params[:convert_id]
|
45
|
-
@rally = Rally.new(:convert_id => params[:convert_id])
|
46
|
-
else
|
47
|
-
@rally = Rally.new
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def create
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
def edit
|
57
|
-
@rally = Rally.find(params[:id])
|
58
|
-
end
|
59
|
-
|
60
|
-
def update
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
43
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class Mg::ReportItemsController < Mg
|
2
|
+
|
3
|
+
def get_extra
|
4
|
+
( render :json => { :success => true, :result => "<span></span>" } and return ) if params[:value].blank?
|
5
|
+
id, model = params[:value].split('-')
|
6
|
+
reportable = model.constantize.find(id)
|
7
|
+
render :json => { :success => true, :result => render_to_string( :partial => 'mg/report_items/report_item_pivot_form', :locals => { :reportable => reportable } ) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
@report = Mg::Report.find(params[:report_id])
|
12
|
+
raise ArgumentError, "Invalid report" if @report.nil?
|
13
|
+
|
14
|
+
@report_item = Mg::ReportItem.new
|
15
|
+
|
16
|
+
render :json => { :success => true,
|
17
|
+
:result => render_to_string(:action => :new, :layout => 'xhr') }
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@report = Mg::Report.find(params[:report_id])
|
22
|
+
raise ArgumentError, "Invalid report" if @report.nil?
|
23
|
+
|
24
|
+
@report_item = @report.report_items.new(params[:report_item].clone.delete_if { |k, v| k.intern == :reportable || k.intern == :pivot } )
|
25
|
+
@report_item.order = @report.report_items.to_a.map { |ri| ri.order }.push(0).max + 1#@report.report_items.maximum(:order) + 1 -- weird sqlite3 bugs
|
26
|
+
|
27
|
+
if !params[:report_item][:reportable].blank?
|
28
|
+
id, model = params[:report_item][:reportable].split('-')
|
29
|
+
@report_item.reportable = model.constantize.find(id)
|
30
|
+
end
|
31
|
+
|
32
|
+
if !params[:report_item][:pivot].blank?
|
33
|
+
id, model = params[:report_item][:pivot].split('-')
|
34
|
+
@report_item.pivot = model.constantize.find(id)
|
35
|
+
end
|
36
|
+
|
37
|
+
if @report_item.save
|
38
|
+
render :json => { :success => true,
|
39
|
+
:close_dialog => true,
|
40
|
+
:result => "<span>Successfully added report item</span>",
|
41
|
+
:also => [ { :item => ".report-report-items", :result => render_to_string( :partial => "mg/reports/report_report_items", :locals => { :report => @report_item.report } ) } ] }
|
42
|
+
else
|
43
|
+
render :json => { :success => true,
|
44
|
+
:result => render_to_string(:action => :new, :layout => 'xhr') }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def edit
|
49
|
+
@report_item = Mg::ReportItem.find(params[:id])
|
50
|
+
@report = @report_item.report
|
51
|
+
|
52
|
+
render :json => { :success => true,
|
53
|
+
:result => render_to_string(:action => :edit, :layout => 'xhr') }
|
54
|
+
end
|
55
|
+
|
56
|
+
def update
|
57
|
+
@report_item = Mg::ReportItem.find(params[:id])
|
58
|
+
@report_item.update_attributes(params[:report_item].clone.delete_if { |k, v| k.intern == :reportable || k.intern == :pivot } )
|
59
|
+
|
60
|
+
if !params[:report_item][:reportable].blank?
|
61
|
+
id, model = params[:report_item][:reportable].split('-')
|
62
|
+
@report_item.reportable = model.constantize.find(id)
|
63
|
+
end
|
64
|
+
|
65
|
+
if !params[:report_item][:pivot].blank?
|
66
|
+
id, model = params[:report_item][:pivot].split('-')
|
67
|
+
@report_item.pivot = model.constantize.find(id)
|
68
|
+
end
|
69
|
+
|
70
|
+
if @report_item.save
|
71
|
+
render :json => { :success => true,
|
72
|
+
:close_dialog => true,
|
73
|
+
:result => "<span>Successfully updated report item</span>",
|
74
|
+
:also => [ { :item => ".report-report-items", :result => render_to_string( :partial => "mg/reports/report_report_items", :locals => { :report => @report_item.report }) } ] }
|
75
|
+
else
|
76
|
+
render :json => { :success => true,
|
77
|
+
:result => render_to_string(:action => :edit, :layout => 'xhr') }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#TODO: Destroy
|
82
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Mg::ReportsController < Mg
|
2
|
+
# GET /mg_reports
|
3
|
+
# GET /mg_reports.xml
|
4
|
+
def index
|
5
|
+
@reports = Mg::Report.all
|
6
|
+
|
7
|
+
respond_to do |format|
|
8
|
+
format.html # index.html.erb
|
9
|
+
format.xml { render :xml => @reports }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /mg_reports/1
|
14
|
+
# GET /mg_reports/1.xml
|
15
|
+
def show
|
16
|
+
@report = Mg::Report.find(params[:id])
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html # show.html.erb
|
20
|
+
format.xml { render :xml => @report }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def show_svg
|
25
|
+
@report = Mg::Report.find(params[:id])
|
26
|
+
|
27
|
+
render :text => render_to_string(:partial => "mg/reports/report", :layout => '_pdf', :locals => { :report => @report } )
|
28
|
+
response.content_type = 'application/xhtml+xml'
|
29
|
+
end
|
30
|
+
|
31
|
+
# GET /mg_reports/new
|
32
|
+
# GET /mg_reports/new.xml
|
33
|
+
def new
|
34
|
+
@report = Mg::Report.new
|
35
|
+
|
36
|
+
respond_to do |format|
|
37
|
+
format.html # new.html.erb
|
38
|
+
format.xml { render :xml => @report }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# GET /mg_reports/1/edit
|
43
|
+
def edit
|
44
|
+
@report = Mg::Report.find(params[:id])
|
45
|
+
end
|
46
|
+
|
47
|
+
# POST /mg_reports
|
48
|
+
# POST /mg_reports.xml
|
49
|
+
def create
|
50
|
+
@report = Mg::Report.new(params[:report])
|
51
|
+
|
52
|
+
respond_to do |format|
|
53
|
+
if @report.save
|
54
|
+
format.html { flash[:notice] = 'Your report was successfully created, now add some report items.'; redirect_to(edit_mg_report_url @report) }
|
55
|
+
format.xml { render :xml => @report, :status => :created, :location => @report }
|
56
|
+
else
|
57
|
+
format.html { render :action => "new" }
|
58
|
+
format.xml { render :xml => @report.errors, :status => :unprocessable_entity }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# PUT /mg_reports/1
|
64
|
+
# PUT /mg_reports/1.xml
|
65
|
+
def update
|
66
|
+
@report = Mg::Report.find(params[:id])
|
67
|
+
|
68
|
+
respond_to do |format|
|
69
|
+
if @report.update_attributes(params[:report])
|
70
|
+
format.html { redirect_to(@report, :notice => 'Mg::Report was successfully updated.') }
|
71
|
+
format.xml { head :ok }
|
72
|
+
else
|
73
|
+
format.html { render :action => "edit" }
|
74
|
+
format.xml { render :xml => @report.errors, :status => :unprocessable_entity }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# DELETE /mg_reports/1
|
80
|
+
# DELETE /mg_reports/1.xml
|
81
|
+
def destroy
|
82
|
+
@report = Mg::Report.find(params[:id])
|
83
|
+
@report.destroy
|
84
|
+
|
85
|
+
respond_to do |format|
|
86
|
+
format.html { redirect_to(mg_reports_url) }
|
87
|
+
format.xml { head :ok }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
################
|
3
|
+
# Setup PDFKit #
|
4
|
+
################
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'pdfkit'
|
8
|
+
rescue LoadError
|
9
|
+
raise "Mountain Goat Reports will not work without the 'pdfkit' gem (please run `gem install pdfkit`)"
|
10
|
+
end
|
11
|
+
|
12
|
+
######################
|
13
|
+
# Setup svg-graph #
|
14
|
+
######################
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'SVG/Graph/TimeSeries'
|
18
|
+
rescue LoadError
|
19
|
+
raise "Mountain Goat Reports will not work without the 'svg-graph' gem (please run `gem install svg-graph`)"
|
20
|
+
end
|
21
|
+
|
22
|
+
############################
|
23
|
+
# TODO: Verify Email Setup #
|
24
|
+
############################
|
25
|
+
|
26
|
+
class MG
|
27
|
+
def self.deliver(delivery_set = nil)
|
28
|
+
mg_yml = YAML::load(File.open("#{RAILS_ROOT}/config/mountain-goat.yml"))
|
29
|
+
|
30
|
+
if mg_yml.blank? || mg_yml[RAILS_ENV].blank? || mg_yml[RAILS_ENV]['wkhtmltopdf'].blank?
|
31
|
+
raise "Please configure wkhtmltopdf settings in #{RAILS_ROOT}/config/mountain-goat.yml"
|
32
|
+
end
|
33
|
+
|
34
|
+
PDFKit.configure do |cz|
|
35
|
+
cz.wkhtmltopdf = mg_yml[RAILS_ENV]['wkhtmltopdf']
|
36
|
+
cz.default_options = { :'custom-header' => "'Content-Type' 'application/xhtml+xml'" }
|
37
|
+
end
|
38
|
+
|
39
|
+
if delivery_set.nil?
|
40
|
+
reports = Mg::Report.all
|
41
|
+
else
|
42
|
+
reports = Mg::Report.find(:all, :conditions => { :delivery_set => delivery_set.to_s } )
|
43
|
+
end
|
44
|
+
|
45
|
+
#We need to render the report report_show
|
46
|
+
reports.each do |report|
|
47
|
+
puts "Delivering report: #{report.title}"
|
48
|
+
av = ActionView::Base.new
|
49
|
+
av.view_paths = File.join([File.dirname(__FILE__), 'views/mountain_goat/'])
|
50
|
+
data = av.render(:partial => 'mg/reports/report', :layout => 'layouts/pdf', :locals => { :report => report } )
|
51
|
+
|
52
|
+
#Oddly, the file extension matters most here
|
53
|
+
tmp = Tempfile.new(['chart', '.xhtml'])
|
54
|
+
tmp << data
|
55
|
+
tmp.flush
|
56
|
+
|
57
|
+
kit = PDFKit.new(File.new(tmp.path), :page_size => 'Letter')
|
58
|
+
pdf = kit.to_pdf
|
59
|
+
tmp.close
|
60
|
+
|
61
|
+
Mg::ReportMailer.deliver_report(report, pdf)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -7,49 +7,165 @@ module MetricTracking
|
|
7
7
|
define_method :clear!, lambda {}
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
Mime::Type.register "application/xhtml+xml", :xhtml
|
11
|
+
|
11
12
|
ActionController::Routing::Routes.draw do |map|
|
12
|
-
map.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
map.namespace :mg do |mg|
|
14
|
+
mg.mg '/mg', :controller => :converts, :action => :index, :path_prefix => ""
|
15
|
+
mg.login '/login', :controller => :mountain_goat, :action => :login
|
16
|
+
mg.login_create '/login/create', :controller => :mountain_goat, :action => :login_create
|
17
|
+
mg.resources :metric_variants
|
18
|
+
mg.resources :converts, :has_many => [ :rallies ]
|
19
|
+
mg.resources :metrics, :has_many => :metric_variants
|
20
|
+
mg.resources :rallies, :collection => { :new_rallies => :get }
|
21
|
+
mg.resources :reports, :has_many => :report_items, :member => { :show_svg => :get }
|
22
|
+
mg.resources :report_items, :member => { :destroy => :get, :update => :post }, :collection => { :get_extra => :get }
|
23
|
+
mg.resources :playground, :collection => { :test => :get }
|
24
|
+
mg.new_rallies '/rallies/new', :controller => :rallies, :action => :new_rallies
|
25
|
+
mg.fresh_metrics '/fresh-metrics', :controller => :metrics, :action => :fresh_metrics
|
26
|
+
mg.connect '/public/:file', :controller => :mountain_goat, :action => :fetch
|
27
|
+
end
|
22
28
|
end
|
23
29
|
|
24
30
|
module Controller
|
25
31
|
|
32
|
+
#This is just for testing
|
33
|
+
def mg_rand
|
34
|
+
return "(SELECT #{@mg_i.nil? ? 1 : @mg_i.to_f})" if defined?(MOUNTAIN_GOAT_TEST) && MOUNTAIN_GOAT_TEST
|
35
|
+
"RAND()"
|
36
|
+
end
|
37
|
+
|
38
|
+
def mg_epsilon
|
39
|
+
if @mg_epsilon.nil?
|
40
|
+
@mg_epsilon = 0.1 #default
|
41
|
+
mg_yml = nil
|
42
|
+
begin
|
43
|
+
mg_yml = YAML::load(File.open("#{RAILS_ROOT}/config/mountain-goat.yml"))
|
44
|
+
rescue
|
45
|
+
end
|
46
|
+
if mg_yml
|
47
|
+
if mg_yml.has_key?(RAILS_ENV) && mg_yml[RAILS_ENV].has_key?('epsilon')
|
48
|
+
@mg_epsilon = mg_yml[RAILS_ENV]['epsilon'].to_f
|
49
|
+
elsif mg_yml.has_key?('settings') && mg_yml['settings'].has_key?('epsilon')
|
50
|
+
@mg_epsilon = mg_yml['settings']['epsilon'].to_f
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
return @mg_epsilon
|
55
|
+
end
|
56
|
+
|
57
|
+
def mg_strategy
|
58
|
+
if @mg_strategy.nil?
|
59
|
+
@mg_strategy = 'e-greedy' #default
|
60
|
+
mg_yml = nil
|
61
|
+
begin
|
62
|
+
mg_yml = YAML::load(File.open("#{RAILS_ROOT}/config/mountain-goat.yml"))
|
63
|
+
rescue
|
64
|
+
end
|
65
|
+
if mg_yml
|
66
|
+
if mg_yml.has_key?(RAILS_ENV) && mg_yml[RAILS_ENV].has_key?('strategy')
|
67
|
+
@mg_strategy = mg_yml[RAILS_ENV]['strategy']
|
68
|
+
elsif mg_yml.has_key?('settings') && mg_yml['settings'].has_key?('strategy')
|
69
|
+
@mg_strategy = mg_yml['settings']['strategy']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
return @mg_strategy
|
74
|
+
end
|
75
|
+
|
76
|
+
def mg_apply_strategy(metric)
|
77
|
+
case mg_strategy.downcase
|
78
|
+
when 'e-greedy'
|
79
|
+
logger.warn Mg::MetricVariant.all(:order => "CASE WHEN served = 0 THEN 1 ELSE 0 END DESC, CASE WHEN #{mg_rand} < #{mg_epsilon.to_f} THEN #{mg_rand} ELSE CASE WHEN served = 0 THEN -1 ELSE reward / served END END DESC, #{mg_rand} DESC", :conditions => { :metric_id => metric.id } )
|
80
|
+
return Mg::MetricVariant.first(:order => "CASE WHEN served = 0 THEN 1 ELSE 0 END DESC, CASE WHEN #{mg_rand} < #{mg_epsilon.to_f} THEN #{mg_rand} ELSE CASE WHEN served = 0 THEN -1 ELSE reward / served END END DESC, #{mg_rand} DESC", :conditions => { :metric_id => metric.id } )
|
81
|
+
when 'e-greedy-decreasing'
|
82
|
+
return Mg::MetricVariant.first(:order => "CASE WHEN served = 0 THEN 1 ELSE 0 END DESC,
|
83
|
+
CASE WHEN #{mg_rand} < #{mg_epsilon.to_f} / ( select sum(served) from mg_metric_variants where metric_id = #{ metric.id.to_i } ) THEN #{mg_rand} ELSE CASE WHEN served = 0 THEN -1 ELSE reward / served END END DESC,
|
84
|
+
#{mg_rand} DESC", :conditions => { :metric_id => metric.id } ) # * log( ( select sum(served) from mg_metric_variants where metric_id = #{ metric.id.to_i } ) )
|
85
|
+
when 'a/b'
|
86
|
+
return Mg::MetricVariant.first(:order => "#{mg_rand} DESC", :conditions => { :metric_id => metric.id } )
|
87
|
+
else
|
88
|
+
raise "Invalid strategy #{mg_strategy}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def mg_storage
|
93
|
+
if @mg_storage.nil?
|
94
|
+
@mg_storage = defined?(cookies) ? cookies : nil
|
95
|
+
|
96
|
+
mg_yml = nil
|
97
|
+
begin
|
98
|
+
mg_yml = YAML::load(File.open("#{RAILS_ROOT}/config/mountain-goat.yml"))
|
99
|
+
rescue
|
100
|
+
end
|
101
|
+
if mg_yml
|
102
|
+
if mg_yml.has_key?(RAILS_ENV) && mg_yml[RAILS_ENV].has_key?('storage')
|
103
|
+
uc = mg_yml[RAILS_ENV]['storage'].strip
|
104
|
+
@mg_storage = ( uc == "cookies" && defined?(cookies) ) ? cookies : ( uc == "session" && defined?(session) ) ? session : nil
|
105
|
+
elsif mg_yml.has_key?('settings') && mg_yml['settings'].has_key?('storage')
|
106
|
+
uc = mg_yml['settings']['storage'].strip
|
107
|
+
@mg_storage = ( uc == "cookies" && defined?(cookies) ) ? cookies : ( uc == "session" && defined?(session) ) ? session : nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
@mg_storage = {} if @mg_storage.nil? #'none'
|
112
|
+
return @mg_storage
|
113
|
+
end
|
114
|
+
|
26
115
|
######################
|
27
116
|
# Metric Tracking #
|
28
117
|
######################
|
29
118
|
|
30
|
-
def
|
119
|
+
def bds(metric_type, &block)
|
31
120
|
raise ArgumentError, "Switch variant needs block" if !block_given?
|
32
|
-
metric
|
33
|
-
block.call(SwitchVariant.new( logger, metric,
|
121
|
+
metric = get_metric( metric_type, true )
|
122
|
+
block.call(SwitchVariant.new( logger, metric, nil ) )
|
34
123
|
|
35
|
-
var = get_switch_metric_variant(metric_type
|
36
|
-
block.call(SwitchVariant.new( logger, metric,
|
124
|
+
var = get_switch_metric_variant( metric_type )
|
125
|
+
block.call(SwitchVariant.new( logger, metric, var ) )
|
126
|
+
end
|
127
|
+
|
128
|
+
def bd(metric_type, default, opts = {}, opt = nil)
|
129
|
+
return get_metric_variant(metric_type, default, opts, opt)[:value]
|
130
|
+
end
|
131
|
+
|
132
|
+
def bdd(metric_type, default, opts = {}, opt = nil)
|
133
|
+
return get_metric_variant(metric_type, default, opts, opt)
|
134
|
+
end
|
135
|
+
|
136
|
+
#Legacy
|
137
|
+
def sv(metric_type, convert_type, &block)
|
138
|
+
bds(metric_type, &block)
|
37
139
|
end
|
38
140
|
|
39
141
|
def mv(metric_type, convert_type, default, opts = {}, opt = nil)
|
40
|
-
|
142
|
+
bd(metric_type, default, opts, opt)
|
41
143
|
end
|
42
144
|
|
43
145
|
def mv_detailed(metric_type, convert_type, default, opts = {}, opt = nil)
|
44
|
-
|
146
|
+
bdd(metric_type, default, opts, opt)
|
45
147
|
end
|
46
148
|
|
47
149
|
#shorthand
|
150
|
+
def rw(convert_type, reward, options = {})
|
151
|
+
self.bandit_reward(convert_type, reward, options)
|
152
|
+
end
|
153
|
+
|
48
154
|
def rc(convert_type, options = {})
|
49
|
-
self.
|
155
|
+
self.bandit_reward(convert_type, 1, options)
|
50
156
|
end
|
51
157
|
|
52
158
|
def record_conversion(convert_type, options = {})
|
159
|
+
self.bandit_reward(convert_type, 1, options)
|
160
|
+
end
|
161
|
+
|
162
|
+
#allows bandit_reward(convert, options)
|
163
|
+
def bandit_reward(convert_type, reward, options = {})
|
164
|
+
|
165
|
+
if reward.is_a?(Hash) #allow arguments bandit_reward(convert, options)
|
166
|
+
options = reward
|
167
|
+
reward = 0
|
168
|
+
end
|
53
169
|
|
54
170
|
metrics = {} #for user-defined metrics
|
55
171
|
options = options.with_indifferent_access
|
@@ -71,18 +187,18 @@ module MetricTracking
|
|
71
187
|
|
72
188
|
logger.warn "Recording conversion #{convert_type.to_s} with options #{options.inspect}"
|
73
189
|
|
74
|
-
convert = Convert.first( :conditions => { :convert_type => convert_type.to_s } )
|
190
|
+
convert = Mg::Convert.first( :conditions => { :convert_type => convert_type.to_s } )
|
75
191
|
|
76
192
|
#now, we just create the convert if we don't have one
|
77
|
-
convert = Convert.create!( :convert_type => convert_type.to_s, :name => convert_type.to_s ) if convert.nil?
|
78
|
-
|
193
|
+
convert = Mg::Convert.create!( :convert_type => convert_type.to_s, :name => convert_type.to_s, :reward => reward ) if convert.nil?
|
194
|
+
|
79
195
|
#first, let's tally for the conversion itself
|
80
196
|
#we need to see what meta information we should fill based on the conversion type
|
81
|
-
Rally.create!( { :convert_id => convert.id } ).set_meta_data(options)
|
197
|
+
Mg::Rally.create!( { :convert_id => convert.id } ).set_meta_data(options)
|
82
198
|
|
83
199
|
#User-defined metric tallies
|
84
200
|
metrics.each do |metric_type, variant_id|
|
85
|
-
m = Metric.find_by_metric_type(metric_type)
|
201
|
+
m = Mg::Metric.find_by_metric_type(metric_type)
|
86
202
|
if m.nil?
|
87
203
|
logger.warn "Missing user-defined metric #{metric_type}"
|
88
204
|
next
|
@@ -96,27 +212,27 @@ module MetricTracking
|
|
96
212
|
end
|
97
213
|
|
98
214
|
logger.warn "Tallying conversion #{convert.name} for #{m.title} - #{v.name} (#{v.value} - #{v.id})"
|
99
|
-
v.tally_convert
|
215
|
+
v.tally_convert(convert, reward)
|
100
216
|
end
|
101
217
|
|
102
|
-
if
|
103
|
-
#we just converted, let's tally each of our metrics (from cookies)
|
104
|
-
|
218
|
+
if !mg_storage.nil?
|
219
|
+
#we just converted, let's tally each of our metrics (from cookies or session)
|
220
|
+
Mg::Metric.all.each do |metric|
|
105
221
|
metric_sym = "metric_#{metric.metric_type}".to_sym
|
106
222
|
metric_variant_sym = "metric_#{metric.metric_type}_variant".to_sym
|
107
223
|
|
108
|
-
value =
|
109
|
-
variant_id =
|
224
|
+
value = mg_storage[metric_sym]
|
225
|
+
variant_id = mg_storage[metric_variant_sym]
|
110
226
|
|
111
227
|
#logger.warn "Value: #{metric_sym} - #{value}"
|
112
228
|
#logger.warn "Value: #{metric_variant_sym} - #{variant_id}"
|
113
229
|
|
114
230
|
if variant_id.blank? #the user just doesn't have this set
|
115
|
-
|
231
|
+
#This is now common-case
|
116
232
|
next
|
117
233
|
end
|
118
234
|
|
119
|
-
variant = MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
235
|
+
variant = Mg::MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
120
236
|
|
121
237
|
if variant.nil?
|
122
238
|
logger.error "Variant #{variant_id} not in metric variants for #{metric.title}"
|
@@ -128,7 +244,7 @@ module MetricTracking
|
|
128
244
|
end
|
129
245
|
|
130
246
|
logger.warn "Tallying conversion #{convert.name} for #{metric.title} - #{variant.name} (#{variant.value} - #{variant.id})"
|
131
|
-
variant.tally_convert
|
247
|
+
variant.tally_convert(convert, reward)
|
132
248
|
end
|
133
249
|
end
|
134
250
|
end
|
@@ -136,15 +252,15 @@ module MetricTracking
|
|
136
252
|
private
|
137
253
|
|
138
254
|
#returns a map { :value => value, :variant_id => id }
|
139
|
-
def get_metric_variant(metric_type,
|
255
|
+
def get_metric_variant(metric_type, default, opts = {}, opt = nil)
|
140
256
|
metric_sym = "metric_#{metric_type}#{ opt.nil? ? "" : '_' + opt.to_s }".to_sym
|
141
257
|
metric_variant_sym = "metric_#{metric_type}_variant".to_sym
|
142
258
|
|
143
259
|
#first, we'll check for a cookie value
|
144
|
-
if
|
260
|
+
if !mg_storage.nil? && mg_storage[metric_sym] && !mg_storage[metric_sym].blank?
|
145
261
|
#we have the cookie
|
146
|
-
variant_id =
|
147
|
-
variant = MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
262
|
+
variant_id = mg_storage[metric_variant_sym]
|
263
|
+
variant = Mg::MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
148
264
|
if !variant.nil?
|
149
265
|
if variant.metric.tally_each_serve
|
150
266
|
variant.tally_serve
|
@@ -153,46 +269,44 @@ module MetricTracking
|
|
153
269
|
logger.warn "Serving metric #{metric_type} #{ opt.nil? ? "" : opt.to_s } without finding / tallying variant."
|
154
270
|
end
|
155
271
|
|
156
|
-
return { :value =>
|
272
|
+
return { :value => mg_storage[metric_sym], :variant_id => mg_storage[metric_variant_sym] } #it's the best we can do
|
157
273
|
else
|
158
274
|
#we don't have the cookie, let's find a value to set
|
159
|
-
metric
|
275
|
+
metric = get_metric( metric_type, false )
|
160
276
|
|
161
|
-
|
162
|
-
sum_priority = MetricVariant.first(:select => "SUM(priority) as sum_priority", :conditions => { :metric_id => metric.id } ).sum_priority.to_f
|
163
|
-
|
164
|
-
if sum_priority > 0.0
|
165
|
-
metric_variant = MetricVariant.first(:order => "RAND() * ( priority / #{sum_priority.to_f} ) DESC", :conditions => { :metric_id => metric.id } )
|
166
|
-
end
|
277
|
+
metric_variant = mg_apply_strategy(metric)
|
167
278
|
|
168
279
|
if metric_variant.nil?
|
169
280
|
logger.warn "Missing metric variants for #{metric_type}"
|
170
|
-
metric_variant = MetricVariant.create!( { :metric_id => metric.id, :value => default, :name => default }.merge(opts) )
|
281
|
+
metric_variant = Mg::MetricVariant.create!( { :metric_id => metric.id, :value => default, :name => default }.merge(opts) )
|
282
|
+
end
|
283
|
+
|
284
|
+
if metric_variant.metric.tally_each_serve
|
285
|
+
metric_variant.tally_serve #donate we served this to a user
|
171
286
|
end
|
172
287
|
|
173
|
-
metric_variant.tally_serve #donate we served this to a user
|
174
288
|
value = metric_variant.read_attribute( opt.nil? ? :value : opt )
|
175
289
|
logger.debug "Serving #{metric_variant.name} (#{value}) for #{metric_sym}"
|
176
290
|
#good, we have a variant, let's store it in session
|
177
291
|
|
178
|
-
if
|
179
|
-
|
180
|
-
|
292
|
+
if !mg_storage.nil?
|
293
|
+
mg_storage[metric_sym] = value #, :domain => WILD_DOMAIN
|
294
|
+
mg_storage[metric_variant_sym] = metric_variant.id #, :domain => WILD_DOMAIN
|
181
295
|
end
|
182
296
|
|
183
297
|
return { :value => value, :variant_id => metric_variant.id }
|
184
298
|
end
|
185
299
|
end
|
186
300
|
|
187
|
-
def get_switch_metric_variant(metric_type
|
301
|
+
def get_switch_metric_variant(metric_type)
|
188
302
|
metric_variant_sym = "metric_#{metric_type}_variant".to_sym
|
189
303
|
|
190
304
|
#first, we'll check for a cookie selection
|
191
|
-
if
|
305
|
+
if !mg_storage.nil? && mg_storage[metric_variant_sym] && !mg_storage[metric_variant_sym].blank?
|
192
306
|
#we have the cookie
|
193
307
|
|
194
|
-
variant_id =
|
195
|
-
variant = MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
308
|
+
variant_id = mg_storage[metric_variant_sym]
|
309
|
+
variant = Mg::MetricVariant.first(:conditions => { :id => variant_id.to_i } )
|
196
310
|
if !variant.nil?
|
197
311
|
|
198
312
|
if variant.metric.tally_each_serve
|
@@ -208,46 +322,38 @@ module MetricTracking
|
|
208
322
|
end
|
209
323
|
|
210
324
|
#we don't have the cookie, let's find a value to set
|
211
|
-
metric
|
325
|
+
metric = get_metric( metric_type, true )
|
212
326
|
|
213
|
-
|
214
|
-
sum_priority = MetricVariant.first(:select => "SUM(priority) as sum_priority", :conditions => { :metric_id => metric.id } ).sum_priority.to_f
|
215
|
-
|
216
|
-
if sum_priority > 0.0
|
217
|
-
metric_variant = MetricVariant.first(:order => "RAND() * ( priority / #{sum_priority.to_f} ) DESC", :conditions => { :metric_id => metric.id } )
|
218
|
-
end
|
327
|
+
metric_variant = mg_apply_strategy(metric)
|
219
328
|
|
220
329
|
if metric_variant.nil?
|
221
330
|
logger.warn "Missing metric variants for #{metric_type}"
|
222
331
|
raise ArgumentError, "Missing variants for switch-type #{metric_type}"
|
223
332
|
end
|
224
333
|
|
225
|
-
metric_variant.
|
334
|
+
if metric_variant.metric.tally_each_serve
|
335
|
+
metric_variant.tally_serve #donate we served this to a user
|
336
|
+
end
|
337
|
+
|
226
338
|
logger.debug "Serving #{metric_variant.name} (#{metric_variant.switch_type}) for #{metric.title} (switch-type)"
|
227
339
|
#good, we have a variant, let's store it in session (not the value, just the selection)
|
228
|
-
if
|
229
|
-
|
340
|
+
if !mg_storage.nil?
|
341
|
+
mg_storage[metric_variant_sym] = metric_variant.id #, :domain => WILD_DOMAIN
|
230
342
|
end
|
231
343
|
|
232
344
|
return metric_variant
|
233
345
|
end
|
234
346
|
|
235
|
-
def
|
347
|
+
def get_metric(metric_type, is_switch = false)
|
236
348
|
|
237
|
-
metric = Metric.first(:conditions => { :metric_type => metric_type.to_s } )
|
349
|
+
metric = Mg::Metric.first(:conditions => { :metric_type => metric_type.to_s } )
|
238
350
|
|
239
|
-
conv = Convert.find_by_convert_type( convert_type.to_s )
|
240
|
-
if conv.nil?
|
241
|
-
logger.warn "Missing convert type #{convert_type.to_s} -- creating"
|
242
|
-
conv = Convert.create( :convert_type => convert_type.to_s, :name => convert_type.to_s ) if conv.nil?
|
243
|
-
end
|
244
|
-
|
245
351
|
if metric.nil? #we don't have a metric of this type
|
246
352
|
logger.warn "Missing metric type #{metric_type.to_s} -- creating"
|
247
|
-
metric = Metric.create( :metric_type => metric_type.to_s, :title => metric_type.to_s, :
|
353
|
+
metric = Mg::Metric.create( :metric_type => metric_type.to_s, :title => metric_type.to_s, :is_switch => is_switch )
|
248
354
|
end
|
249
355
|
|
250
|
-
return metric
|
356
|
+
return metric
|
251
357
|
end
|
252
358
|
end
|
253
359
|
|
@@ -263,6 +369,18 @@ module MetricTracking
|
|
263
369
|
def sv(*args, &block)
|
264
370
|
@controller.send(:sv, *args, &block)
|
265
371
|
end
|
372
|
+
|
373
|
+
def bd(*args, &block)
|
374
|
+
@controller.send(:bd, *args, &block)
|
375
|
+
end
|
376
|
+
|
377
|
+
def bdd(*args, &block)
|
378
|
+
@controller.send(:bdd, *args, &block)
|
379
|
+
end
|
380
|
+
|
381
|
+
def bds(*args, &block)
|
382
|
+
@controller.send(:bds, *args, &block)
|
383
|
+
end
|
266
384
|
end
|
267
385
|
end
|
268
386
|
|