mountain-goat 1.0.0 → 1.0.1

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.
Files changed (65) hide show
  1. data/README.md +84 -70
  2. data/generators/mg/mg_generator.rb +9 -3
  3. data/generators/mg/templates/create_mountain_goat_tables.rb +4 -0
  4. data/generators/mg/templates/mountain-goat.yml +1 -0
  5. data/lib/mountain-goat.rb +12 -12
  6. data/lib/mountain-goat/controllers/mg/mountain_goat_controller.rb +1 -1
  7. data/lib/mountain-goat/controllers/mg/report_items_controller.rb +5 -5
  8. data/lib/mountain-goat/controllers/mg/reports_controller.rb +28 -1
  9. data/lib/mountain-goat/metric_tracking.rb +4 -4
  10. data/lib/mountain-goat/models/mg/report.rb +4 -4
  11. data/lib/mountain-goat/models/mg/report_item.rb +2 -2
  12. data/lib/mountain-goat/models/mg/report_mailer.rb +7 -0
  13. data/lib/mountain-goat/public/jquery.raphael.js +25 -1
  14. data/lib/mountain-goat/public/mg.css +307 -316
  15. data/lib/mountain-goat/public/mg.js +17 -16
  16. data/lib/mountain-goat/public/mg.png +0 -0
  17. data/lib/mountain-goat/version.rb +1 -1
  18. data/lib/mountain-goat/views/mountain_goat/layouts/mountain_goat.html.erb +21 -20
  19. data/lib/mountain-goat/views/mountain_goat/mg/mountain_goat/login.html.erb +11 -19
  20. data/lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_form.html.erb +1 -1
  21. data/lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_pivot_form.html.erb +4 -4
  22. data/lib/mountain-goat/views/mountain_goat/mg/reports/_report_form.html.erb +7 -2
  23. data/lib/mountain-goat/views/mountain_goat/mg/reports/_report_report_items.html.erb +1 -1
  24. data/lib/mountain-goat/views/mountain_goat/mg/reports/edit.html.erb +27 -30
  25. data/lib/mountain-goat/views/mountain_goat/mg/reports/index.html.erb +24 -20
  26. data/lib/mountain-goat/views/mountain_goat/mg/reports/new.html.erb +14 -13
  27. data/lib/mountain-goat/views/mountain_goat/mg/reports/show.html.erb +10 -13
  28. data/mountain-goat.gemspec +2 -2
  29. metadata +31 -54
  30. data/lib/mountain-goat/controllers/mg/metric_variants_controller.rb +0 -81
  31. data/lib/mountain-goat/controllers/mg/metrics_controller.rb +0 -110
  32. data/lib/mountain-goat/controllers/mg/rallies_controller.rb +0 -43
  33. data/lib/mountain-goat/models/mg/ci_meta.rb +0 -10
  34. data/lib/mountain-goat/models/mg/convert.rb +0 -147
  35. data/lib/mountain-goat/models/mg/convert_meta_type.rb +0 -20
  36. data/lib/mountain-goat/models/mg/cs_meta.rb +0 -10
  37. data/lib/mountain-goat/models/mg/metric.rb +0 -8
  38. data/lib/mountain-goat/models/mg/metric_variant.rb +0 -25
  39. data/lib/mountain-goat/models/mg/rally.rb +0 -59
  40. data/lib/mountain-goat/views/mountain_goat/mg/converts/.tmp_show.html.erb.4433~ +0 -69
  41. data/lib/mountain-goat/views/mountain_goat/mg/converts/_convert_form.html.erb +0 -26
  42. data/lib/mountain-goat/views/mountain_goat/mg/converts/_convert_meta_type_form.html.erb +0 -27
  43. data/lib/mountain-goat/views/mountain_goat/mg/converts/edit.html.erb +0 -13
  44. data/lib/mountain-goat/views/mountain_goat/mg/converts/index.html.erb +0 -25
  45. data/lib/mountain-goat/views/mountain_goat/mg/converts/new.html.erb +0 -13
  46. data/lib/mountain-goat/views/mountain_goat/mg/converts/show.html.erb +0 -44
  47. data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/_metric_variant_form.html.erb +0 -37
  48. data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/edit.html.erb +0 -13
  49. data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/index.html.erb +0 -34
  50. data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/new.html.erb +0 -15
  51. data/lib/mountain-goat/views/mountain_goat/mg/metric_variants/show.html.erb +0 -30
  52. data/lib/mountain-goat/views/mountain_goat/mg/metrics/.tmp_show.html.erb.21270~ +0 -68
  53. data/lib/mountain-goat/views/mountain_goat/mg/metrics/_metric_form.html.erb +0 -24
  54. data/lib/mountain-goat/views/mountain_goat/mg/metrics/edit.html.erb +0 -13
  55. data/lib/mountain-goat/views/mountain_goat/mg/metrics/index.html.erb +0 -14
  56. data/lib/mountain-goat/views/mountain_goat/mg/metrics/new.html.erb +0 -14
  57. data/lib/mountain-goat/views/mountain_goat/mg/metrics/show.html.erb +0 -67
  58. data/lib/mountain-goat/views/mountain_goat/mg/rallies/.tmp__rally.html.erb.40484~ +0 -12
  59. data/lib/mountain-goat/views/mountain_goat/mg/rallies/_rallies.html.erb +0 -5
  60. data/lib/mountain-goat/views/mountain_goat/mg/rallies/_rallies_form.html.erb +0 -21
  61. data/lib/mountain-goat/views/mountain_goat/mg/rallies/_rally.html.erb +0 -12
  62. data/lib/mountain-goat/views/mountain_goat/mg/rallies/edit.html.erb +0 -13
  63. data/lib/mountain-goat/views/mountain_goat/mg/rallies/index.html.erb +0 -19
  64. data/lib/mountain-goat/views/mountain_goat/mg/rallies/new.html.erb +0 -13
  65. data/lib/mountain-goat/views/mountain_goat/mg/rallies/show.html.erb +0 -14
@@ -1,81 +0,0 @@
1
-
2
- class Mg::MetricVariantsController < Mg
3
-
4
- # GET /metric_variants
5
- # GET /metric_variants.xml
6
- def index
7
- @metric_variants = MetricVariant.all
8
-
9
- respond_to do |format|
10
- format.html # index.html.erb
11
- format.xml { render :xml => @metric_variants }
12
- end
13
- end
14
-
15
- # GET /metric_variants/1
16
- # GET /metric_variants/1.xml
17
- def show
18
- @metric_variant = MetricVariant.find(params[:id])
19
-
20
- respond_to do |format|
21
- format.html # show.html.erb
22
- format.xml { render :xml => @metric_variant }
23
- end
24
- end
25
-
26
- # GET /metric_variants/new
27
- # GET /metric_variants/new.xml
28
- def new
29
- @metric = Metric.find( params[:metric_id] )
30
- @metric_variant = MetricVariant.new( :metric_id => @metric.id )
31
-
32
- respond_to do |format|
33
- format.html # new.html.erb
34
- format.xml { render :xml => @metric_variant }
35
- end
36
- end
37
-
38
- # GET /metric_variants/1/edit
39
- def edit
40
- @metric_variant = MetricVariant.find(params[:id])
41
- end
42
-
43
- # POST /metric_variants
44
- # POST /metric_variants.xml
45
- def create
46
- @metric = Metric.find( params[:metric_variant][:metric_id] )
47
- @metric_variant = MetricVariant.new(params[:metric_variant])
48
-
49
- if @metric_variant.save
50
- flash[:notice] = 'Metric variant was successfully created.'
51
- redirect_to mg_metric_url :id => @metric_variant.metric.id
52
- else
53
- render :action => "new"
54
- end
55
- end
56
-
57
- # PUT /metric_variants/1
58
- # PUT /metric_variants/1.xml
59
- def update
60
- @metric_variant = MetricVariant.find(params[:id])
61
-
62
- if @metric_variant.update_attributes(params[:metric_variant])
63
- flash[:notice] = 'Metric variant was successfully updated.'
64
- redirect_to mg_metric_url :id => @metric_variant.metric.id
65
- else
66
- render :action => "edit"
67
- end
68
- end
69
-
70
- # DELETE /metric_variants/1
71
- # DELETE /metric_variants/1.xml
72
- def destroy
73
- @metric_variant = MetricVariant.find(params[:id])
74
- @metric_variant.destroy
75
-
76
- respond_to do |format|
77
- format.html { redirect_to mg_metric_variants_url }
78
- format.xml { head :ok }
79
- end
80
- end
81
- end
@@ -1,110 +0,0 @@
1
-
2
- class Mg::MetricsController < Mg
3
-
4
- # GET /metrics
5
- # GET /metrics.xml
6
- def index
7
- @metrics = Metric.all
8
-
9
- respond_to do |format|
10
- format.html # index.html.erb
11
- format.xml { render :xml => @metrics }
12
- end
13
- end
14
-
15
- # GET /metrics/1
16
- # GET /metrics/1.xml
17
- def show
18
- @metric = Metric.find(params[:id])
19
-
20
- @rates = {}
21
- @rates[:served] = []
22
- @rates[:conversions] = []
23
- @rates[:conversion_rates] = []
24
- @rates[:titles] = {}
25
- i = 0
26
- @metric.metric_variants.each do |mv|
27
- @rates[:served].push( { :variant_type => i, :value => mv.served } )
28
- @rates[:conversions].push( { :variant_type => i, :value => mv.conversions } )
29
- @rates[:conversion_rates].push( { :variant_type => i, :value => mv.conversion_rate } )
30
- @rates[:titles].merge!({i => mv.name})
31
- i += 1
32
- end
33
-
34
- logger.warn @rates[:titles].inspect
35
-
36
- respond_to do |format|
37
- format.html # show.html.erb
38
- format.xml { render :xml => @metric }
39
- end
40
- end
41
-
42
- # GET /metrics/new
43
- # GET /metrics/new.xml
44
- def new
45
- @metric = Metric.new
46
-
47
- respond_to do |format|
48
- format.html # new.html.erb
49
- format.xml { render :xml => @metric }
50
- end
51
- end
52
-
53
- # GET /metrics/1/edit
54
- def edit
55
- @metric = Metric.find(params[:id])
56
- end
57
-
58
- # POST /metrics
59
- # POST /metrics.xml
60
- def create
61
- @metric = Metric.new(params[:metric])
62
-
63
- if @metric.save
64
- flash[:notice] = 'Metric was successfully created.'
65
- redirect_to mg_metric_url :id => @metric.id
66
- else
67
- render :action => "new"
68
- end
69
- end
70
-
71
- # PUT /metrics/1
72
- # PUT /metrics/1.xml
73
- def update
74
- @metric = Metric.find(params[:id])
75
-
76
- if @metric.update_attributes(params[:metric])
77
- flash[:notice] = 'Metric was successfully updated.'
78
- redirect_to mg_metric_url :id => @metric.id
79
- else
80
- render :action => "edit"
81
- end
82
- end
83
-
84
- # DELETE /metrics/1
85
- # DELETE /metrics/1.xml
86
- def destroy
87
- @metric = Metric.find(params[:id])
88
- @metric.destroy
89
-
90
- respond_to do |format|
91
- format.html { redirect_to(mg_metrics_url) }
92
- format.xml { head :ok }
93
- end
94
- end
95
-
96
- #TODO: This only works if we are using cookie storage? Clear session as well
97
- def fresh_metrics
98
- #clear metrics
99
- #logger.warn "Headerish #{response.headers['cookie']}"
100
- cookies.each do |cookie|
101
- if cookie[0] =~ /metric_([a-z0-9_]+)/
102
- logger.warn "Deleting cookie #{cookie[0]}"
103
- cookies.delete cookie[0], :domain => WILD_DOMAIN
104
- end
105
- end
106
-
107
- flash[:notice] = "Your metrics have been cleared from cookies."
108
- redirect_to :back
109
- end
110
- end
@@ -1,43 +0,0 @@
1
-
2
- class Mg::RalliesController < Mg
3
-
4
- def index
5
- @page = !params[:page].nil? ? params[:page].to_i : 1
6
- @convert = Convert.find(params[:convert_id]) if !params[:convert_id].nil?
7
-
8
- if @convert
9
- @rallies = @convert.rallies.find(:all, :conditions => { }, :order => "created_at DESC", :limit => 100, :offset => ( @page - 1 ) * 100 )
10
- else
11
- @rallies = Rally.find(:all, :conditions => { }, :order => "created_at DESC", :limit => 100, :offset => ( @page - 1 ) * 100 )
12
- end
13
-
14
- respond_to do |format|
15
- format.html { }
16
- end
17
- end
18
-
19
- def new_rallies
20
- recent_rally = params[:recent_rally].to_i
21
- convert = Convert.find(params[:convert_id].to_i) unless params[:convert_id].blank?
22
-
23
- if convert
24
- @rallies = convert.rallies.find(:all, :conditions => [ 'id > ?', recent_rally ], :order => "id DESC" )
25
- else
26
- @rallies = Rally.find(:all, :conditions => [ 'id > ?', recent_rally ], :order => "id DESC" )
27
- end
28
-
29
- if @rallies.count > 0
30
- render :json => { :success => true,
31
- :result => render_to_string(:partial => 'mg/rallies/rallies', :locals => { :rallies => @rallies } ),
32
- :recent_rally_id => @rallies.first.id }
33
- else
34
- render :json => { :success => false }
35
- end
36
-
37
- end
38
-
39
- def show
40
- @rally = Rally.find(params[:id])
41
- end
42
-
43
- end
@@ -1,10 +0,0 @@
1
- class Mg::CiMeta < ActiveRecord::Base
2
- set_table_name :mg_ci_metas
3
-
4
- belongs_to :convert_meta_type, :class_name => "Mg::ConvertMetaType"
5
- belongs_to :rally, :class_name => "Mg::Rally"
6
-
7
- validates_presence_of :convert_meta_type_id
8
- validates_presence_of :rally_id
9
-
10
- end
@@ -1,147 +0,0 @@
1
- class Mg::Convert < ActiveRecord::Base
2
- set_table_name :mg_converts
3
-
4
- has_many :rallies, :class_name => "Mg::Rally", :foreign_key => "convert_id"
5
- has_many :convert_meta_types, :class_name => "Mg::ConvertMetaType", :foreign_key => "convert_id"
6
- has_many :ci_metas, :through => :convert_meta_types, :class_name => "Mg::CiMeta", :foreign_key => "convert_id"
7
- has_many :cs_metas, :through => :convert_meta_types, :class_name => "Mg::CsMeta", :foreign_key => "convert_id"
8
- has_many :report_items, :as => :reportable, :class_name => "Mg::ReportItem"
9
-
10
- validates_presence_of :name
11
- validates_format_of :convert_type, :with => /[a-z0-9_]{3,50}/i, :message => "must be between 3 and 30 characters, alphanumeric with underscores"
12
- validates_uniqueness_of :convert_type
13
-
14
- accepts_nested_attributes_for :convert_meta_types, :reject_if => lambda { |a| a[:name].blank? || a[:var].blank? || a[:meta_type].blank? }, :allow_destroy => true
15
-
16
- def self.by_type(s)
17
- Mg::Convert.find( :first, :conditions => { :convert_type => s.to_s } )
18
- end
19
-
20
- def rallies_for_meta(var)
21
- cmt = self.convert_meta_types.find_by_var( var.to_s )
22
- return {} if cmt.nil?
23
- cmt.meta.map { |m| { m.data => m.rally } }
24
- end
25
-
26
- def rallies_for_meta_val(var, data)
27
- cmt = self.convert_meta_types.find_by_var( var.to_s )
28
- return [] if cmt.nil?
29
- cmt.meta.find(:all, :conditions => { :data => data } ).map { |m| m.rally }
30
- end
31
-
32
- def rallies_pivot(pivot)
33
- res = {}
34
- cmt_pivot = self.convert_meta_types.find_by_var( pivot.to_s )
35
- return {} if cmt_pivot.nil?
36
- cmt_pivot.meta.map { |c| { :created_at => c.created_at, :pivot => c.data } }.each do |c|
37
- if !res.include?(c[:pivot])
38
- res[c[:pivot]] = []
39
- end
40
-
41
- res[c[:pivot]].push c[:created_at]
42
- end
43
-
44
- res.each { |k,v| v.sort! }
45
- res
46
- end
47
-
48
- def rallies_for_meta_val_pivot(var, data, pivot)
49
- res = {}
50
- cmt = self.convert_meta_types.find_by_var( var.to_s )
51
- cmt_pivot = self.convert_meta_types.find_by_var( pivot.to_s )
52
- return {} if cmt.nil? || cmt_pivot.nil?
53
- cmt.meta.find(:all, :select => "`#{cmt.meta.table_name}`.created_at, cm.data AS pivot", :conditions => { :data => data }, :joins => "LEFT JOIN `#{cmt_pivot.meta.table_name}` cm ON cm.convert_meta_type_id = #{cmt_pivot.id} AND cm.rally_id = `#{cmt.meta.table_name}`.rally_id").each do |c|
54
- if !res.include?(c.pivot)
55
- res[c.pivot] = []
56
- end
57
-
58
- res[c.pivot].push c.created_at
59
- end
60
-
61
- res.each { |k,v| v.sort! }
62
- res
63
- end
64
-
65
- def rallies_for_meta_val_pivot_item(var, data, pivot, item)
66
- res = {}
67
- cmt = self.convert_meta_types.find_by_var( var.to_s )
68
- cmt_pivot = self.convert_meta_types.find_by_var( pivot.to_s )
69
- cmt_item = self.convert_meta_types.find_by_var( item.to_s )
70
- return {} if cmt.nil? || cmt_pivot.nil? || cmt_item.nil?
71
- cmt.meta.find(:all, :select => "`#{cmt.meta.table_name}`.created_at, cm.data AS pivot, ci.data as item", :conditions => { :data => data }, :joins => "LEFT JOIN `#{cmt_pivot.meta.table_name}` cm ON cm.convert_meta_type_id = #{cmt_pivot.id} AND cm.rally_id = `#{cmt.meta.table_name}`.rally_id LEFT JOIN `#{cmt_item.meta.table_name}` ci ON ci.convert_meta_type_id = #{cmt_item.id} AND ci.rally_id = `#{cmt.meta.table_name}`.rally_id").each do |c|
72
- if !res.include?(c.pivot)
73
- res[c.pivot] = []
74
- end
75
-
76
- if cmt_item.meta_type == 'ci_meta'
77
- c.item.to_i.times { res[c.pivot].push c.created_at }
78
- else
79
- res[c.pivot].push c.created_at if c.item == 'yes' #what else?
80
- end
81
- end
82
-
83
- res.each { |k,v| v.sort! }
84
- res.delete_if { |k,v| v.count == 0 }
85
- res
86
- end
87
-
88
- #For Reportable
89
-
90
- def reportable_title(pivot)
91
- if pivot.nil?
92
- return self.name
93
- elsif pivot.instance_of?(Mg::ConvertMetaType)
94
- return "#{self.name} by #{pivot.name}"
95
- end
96
- end
97
-
98
- def reportable_chart_items(pivot)
99
- #let's look for pageviews by day by source
100
- #rallies_for_meta_val( :clique_id, @clique.id )
101
- #logger.debug "sources: #{sources.inspect}"
102
- #We now have a map of { source => [ date1, date2, ... ], ... }
103
-
104
- #Now, we just need to insert missing data (and group)
105
- #Let's transpose that into { source => [ :x => day0, y => count ] }
106
- if pivot.nil?
107
- return Analytics.pivot_by_date( { :"Rallies" => self.rallies.map { |r| r.created_at } }, self.created_at )
108
- elsif pivot.instance_of?(Mg::ConvertMetaType)
109
- sources = self.rallies_pivot( pivot.var )
110
- logger.warn "sources: #{sources}"
111
- return Analytics.pivot_by_date(sources, self.created_at)
112
- end
113
- end
114
-
115
- def reportable_gerbil_chart(pivot)
116
- #chart = GerbilCharts::Charts::LineChart.new( :width => 350, :height => 200, :style => 'brushmetal.css', :circle_data_points => true )
117
-
118
- if pivot.nil?
119
- data = Analytics.pivot_by_date( { :"Rallies" => self.rallies.map { |r| r.created_at } }, self.created_at )
120
- elsif pivot.instance_of?(Mg::ConvertMetaType)
121
- sources = self.rallies_pivot( pivot.var )
122
- data = Analytics.pivot_by_date(sources, self.created_at)
123
- end
124
- #logger.warn "data: #{data.inspect}"
125
- #logger.warn "ts: #{data.map { |line| line[1].map { |d| d[:x] }.to_a }[0].inspect}"
126
- #logger.warn "val: #{data.map { |line| [ line[0] ] + line[1].map { |d| d[:y] }.to_a }[0].inspect}"
127
- #chart.modelgroup = GerbilCharts::Models::SimpleTimeSeriesModelGroup.new(
128
- # :title => "Rallies",
129
- # :timeseries => data.map { |line| line[1].map { |d| d[:x].to_time }.to_a }[0],
130
- # :models => data.map { |line| [ line[0].to_s ] + line[1].map { |d| d[:y] }.to_a }
131
- #)
132
- #fields = { }
133
- #fields_simple = []
134
- #fields.merge!({ d[:x].to_time.to_i => d[:x].to_s } ); fields_simple.push(d[:x])
135
- graph = SVG::Graph::TimeSeries.new( :height => 350, :width => 700, :show_data_labels => false, :x_label_format => "%m/%d/%y", :graph_title => self.reportable_title(pivot), :show_graph_title => true, :show_data_values => false, :show_data_points => false, :area_fill => true )
136
- data.each do |line|
137
- res = []
138
- line[1].each { |d| res.push(d[:x].strftime('%m/%d/%y')).push(d[:y]) }
139
- graph.add_data :data => res, :title => line[0].to_s
140
- end
141
-
142
- #logger.warn "Fields: #{fields.inspect}"
143
- #logger.warn "Fields Simple: #{fields_simple.inspect}"
144
-
145
- graph
146
- end
147
- end
@@ -1,20 +0,0 @@
1
- class Mg::ConvertMetaType < ActiveRecord::Base
2
- set_table_name :mg_convert_meta_types
3
-
4
- belongs_to :convert, :class_name => "Mg::Convert"
5
- has_many :ci_metas, :dependent => :destroy, :class_name => "Mg::CiMeta", :foreign_key => "convert_meta_type_id"
6
- has_many :cs_metas, :dependent => :destroy, :class_name => "Mg::CsMeta", :foreign_key => "convert_meta_type_id"
7
-
8
- validates_presence_of :name
9
- validates_presence_of :var
10
- validates_presence_of :meta_type
11
-
12
- def meta
13
- case self.meta_type
14
- when 'ci_meta'
15
- return self.ci_metas
16
- when 'cs_meta'
17
- return self.cs_metas
18
- end
19
- end
20
- end
@@ -1,10 +0,0 @@
1
- class Mg::CsMeta < ActiveRecord::Base
2
- set_table_name :mg_cs_metas
3
-
4
- belongs_to :convert_meta_type, :class_name => "Mg::ConvertMetaType"
5
- belongs_to :rally, :class_name => "Mg::Rally"
6
-
7
- validates_presence_of :convert_meta_type_id
8
- validates_presence_of :rally_id
9
-
10
- end
@@ -1,8 +0,0 @@
1
- class Mg::Metric < ActiveRecord::Base
2
- set_table_name :mg_metrics
3
-
4
- has_many :metric_variants, :class_name => "Mg::MetricVariant", :foreign_key => "metric_id"
5
-
6
- validates_format_of :metric_type, :with => /[a-z0-9_]{3,50}/i, :message => "must be between 3 and 30 characters, alphanumeric with underscores"
7
- validates_uniqueness_of :metric_type
8
- end
@@ -1,25 +0,0 @@
1
- class Mg::MetricVariant < ActiveRecord::Base
2
- set_table_name :mg_metric_variants
3
-
4
- belongs_to :metric, :class_name => "Mg::Metric"
5
-
6
- validates_presence_of :name
7
- validates_presence_of :metric_id
8
-
9
- def tally_serve
10
- self.update_attribute(:reward, 0) if self.reward.nil? #we should merge this with the next line, but whatever
11
- Mg::MetricVariant.update_counters(self.id, :served => 1)
12
- self.reload
13
- end
14
-
15
- #reward has a "default" or adjustable setting
16
- def tally_convert(convert, reward = nil)
17
- Mg::MetricVariant.update_counters(self.id, :conversions => 1, :reward => reward.nil? ? convert.reward : reward)
18
- self.reload
19
- end
20
-
21
- def conversion_rate
22
- return nil if self.served == 0
23
- return self.conversions / self.served.to_f * 100
24
- end
25
- end