├── POST_INSTALL ├── .gitignore ├── Gemfile ├── generators └── mg │ ├── templates │ ├── initializer.rb │ ├── mg.rb │ ├── mountain_goat_reports.rake │ ├── mountain-goat.yml │ ├── update_mountain_goat_tables_v2.rb │ ├── update_mountain_goat_tables.rb │ └── create_mountain_goat_tables.rb │ └── mg_generator.rb ├── lib ├── mountain-goat │ ├── views │ │ └── mountain_goat │ │ │ ├── layouts │ │ │ ├── xhr.html.erb │ │ │ ├── _pdf.html.erb │ │ │ └── mountain_goat.html.erb │ │ │ └── mg │ │ │ ├── records │ │ │ ├── _records.html.erb │ │ │ ├── new.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── show.html.erb │ │ │ ├── _record.html.erb │ │ │ ├── _records_form.html.erb │ │ │ └── index.html.erb │ │ │ ├── report_items │ │ │ ├── _svg_chart.html.erb │ │ │ ├── _funnel.html.erb │ │ │ ├── _report_item_pivot_form.html.erb │ │ │ ├── new.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── _chart.html.erb │ │ │ ├── _report_item_form.html.erb │ │ │ └── _show.html.erb │ │ │ ├── reports │ │ │ ├── _report_report_items.html.erb │ │ │ ├── _report.html.erb │ │ │ ├── new.html.erb │ │ │ ├── show.html.erb │ │ │ ├── _report_form.html.erb │ │ │ ├── edit.html.erb │ │ │ └── index.html.erb │ │ │ ├── tests │ │ │ ├── new.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── _test_form.html.erb │ │ │ ├── index.html.erb │ │ │ └── show.html.erb │ │ │ ├── goals │ │ │ ├── new.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── _goal_form.html.erb │ │ │ ├── _goal_meta_type_form.html.erb │ │ │ ├── index.html.erb │ │ │ └── show.html.erb │ │ │ ├── choices │ │ │ ├── edit.html.erb │ │ │ ├── new.html.erb │ │ │ ├── index.html.erb │ │ │ ├── _choice_form.html.erb │ │ │ └── show.html.erb │ │ │ ├── playground │ │ │ └── test.html.erb │ │ │ ├── mountain_goat │ │ │ └── login.html.erb │ │ │ └── report_mailer │ │ │ └── report.html.erb │ ├── version.rb │ ├── models │ │ └── mg │ │ │ ├── mountain_goat.rb │ │ │ ├── gi_meta.rb │ │ │ ├── gs_meta.rb │ │ │ ├── report.rb │ │ │ ├── report_mailer.rb │ │ │ ├── goal_meta_type.rb │ │ │ ├── report_item.rb │ │ │ ├── test.rb │ │ │ ├── choice.rb │ │ │ ├── record.rb │ │ │ └── goal.rb │ ├── public │ │ ├── mg.png │ │ ├── raster.png │ │ ├── dirtyred.png │ │ ├── containerbg.png │ │ ├── dottedblack.png │ │ ├── dottedblue.png │ │ ├── jqModel.css │ │ ├── g-dot-min.js │ │ ├── g-pie-min.js │ │ ├── jqModel.js │ │ ├── mg.js │ │ ├── g-line-min.js │ │ ├── jquery.timeago.js │ │ ├── g-bar-min.js │ │ ├── g-funnel.js │ │ ├── jquery.raphael.js │ │ ├── g-raphael-min.js │ │ └── mg.css │ ├── controllers │ │ └── mg │ │ │ ├── playground_controller.rb │ │ │ ├── mg.rb │ │ │ ├── records_controller.rb │ │ │ ├── choices_controller.rb │ │ │ ├── mountain_goat_controller.rb │ │ │ ├── converts_controller.rb │ │ │ ├── tests_controller.rb │ │ │ ├── reports_controller.rb │ │ │ ├── goals_controller.rb │ │ │ └── report_items_controller.rb │ ├── switch_choice.rb │ ├── m_g.rb │ └── analytics.rb └── mountain-goat.rb ├── History.md ├── init.rb ├── test ├── mg_report_item_test.rb ├── fixtures │ ├── mg_rallies.yml │ ├── mg_deliveries.yml │ ├── mg_ci_metas.yml │ ├── mg_metrics.yml │ ├── mg_cs_metas.yml │ ├── mg_convert_meta_types.yml │ ├── mg_report_items.yml │ ├── mg_converts.yml │ ├── mg_reports.yml │ └── mg_metric_variants.yml ├── mg_playground_controller_test.rb ├── mg_report_test.rb ├── mg_convert_test.rb ├── mg_report_items_controller_test.rb ├── mg_rallies_controller_test.rb ├── mg_mountain_goat_controller_test.rb ├── mg_converts_controller_test.rb ├── mg_metric_variants_controller_test.rb ├── mg_reports_controller_test.rb ├── mg_metrics_controller_test.rb └── test_helper.rb ├── Gemfile.lock ├── Rakefile ├── mountain-goat.gemspec ├── LICENSE └── install.rb /POST_INSTALL: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .svn 2 | .DS_Store 3 | .tmp 4 | rb~ 5 | ~ -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :gemcutter 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /generators/mg/templates/initializer.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | #geoff -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/layouts/xhr.html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= yield %> -------------------------------------------------------------------------------- /lib/mountain-goat/version.rb: -------------------------------------------------------------------------------- 1 | class MountainGoat 2 | VERSION = "1.0.4" 3 | end 4 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2011-7-6 2 | ================== 3 | * Initial commit 4 | * Added History.md 5 | -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/mountain_goat.rb: -------------------------------------------------------------------------------- 1 | class Mg::MountainGoat < ActiveRecord::Base 2 | 3 | end 4 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | 2 | require File.join([File.dirname(__FILE__), 'lib/mountain-goat']) 3 | 4 | #ActionView::Helpers -------------------------------------------------------------------------------- /lib/mountain-goat/public/mg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/mg.png -------------------------------------------------------------------------------- /generators/mg/templates/mg.rb: -------------------------------------------------------------------------------- 1 | #Dir["#{Gem.searcher.find('facebooker').full_gem_path}/lib/tasks/*.rake"].each { |ext| load ext } -------------------------------------------------------------------------------- /lib/mountain-goat/public/raster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/raster.png -------------------------------------------------------------------------------- /lib/mountain-goat/public/dirtyred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/dirtyred.png -------------------------------------------------------------------------------- /lib/mountain-goat/public/containerbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/containerbg.png -------------------------------------------------------------------------------- /lib/mountain-goat/public/dottedblack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/dottedblack.png -------------------------------------------------------------------------------- /lib/mountain-goat/public/dottedblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hayesgm/mountain_goat/HEAD/lib/mountain-goat/public/dottedblue.png -------------------------------------------------------------------------------- /lib/mountain-goat/controllers/mg/playground_controller.rb: -------------------------------------------------------------------------------- 1 | 2 | class Mg::PlaygroundController < Mg 3 | 4 | def test 5 | 6 | end 7 | 8 | end 9 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/_records.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => records %> 2 | 3 | <% records.each do |record| %> 4 | <%= render 'record', :record => record %> 5 | <% end %> -------------------------------------------------------------------------------- /test/mg_report_item_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::ReportItemTest < ActiveSupport::TestCase 4 | 5 | #TODO: Test cases 6 | 7 | end 8 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/_svg_chart.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => report_item %> 2 | 3 | <% res = report_item.gerbil_chart.burn %> 4 | <%= res[res.index(" 5 | -------------------------------------------------------------------------------- /test/fixtures/mg_rallies.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | convert_id: 123 5 | 6 | two: 7 | convert_id: 123 8 | 9 | three: 10 | convert_id: 234 11 | -------------------------------------------------------------------------------- /test/fixtures/mg_deliveries.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | frequency: MyString 5 | recipients: MyText 6 | 7 | two: 8 | frequency: MyString 9 | recipients: MyText 10 | -------------------------------------------------------------------------------- /test/fixtures/mg_ci_metas.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | rally_id: 1 5 | convert_meta_type_id: 1 6 | data: 1 7 | 8 | two: 9 | rally_id: 1 10 | convert_meta_type_id: 1 11 | data: 1 12 | -------------------------------------------------------------------------------- /test/fixtures/mg_metrics.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | id: 123 5 | metric_type: my_metric1 6 | title: MyString 7 | 8 | two: 9 | id: 234 10 | metric_type: my_metric2 11 | title: MyString -------------------------------------------------------------------------------- /test/fixtures/mg_cs_metas.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | rally_id: 1 5 | convert_meta_type_id: 1 6 | data: MyString 7 | 8 | two: 9 | rally_id: 1 10 | convert_meta_type_id: 1 11 | data: MyString 12 | -------------------------------------------------------------------------------- /test/fixtures/mg_convert_meta_types.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | convert_id: 1 5 | name: MyString 6 | var: MyString 7 | meta_type: MyString 8 | 9 | two: 10 | convert_id: 1 11 | name: MyString 12 | var: MyString 13 | meta_type: MyString 14 | -------------------------------------------------------------------------------- /test/fixtures/mg_report_items.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | report_id: 123 5 | reportable_id: 123 6 | reportable_type: Mg::Convert 7 | order: 1 8 | 9 | two: 10 | report_id: 234 11 | reportable_id: 234 12 | reportable_type: Mg::Convert 13 | order: 1 14 | -------------------------------------------------------------------------------- /test/fixtures/mg_converts.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | id: 123 5 | name: my convert 6 | convert_type: convert_1 7 | 8 | two: 9 | id: 234 10 | name: my second convert 11 | convert_type: convert_2 12 | 13 | open_mail: 14 | id: 345 15 | name: open mail 16 | convert_type: open_mail -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/gi_meta.rb: -------------------------------------------------------------------------------- 1 | class Mg::GiMeta < ActiveRecord::Base 2 | set_table_name :mg_gi_metas 3 | 4 | belongs_to :mg_goal_meta_type, :class_name => "Mg::GoalMetaType" 5 | belongs_to :mg_record, :class_name => "Mg::Record" 6 | 7 | validates_presence_of :mg_goal_meta_type_id 8 | validates_presence_of :mg_record_id 9 | 10 | end 11 | -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/gs_meta.rb: -------------------------------------------------------------------------------- 1 | class Mg::GsMeta < ActiveRecord::Base 2 | set_table_name :mg_gs_metas 3 | 4 | belongs_to :mg_goal_meta_type, :class_name => "Mg::GoalMetaType" 5 | belongs_to :mg_record, :class_name => "Mg::Record" 6 | 7 | validates_presence_of :mg_goal_meta_type_id 8 | validates_presence_of :mg_record_id 9 | 10 | end 11 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/_report_report_items.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => report %> 2 | 3 | <% i = 0 %> 4 | <% report.mg_report_items.each do |report_item| %> 5 | <%= render :partial => 'mg/report_items/show', :locals => { :report_item => report_item, :show_up => i > 0, :show_down => i < report.mg_report_items.count - 1 } %> 6 | <% i += 1 %> 7 | <% end %> -------------------------------------------------------------------------------- /test/mg_playground_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::PlaygroundControllerTest < ActionController::TestCase 4 | 5 | #This is going to be a start for testing our in-page drops 6 | test "should get test" do 7 | get :test, {}, logged_in 8 | assert_response :success 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /test/fixtures/mg_reports.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | id: 123 5 | title: MyString 6 | description: MyText 7 | delivery_set: daily 8 | recipients: gg@ggg.com 9 | 10 | two: 11 | id: 234 12 | title: MyString 13 | description: MyText 14 | delivery_set: weekly 15 | recipients: gg@ggg.com 16 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

New Record

5 | 6 | <% form_for :record, @record, :url => mg_records_url do |f| %> 7 | <%= f.error_messages %> 8 | 9 | <%= render 'records_form', :f => f %> 10 | <% end %> 11 | 12 |
13 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/tests/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Create New Test

3 |
4 |
5 | <% form_for :test, @test, :url => mg_tests_url do |f| %> 6 | <%= f.error_messages %> 7 | 8 | <%= render 'test_form', :f => f %> 9 | <% end %> 10 |
11 |
12 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Edit Record

5 | 6 | <% form_for :record, @record, :url => mg_records_url do |f| %> 7 | <%= f.error_messages %> 8 | 9 | <%= render 'records_form', :f => f %> 10 | <% end %> 11 | 12 |
13 |
-------------------------------------------------------------------------------- /test/fixtures/mg_metric_variants.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html 2 | 3 | one: 4 | metric_id: 123 5 | name: my variant 1 6 | value: MyText 7 | opt1: MyText 8 | opt2: MyText 9 | served: 1 10 | conversions: 1 11 | 12 | two: 13 | metric_id: 123 14 | name: my variant 2 15 | value: MyText 16 | opt1: MyText 17 | opt2: MyText 18 | served: 1 19 | conversions: 1 20 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/goals/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Create New Goal

3 |
4 |
5 | <% form_for :goal, @goal, :url => mg_goals_url do |f| %> 6 | <%= f.error_messages %> 7 | 8 | <%= render :partial => 'mg/goals/goal_form', :locals => { :f => f } %> 9 | <% end %> 10 |
11 |
12 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/choices/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

Edit <%=h @choice.name %>

6 | 7 | <% form_for :choice, @choice, :url => mg_choice_url(:id => @choice.id), :html => { :method => :put } do |f| %> 8 | <%= f.error_messages %> 9 | 10 | <%= render 'choice_form', :f => f %> 11 | <% end %> 12 |
13 |
-------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/report.rb: -------------------------------------------------------------------------------- 1 | class Mg::Report < ActiveRecord::Base 2 | set_table_name :mg_reports 3 | 4 | has_many :mg_report_items, :class_name => "Mg::ReportItem", :foreign_key => "mg_report_id", :order => "mg_report_items.order" 5 | has_many :reportables, :through => :mg_report_items 6 | 7 | validates_presence_of :title 8 | validates_presence_of :delivery_set #can be nil 9 | #validates_presence_of :recipients 10 | 11 | end 12 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/tests/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Edit <%= @test.title.capitalize %>

3 |
4 |
5 | <% form_for :test, @test, :url => mg_test_url(:id => @test.id), :html => { :method => :put } do |f| %> 6 | <%= f.error_messages %> 7 | 8 | <%= render 'test_form', :f => f %> 9 | <% end %> 10 |
11 |
12 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/show.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Record for <%=h @record.goal.name %>

5 | 6 |
7 | <%= @record.created_at.to_s %> 8 |
9 | 10 |
11 | Edit 12 |
13 |
14 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/choices/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

New Choice for <%=h @test.title %>

6 | 7 | <% form_for :choice, @choice, :url => mg_choices_url do |f| %> 8 | <%= f.error_messages %> 9 | 10 | <%= render 'choice_form', :f => f %> 11 | <% end %> 12 | 13 | Back to <%=h @test.title %> 14 |
15 |
-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/goals/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Edit <%=h @goal.name.capitalize %>

3 |
4 |
5 | <% form_for :goal, @goal, :url => mg_goal_url(:id => @goal.id), :html => { :method => :put } do |f| %> 6 | <%= f.error_messages %> 7 | 8 | <%= render :partial => 'mg/goals/goal_form', :locals => { :f => f } %> 9 | <% end %> 10 |
11 |
12 |
-------------------------------------------------------------------------------- /test/mg_report_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::ReportTest < ActiveSupport::TestCase 4 | 5 | test "delivery" do 6 | assert_difference 'ActionMailer::Base.deliveries.size', 2 do 7 | MG.deliver(nil) 8 | end 9 | 10 | assert_difference 'ActionMailer::Base.deliveries.size' do 11 | MG.deliver("daily") 12 | end 13 | 14 | assert_difference 'ActionMailer::Base.deliveries.size' do 15 | MG.deliver("weekly") 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/_report.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => report %> 2 | 3 | 13 | 14 |

<%=h report.title %>

15 | 16 |

<%=h report.description %>

17 | 18 | <% report.mg_report_items.each do |report_item| %> 19 |
20 | <%= render 'mg/report_items/svg_chart', :report_item => report_item %> 21 |
22 | <% end %> -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/playground/test.html.erb: -------------------------------------------------------------------------------- 1 | 2 |

This is a test page

3 | 4 |

5 | <%= mv(:homies, :jump, 'default') %> 6 | <%= mv_detailed(:homies, :click, 'Rock on')[:value] %> 7 | <%= @controller.rc(:click, :geoff => 'a') %> 8 | <%= @controller.rc(:click, :geoff => 'b') %> 9 | <%= @controller.rc(:click, :geoff => 'b') %> 10 | <%= bd(:jim, 'jim') %> 11 | <%= bd(:beam, 'beam') %> 12 | <%= bd(:beam, 'beam') %> 13 | <%# @controller.rc(:click, :metric_homies => 1, :drum_id => 2, :user => true, :invitees => true) %> 14 |

-------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Create New Report

3 |
4 |
5 | 6 | <% form_for :report, @report, :url => mg_reports_url do |f| %> 7 | <%= f.error_messages %> 8 | 9 | <%= render :partial => 'mg/reports/report_form', :locals => { :f => f } %> 10 | 11 |
12 | <%= f.submit 'Submit' %> 13 |
14 | 15 | <% end %> 16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/layouts/_pdf.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 10 | Mountain Goat 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/_record.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => record %> 2 | 3 |
  • 4 |
    5 |
    <%= record.mg_goal.name %>
    6 |
    <%= content_tag(:abbr, record.created_at.to_s, :title => record.created_at.getutc.iso8601, :class => "time-ago") %>
    7 |
    8 | 9 | 16 |
  • -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/mountain_goat/login.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    Please login to Mountain Goat

    3 |

    Mountain Goat is your in-house analytics department. Track metrics, run tests, and monitor your site in real-time.

    4 |
    5 | 14 |
    15 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/_funnel.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => report %> 2 | 3 |
    4 |
    Funnel Chart
    5 |
    6 |
    8 | data-x="<%= report.mg_report_items.map { |ri| ri.reportable.mg_records.count }.join(',') %>" 9 | data-y="<%= report.mg_report_items.map { |ri| "'#{ri.reportable.name}'" }.join(',') %>" 10 | style="width: 450px; height: 450px;" /> 11 |
    12 |
    13 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/_records_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 | 3 | <% if f.object.new_record? %> 4 |
    5 | <%= f.label :goal_type, 'Type (this is technical)' %> 6 | <%= f.text_field :goal_type %> 7 |
    8 | <% else %> 9 | <%= f.hidden_field(:goal_id) %> 10 |

    <%= f.object.mg_goal.name %>

    11 | 12 | <%= f.label :created_at %> 13 | <%= f.text_field :created_at %> 14 | 15 | <% end %> 16 | 17 | <%# TODO: Metas %> 18 | 19 |
    20 | <%= f.submit 'Submit' %> 21 |
    22 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_pivot_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => reportable, optional => pivot %> 2 | 3 | <% pivot = nil if !local_assigns.has_key?(:pivot) %> 4 | 5 | <% if reportable.instance_of?(Mg::Goal) %> 6 | <% gmts = reportable.mg_goal_meta_types %> 7 | <% end %> 8 | 9 | <% if !gmts.nil? %> 10 |
    11 | <%= label_tag :'report_item[pivot]', "Pivot" %> 12 | <%= select_tag :'report_item[pivot]', options_for_select( [[ "None", "" ]] + gmts.map { |gmt| [ gmt.name, "#{gmt.id}-#{gmt.class}" ] }, pivot.nil? ? "" : "#{pivot.id}-#{pivot.type}" ) %> 13 |
    14 | <% end %> -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/records/index.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    <% if @goal %><%=h @goal.name %><% else %>Comprehensive<% end %> Records

    3 |
    4 |
    5 | 6 | <% if @records.count > 0 %> 7 |
      8 | <% @records.each do |record| %> 9 | <%= render 'record', :record => record %> 10 | <% end %> 11 |
    12 | <% else %> 13 |

    No records yet...

    14 | <% end %> 15 |
    16 |
    -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | mountain-goat (0.0.1) 5 | 6 | GEM 7 | remote: http://rubygems.org/ 8 | specs: 9 | diff-lcs (1.1.2) 10 | mocha (0.9.10) 11 | rake 12 | rack (1.2.1) 13 | rack-test (0.5.6) 14 | rack (>= 1.0) 15 | rake (0.8.7) 16 | rspec (2.2.0) 17 | rspec-core (~> 2.2) 18 | rspec-expectations (~> 2.2) 19 | rspec-mocks (~> 2.2) 20 | rspec-core (2.2.1) 21 | rspec-expectations (2.2.0) 22 | diff-lcs (~> 1.1.2) 23 | rspec-mocks (2.2.0) 24 | 25 | PLATFORMS 26 | ruby 27 | 28 | DEPENDENCIES 29 | mountain-goat! 30 | rack-test (>= 0.5.6) 31 | rspec (~> 2.2.0) 32 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
    3 | Add a new Report Item 4 |
    5 |
    6 | <% form_for :report_item, @report_item, :url => mg_report_report_items_url(:report_id => @report.id), :html => { :method => :post, :class => "remote-form report-item", :'data-res' => ".report-items-model .model" } do |f| %> 7 | 8 |
    9 | <%= f.error_messages %> 10 | <%= render :partial => 'mg/report_items/report_item_form', :locals => { :f => f } %> 11 |
    12 | 13 |
    14 | <%= f.submit 'Save', :class => 'bluebutton' %> 15 |
    16 | <% end %> 17 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/show.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    <%=h @report.title %>

    3 |
    4 |

    <%=h @report.description %>

    5 | 6 | <% if @report.report_type == 'graph' %> 7 | <% @report.mg_report_items.each do |report_item| %> 8 | <%= render 'mg/report_items/chart', :report_item => report_item %> 9 | <% end %> 10 | <% elsif @report.report_type == 'funnel' %> 11 | <%= render 'mg/report_items/funnel', :report => @report %> 12 | <% end %> 13 | 14 |
    15 | Edit 16 |
    17 |
    18 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/report_mailer.rb: -------------------------------------------------------------------------------- 1 | class Mg::ReportMailer < ActionMailer::Base 2 | 3 | self.template_root = File.join([File.dirname(__FILE__), '../../views/mountain_goat/']) 4 | 5 | def report(report, pdf) 6 | setup_sender 7 | @recipients = report.recipients 8 | @subject = "[Mountain Goat] - #{report.title}" 9 | @body[:report] = report 10 | 11 | part :content_type => "text/html", 12 | :body => render_message('report', @body) 13 | 14 | attachment :content_type => "application/pdf", 15 | :filename => "report.pdf", 16 | :body => pdf 17 | end 18 | 19 | private 20 | 21 | def setup_sender 22 | 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/tests/_test_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 | 3 |
    4 | <% if f.object.new_record? %> 5 | <%= f.text_field :test_type %> 6 | <%= f.label :test_type, 'Test Type (Technical)' %> 7 | <% else %> 8 |

    <%= f.object.test_type %>

    9 | 10 | <% end %> 11 |
    12 | 13 |
    14 | <%= f.text_field :title %> 15 | <%= f.label :title %> 16 |
    17 | 18 |
    19 | <%= f.check_box :tally_each_serve %> 20 | <%= f.label :tally_each_serve, "Tally every hit?" %> 21 |
    22 | 23 |
    24 | <%= f.submit 'Submit' %> 25 |
    26 | -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/goal_meta_type.rb: -------------------------------------------------------------------------------- 1 | class Mg::GoalMetaType < ActiveRecord::Base 2 | set_table_name :mg_goal_meta_types 3 | 4 | belongs_to :mg_goal, :class_name => "Mg::Goal" 5 | has_many :gi_metas, :dependent => :destroy, :class_name => "Mg::GiMeta", :foreign_key => "mg_goal_meta_type_id" 6 | has_many :gs_metas, :dependent => :destroy, :class_name => "Mg::GsMeta", :foreign_key => "mg_goal_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 'gi_meta', 'ci_meta' 15 | return self.gi_metas 16 | when 'gs_meta', 'cs_meta' 17 | return self.gs_metas 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
    3 | Edit Report Item 4 |
    5 |
    6 |
    7 | <% form_for :report_item, @report_item, :url => update_mg_report_item_url(:id => @report_item.id), :html => { :method => :post, :class => "remote-form report-item", :'data-res' => ".report-items-model .model" } do |f| %> 8 | 9 |
    10 | <%= f.error_messages %> 11 | <%= render :partial => 'mg/report_items/report_item_form', :locals => { :f => f } %> 12 |
    13 | 14 |
    15 | <%= f.submit 'Update', :class => 'bluebutton' %> 16 |
    17 | <% end %> 18 |
    19 |
    -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'bundler' 4 | Bundler::GemHelper.install_tasks 5 | 6 | require 'rspec/core/rake_task' 7 | RSpec::Core::RakeTask.new(:spec) do |spec| 8 | end 9 | 10 | RSpec::Core::RakeTask.new(:rcov) do |spec| 11 | spec.rcov = true 12 | end 13 | 14 | task :default => :spec 15 | 16 | require 'rake/rdoctask' 17 | Rake::RDocTask.new do |rdoc| 18 | version = File.exist?('VERSION') ? File.read('VERSION') : "" 19 | 20 | rdoc.rdoc_dir = 'rdoc' 21 | rdoc.title = "Mountain Goat #{version}" 22 | rdoc.rdoc_files.include('README*') 23 | rdoc.rdoc_files.include('lib/**/*.rb') 24 | end 25 | 26 | require 'install.rb' 27 | task :install do 28 | InstallMetricTrackingTables.new 29 | end 30 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/_chart.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => report_item %> 2 | 3 |
    4 |
    <%= report_item.chart_title %>
    5 |
    6 |
    8 | <%# TODO: There's a ton of assumptions here %> 9 | <% report_item.chart_items.each do |name, channel| %> 10 | data-title<%= it %>="<%= name || "Direct" %>" 11 | data-x<%= it %>="<%= channel.map { |i| i[:x].to_time.to_i * 1000 }.join(',') %>" 12 | data-y<%= it %>="<%= channel.map { |i| i[:y] }.join(',') %>" 13 | <% it = it + 1 %> 14 | <% end %> 15 | style="width: 425px; height: 260px;" /> 16 |
    17 |
    18 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/goals/_goal_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 | 3 | <% if f.object.new_record? %> 4 |
    5 | <%= f.text_field :goal_type %> 6 | <%= f.label :goal_type, 'Type (this is technical)' %> 7 |
    8 | <% else %> 9 |
    10 |

    <%= f.object.goal_type %>

    11 | 12 |
    13 | <% end %> 14 | 15 |
    16 | <%= f.text_field :name %> 17 | <%= f.label :name, 'Goal title' %> 18 |
    19 | 20 |
    21 | <% f.fields_for :mg_goal_meta_types do |builder| %> 22 | <%= render "goal_meta_type_form", :gmt_f => builder %> 23 | <% end %> 24 |
    25 | 26 |
    27 | <%= f.submit 'Submit' %> 28 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/report_item.rb: -------------------------------------------------------------------------------- 1 | class Mg::ReportItem < ActiveRecord::Base 2 | set_table_name :mg_report_items 3 | 4 | belongs_to :mg_report, :class_name => "Mg::Report", :foreign_key => "mg_report_id" 5 | belongs_to :reportable, :polymorphic => true 6 | belongs_to :pivot, :polymorphic => true 7 | 8 | validates_presence_of :mg_report_id 9 | validates_presence_of :reportable_id 10 | validates_presence_of :reportable_type 11 | validates_presence_of :order 12 | 13 | def chart_title 14 | return self.reportable.reportable_title(pivot) 15 | end 16 | 17 | def chart_items 18 | return self.reportable.reportable_chart_items(self.pivot) 19 | end 20 | 21 | def gerbil_chart 22 | return self.reportable.reportable_gerbil_chart(self.pivot) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /generators/mg/templates/mountain_goat_reports.rake: -------------------------------------------------------------------------------- 1 | 2 | ################################################################# 3 | # Mountain Goat # 4 | # # 5 | # This file has been installed to add the 'mg:deliver' # 6 | # rake task to your project. If you are not using # 7 | # Mountain Goat Reporting, you can safely remove this file. # 8 | # # 9 | ################################################################# 10 | 11 | namespace :mg do 12 | 13 | desc "deliver mountain goat reports" 14 | task :deliver, :delivery_set, :needs => :environment do |t, args| 15 | MG.deliver(args[:delivery_set]) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_items/_report_item_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 |
    3 | <%= f.label :reportable, "Report Item" %> 4 | <%= f.select :reportable, options_for_select( [[ "Select a Goal", "" ]] + Mg::Goal.all.map { |goal| [ goal.name, "#{goal.id}-#{goal.class}" ] }, f.object.reportable.nil? ? "" : "#{f.object.reportable_id}-#{f.object.reportable_type}" ), {}, :'data-varies' => 'change', :'data-varies-path' => get_extra_mg_report_items_url, :'data-varies-res' => '#extra' %> 5 |
    6 |
    7 | <% if !f.object.nil? && !f.object.reportable.nil? %> 8 | <%= render :partial => 'mg/report_items/report_item_pivot_form', :locals => { :reportable => f.object.reportable }.merge( f.object.pivot.nil? ? {} : { :pivot => f.object.pivot } ) %> 9 | <% end %> 10 |
    11 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/report_mailer/report.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 | Your statistics for <%=h @report.title %> are attached. 18 |
    19 | 20 |
    21 | - Your friends at Mountain Goat 22 |
    23 |
    24 |
    25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/_report_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 | 3 |
    4 | <%= f.label :title %> 5 | <%= f.text_field :title %> 6 |
    7 | 8 |
    9 | <%= f.label :description %> 10 | <%= f.text_field :description %> 11 |
    12 | 13 |
    14 | <%= f.label :report_type, 'Report Type' %> 15 | <%= f.select :report_type, options_for_select( [ [ 'Graph', 'graph' ], [ 'Funnel', 'funnel' ] ], f.object.report_type ) %> 16 |
    17 | 18 |
    19 | <%= f.label :delivery_set, 'Frequency' %> 20 | <%= f.select :delivery_set, options_for_select( [ [ 'Daily', 'daily' ], [ 'Weekly', 'weekly' ], [ 'Monthly', 'monthly' ], ['Never', 'never'] ], f.object.delivery_set ) %> 21 |
    22 | 23 |
    24 | <%= f.label :recipients, 'Recipients' %> 25 | <%= f.text_area :recipients %> 26 |
    -------------------------------------------------------------------------------- /test/mg_convert_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::ConvertTest < ActiveSupport::TestCase 4 | include MetricTracking::Controller 5 | 6 | test "should tests" do 7 | @mg_strategy = 'e-greedy' 8 | 9 | assert_difference 'Mg::Convert.count' do 10 | assert_difference 'Mg::Rally.count' do 11 | assert_difference 'Mg::CsMeta.count' do 12 | assert_difference 'Mg::ConvertMetaType.count' do 13 | rw(:hiz, 0, :geoff => "hayes") 14 | end 15 | end 16 | end 17 | end 18 | 19 | conv = Mg::Convert.by_type(:hiz) 20 | assert_not_nil conv 21 | 22 | assert_equal "hayes", conv.rallies_for_meta(:geoff).first.first[0] 23 | 24 | #short-hand method 25 | assert_difference 'Mg::Rally.count' do 26 | assert_difference 'Mg::CsMeta.count' do 27 | rw(:hiz, :geoff => "hayes") 28 | end 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/choices/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 |

    Listing Choices

    5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | <% @choices.each do |choice| %> 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | <% end %> 28 |
    MetricValueOpt1Opt2ServedConversions
    <%=h choice.mg_test_id %><%=h choice.value %><%=h choice.opt1 %><%=h choice.opt2 %><%=h choice.served %><%=h choice.conversions %>ShowEdit
    29 | 30 |
    31 | 32 | <%= link_to 'New Choice', new_mg_choice_url %> 33 |
    34 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/goals/_goal_meta_type_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => gmt_f %> 2 | 3 |
    4 | 5 |
    6 | <%= gmt_f.text_field :name %> 7 | <%= gmt_f.label :name, 'Meta Name' %> 8 |
    9 | 10 | <% if gmt_f.object.new_record? %> 11 |
    12 | <%= gmt_f.text_field :var %> 13 | <%= gmt_f.label :var, 'Var' %> 14 |
    15 | <% end %> 16 | 17 |
    18 | <%= gmt_f.select :meta_type, [ [ "Integer", "gi_meta" ], [ "String", "gs_meta" ] ] %> 19 | <% if gmt_f.object.new_record? %> 20 | <%= gmt_f.label :meta_type, 'Meta Type' %> 21 | <% else %> 22 | <%= gmt_f.label :meta_type, "#{gmt_f.object.var} Type" %> 23 | <% end %> 24 |
    25 | 26 |
    27 | <%= gmt_f.check_box :_destroy %> 28 | <% if gmt_f.object.new_record? %> 29 | <%= gmt_f.label :_destroy, "Remove Meta" %> 30 | <% else %> 31 | <%= gmt_f.label :_destroy, "Remove #{gmt_f.object.var}" %> 32 | <% end %> 33 |
    34 |
    35 | -------------------------------------------------------------------------------- /mountain-goat.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "mountain-goat/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "mountain-goat" 7 | s.version = MountainGoat::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Geoffrey Hayes", "meloncard.com"] 10 | s.email = ["geoff@meloncard.com"] 11 | s.homepage = "http://github.com/hayesgm/mountain_goat" 12 | s.summary = "A/B Testing to the edge" 13 | s.description = "A/B test everything and get awesome in-house analytics" 14 | 15 | s.rubyforge_project = "mountain-goat" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | 22 | # Development Dependencies 23 | s.add_development_dependency(%q, ["~> 2.2.0"]) 24 | s.add_development_dependency(%q, [">= 0.5.6"]) 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/choices/_choice_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals => f %> 2 | 3 | <%= f.hidden_field :mg_test_id %> 4 | 5 | <% if f.object.mg_test.is_switch %> 6 | <%=h f.object.switch_type %> 7 | <% end %> 8 | 9 |
    10 | <%= f.label :name, 'Name (whatever you want)' %> 11 | <%= f.text_field :name %> 12 |
    13 | 14 | <% if !f.object.mg_test.is_switch %> 15 |
    16 | <%= f.label :value, 'What\'s displayed' %> 17 | <%= f.text_area :value %> 18 |
    19 | 20 | 21 | 22 | 33 | <% end %> 34 | 35 |
    36 | <%= f.submit 'Submit' %> 37 |
    38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 hayesgm 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /generators/mg/templates/mountain-goat.yml: -------------------------------------------------------------------------------- 1 | 2 | ################# 3 | # Mountain Goat # 4 | ################# 5 | 6 | # Add your access passwords for each environment 7 | # 8 | # Settings: epsilon for e-greedy strategy 9 | # strategy: one of [ 'e-greedy', 'e-greedy-decreasing', 'a/b' ] 10 | # storage: ['cookies','session','none'] 11 | 12 | # wkhtmltopdf must be installed to use Mountain Goat Reporting 13 | # Please specify the executable for wkhtmltopdf below 14 | # E.g. (Linux) /usr/local/bin/wkhtmltopdf 15 | # (Windows) C:\Program Files (x86)\wkhtmltopdf\wkhtmltopdf.exe 16 | # wkhtmltopdf can be installed from http://code.google.com/p/wkhtmltopdf/ 17 | 18 | settings: 19 | epsilon: 0.1 20 | strategy: e-greedy 21 | storage: cookies 22 | email-from: 23 | 24 | test: 25 | password: <%= password %> 26 | wkhtmltopdf: <%= wkhtmltopdf %> 27 | development: 28 | password: <%= password %> 29 | wkhtmltopdf: <%= wkhtmltopdf %> 30 | staging: 31 | password: <%= password %> 32 | wkhtmltopdf: <%= wkhtmltopdf %> 33 | production: 34 | password: <%= password %> 35 | wkhtmltopdf: <%= wkhtmltopdf %> -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/choices/show.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 8 | 9 |

    <%=h @choice.name %>

    10 | 11 |
    12 |
    13 | 14 | <%=h @choice.name %> 15 | 16 | 17 | 18 | 19 | <%= number_to_percentage(@choice.conversion_rate, :precision => 0) %> 20 | (<%= @choice.conversions %> / 21 | <%= @choice.served %>) 22 | 23 |
    24 |
    25 | 26 |
    27 | Edit 28 |
    29 |
    30 |
    -------------------------------------------------------------------------------- /install.rb: -------------------------------------------------------------------------------- 1 | # Install hook code here 2 | 3 | require 'ftools' 4 | 5 | # keep everything inside fo this scope 6 | class InstallMetricTrackingTables 7 | 8 | def initialize 9 | show_banner 10 | check_system_cosistency 11 | copy_migration_files 12 | end 13 | 14 | def here 15 | File.dirname(__FILE__) 16 | end 17 | 18 | def sources 19 | Dir.glob(File.join([here, 'migrations', '*.*'])) 20 | end 21 | 22 | def target 23 | File.join([here, '..', '..', '..', 'db', 'migrate']) 24 | end 25 | 26 | def validate_file_existance(file) 27 | abort "File not found: #{target}" unless File.exist? file 28 | end 29 | 30 | def show_banner 31 | puts ' 32 | ** Copying migrations to your application 33 | ' 34 | end 35 | 36 | def check_system_cosistency 37 | validate_file_existance(target) 38 | sources.each { |file| validate_file_existance(file) } 39 | end 40 | 41 | def copy_migration_files 42 | sources.each do |file| 43 | File.copy(file, target) 44 | puts " 45 | Source : #{file} 46 | Target : #{target} 47 | " 48 | end 49 | end 50 | 51 | end 52 | 53 | #InstallMetricTrackingTables.new 54 | -------------------------------------------------------------------------------- /test/mg_report_items_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::ReportItemsControllerTest < ActionController::TestCase 4 | 5 | test "new" do 6 | get :new, { :report_id => mg_reports(:one).id }, logged_in 7 | assert_response :success 8 | assert_not_nil assigns(:report_item) 9 | end 10 | 11 | test "create" do 12 | get :create, { :report_id => mg_reports(:one).id , :report_item => { :reportable => "#{mg_converts(:one).id}-#{mg_converts(:one).class}" } }, logged_in 13 | assert_response :success 14 | assert_not_nil assigns(:report_item) 15 | assert_equal mg_converts(:one), assigns(:report_item).reportable 16 | end 17 | 18 | test "edit" do 19 | get :edit, { :id => mg_report_items(:one).id }, logged_in 20 | assert_response :success 21 | assert_not_nil assigns(:report_item) 22 | end 23 | 24 | test "update" do 25 | get :update, { :id => mg_report_items(:one).id, :report_item => { :reportable => "#{mg_converts(:two).id}-#{mg_converts(:two).class}" } }, logged_in 26 | assert_response :success 27 | assert_not_nil assigns(:report_item) 28 | assert_equal mg_converts(:two), assigns(:report_item).reportable 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/edit.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    Edit <%= @report.title %>

    3 |
    4 |
    5 | 6 | <% form_for :report, @report, :url => mg_report_url(:id => @report.id), :html => { :method => :put } do |f| %> 7 | <%= f.error_messages %> 8 | 9 | <%= render :partial => 'mg/reports/report_form', :locals => { :f => f } %> 10 | 11 |
    12 |

    Report Items

    13 | 14 | <%= render :partial => "mg/reports/report_report_items", :locals => { :report => @report } %> 15 |
    16 | 17 |
    18 | Add Item 19 | 20 | <%= f.submit 'Submit' %> 21 |
    22 | 23 |
    24 |
    25 | Close 26 |
    27 |
    28 |
    29 | <% end %> 30 |
    31 |
    32 |
    33 | 34 | -------------------------------------------------------------------------------- /lib/mountain-goat/switch_choice.rb: -------------------------------------------------------------------------------- 1 | 2 | class SwitchChoice 3 | def initialize(logger, test, chosen_choice) 4 | @chosen_choice = chosen_choice 5 | @test = test 6 | @logger = logger 7 | raise ArgumentError, "Test type must be switch-type" if !@test.is_switch 8 | end 9 | 10 | def method_missing(sym, *args, &block) 11 | #priority = ( args.first || 1.0 ).to_f 12 | 13 | if @chosen_choice.nil? 14 | #If we have not chosen a choice, we are going to look through 15 | # each option and make sure we have a back-end entry in choices 16 | # for the type 17 | @logger.warn "Looking at option #{sym.to_s}" 18 | if @test.mg_choices.find( :first, :conditions => { :switch_type => sym.to_s } ).nil? 19 | @logger.warn "Creating switch-type choice #{sym.to_s}" 20 | @test.mg_choices.create!( :name => sym.to_s, :switch_type => sym.to_s, :value => nil ) 21 | end 22 | else 23 | if @chosen_choice.switch_type.to_s == sym.to_s 24 | @logger.warn "Executing option #{sym.to_s}" 25 | yield 26 | else 27 | @logger.warn "Bypassing option #{sym.to_s}" 28 | end 29 | end 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /test/mg_rallies_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::RalliesControllerTest < ActionController::TestCase 4 | 5 | #index, new_rallies, show 6 | 7 | test "get index" do 8 | get :index, {}, logged_in 9 | assert_response :success 10 | assert_not_nil assigns(:rallies) 11 | 12 | get :index, { :convert_id => mg_converts(:two).id }, logged_in 13 | assert_response :success 14 | assert_not_nil assigns(:rallies) 15 | assert_equal mg_converts(:two).id, assigns(:rallies).first.convert_id 16 | end 17 | 18 | test "get new rallies" do 19 | get :new_rallies, {}, logged_in #should get everything 20 | assert_response :success 21 | assert_not_nil assigns(:rallies) 22 | assert_equal Mg::Rally.count, assigns(:rallies).count 23 | 24 | #should get nothing (we are up to date) 25 | get :new_rallies, { :recent_rally => Mg::Rally.last.id }, logged_in 26 | assert_response :success 27 | assert_not_nil assigns(:rallies) 28 | assert_equal 0, assigns(:rallies).count 29 | end 30 | 31 | test "get show" do 32 | get :show, { :id => mg_rallies(:one).id }, logged_in 33 | assert_response :success 34 | assert_not_nil assigns(:rally) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/mountain-goat/views/mountain_goat/mg/reports/index.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    Your Reports

    3 |
    4 |
    5 | Report 6 | Frequency 7 | Actions 8 |
    9 |
      10 | <% @reports.each do |report| %> 11 |
    • 12 | <%=h report.title %> 13 | <%=h report.delivery_set.capitalize %> 14 | ViewEdit Hide 15 |
    • 16 | <% end %> 17 |
    18 | 19 |
    20 | New Report 21 |
    22 | 23 |
    24 | <% @hidden_reports.each do |report| %> 25 | <%=h report.title %> 26 | Restore 27 | <% end %> 28 |
    29 |
    30 |
    -------------------------------------------------------------------------------- /lib/mountain-goat/models/mg/test.rb: -------------------------------------------------------------------------------- 1 | # Mg::Test represents something you are 'a/b testing' 2 | # 3 | # Attributes 4 | # test_type:: Symbol uniquely identifying this test (for code interaction) 5 | # title:: Title of the test (E.g. Banner text) 6 | # tally_each_serve:: Should we count each view by a user as a hit, or just first-serve to that user? 7 | # is_switch:: Are we implementing a code-switch as opposed to a text substitution 8 | # deleted_at:: Is this test deleted? (MG Console) 9 | # is_hidden:: Is this test hidden? (MG Console) 10 | class Mg::Test < ActiveRecord::Base 11 | set_table_name :mg_tests 12 | 13 | # ActiveRecord Associations 14 | has_many :mg_choices, :class_name => "Mg::Choice", :foreign_key => "mg_test_id" 15 | 16 | # Validations 17 | validates_format_of :test_type, :with => /[a-z0-9_]{3,50}/i, :message => "must be between 3 and 30 characters, alphanumeric with underscores" 18 | validates_uniqueness_of :test_type 19 | 20 | # Member Functions 21 | 22 | # Get total reward of all choices for this test 23 | def total_reward 24 | self.mg_choices.map { |choice| choice.reward || 0 }.sum 25 | end 26 | 27 | # Get total served of all choices for this test 28 | def total_served 29 | self.mg_choices.map { |choice| choice.served || 0 }.sum 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/mg_mountain_goat_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class Mg::MountainGoatControllerTest < ActionController::TestCase 4 | 5 | #fetch, login, login_create 6 | 7 | test "fetch file" do 8 | #Double __ could theoretically become a .., let's just stem this off 9 | assert_raise ArgumentError do 10 | get :fetch, { :file => 'hi__png' } 11 | end 12 | 13 | assert_raise ArgumentError do 14 | get :fetch, { :file => 'hi/png' } 15 | end 16 | 17 | assert_raise ArgumentError do 18 | get :fetch, { :file => 'hi.png' } 19 | end 20 | 21 | assert_raise ArgumentError do 22 | get :fetch, { :file => '__/analytics_rb' } 23 | end 24 | 25 | get :fetch, { :file => 'mgnew_css' } 26 | assert_response :not_found 27 | 28 | get :fetch, { :file => 'mg_css' } 29 | assert_response :success 30 | end 31 | 32 | test "login" do 33 | get :login 34 | assert_response :success 35 | assert flash[:error].blank? 36 | end 37 | 38 | test "login - create" do 39 | post :login_create, { :password => '123' } 40 | assert_response :success #invalid 41 | 42 | post :login_create, { :password => 'husky' } 43 | assert_redirected_to '/mg' #valid 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/mountain-goat/controllers/mg/mg.rb: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /lib/mountain-goat/public/jqModel.css: -------------------------------------------------------------------------------- 1 | /* jqModal base Styling courtesy of; 2 | Brice Burgess */ 3 | 4 | /* The Window's CSS z-index value is respected (takes priority). If none is supplied, 5 | the Window's z-index value will be set to 3000 by default (via jqModal.js). */ 6 | 7 | .ocelot-flash-model.model { 8 | z-index:3000; 9 | } 10 | 11 | .jqmWindow { 12 | display: none; 13 | 14 | position: fixed; 15 | top: 17%; 16 | left: 50%; 17 | 18 | margin-left: -300px; 19 | width: 600px; 20 | 21 | background-color: #EEE; 22 | color: #333; 23 | border: 1px solid black; 24 | padding: 12px; 25 | } 26 | 27 | .jqmOverlay { background-color: #000; } 28 | 29 | /* Background iframe styling for IE6. Prevents ActiveX bleed-through (