Skip to content
This repository
Browse code

dialing in the download graphs

  • Loading branch information...
commit eede2b6b230dc9c3da0162595286e8361e80da0c 1 parent 11c0be9
Nick Quaranto qrush authored
1  Gemfile
@@ -42,6 +42,7 @@ group :test do
42 42 gem "redgreen", "1.2.2"
43 43 gem "rr", "0.10.11"
44 44 gem "shoulda", "2.11.1"
  45 + gem "timecop", "0.3.5"
45 46 gem "treetop", "1.4.5"
46 47 gem "webrat", "0.5.3"
47 48 gem "webmock", "0.7.3"
2  Gemfile.lock
@@ -133,6 +133,7 @@ GEM
133 133 system_timer (1.0)
134 134 term-ansicolor (1.0.5)
135 135 thor (0.14.0)
  136 + timecop (0.3.5)
136 137 treetop (1.4.5)
137 138 polyglot (>= 0.3.1)
138 139 trollop (1.16.2)
@@ -180,6 +181,7 @@ DEPENDENCIES
180 181 shoulda (= 2.11.1)
181 182 sinatra (= 1.0)
182 183 system_timer (= 1.0)
  184 + timecop (= 0.3.5)
183 185 treetop (= 1.4.5)
184 186 validates_url_format_of (= 0.1.0)
185 187 webmock (= 0.7.3)
1  Rakefile
... ... @@ -1,5 +1,4 @@
1 1 require File.expand_path('../config/application', __FILE__)
2   -require 'rake'
3 2 Gemcutter::Application.load_tasks
4 3
5 4 desc "Run all tests and features"
5 app/controllers/profiles_controller.rb
... ... @@ -1,11 +1,12 @@
1 1 class ProfilesController < ApplicationController
2   - #before_filter :redirect_to_root, :unless => :signed_in?, :except => :show
  2 + before_filter :redirect_to_root, :unless => :signed_in?, :except => :show
3 3
4 4 def edit
5 5 end
6 6
7 7 def show
8   - @user = User.find_by_slug(params[:id])
  8 + @user = User.find_by_slug(params[:id])
  9 + @rubygems = @user.rubygems_downloaded
9 10 end
10 11
11 12 def update
13 app/models/rubygem.rb
@@ -208,6 +208,19 @@ def find_or_initialize_version_from_spec(spec)
208 208 version
209 209 end
210 210
  211 + def monthly_downloads
  212 + key_dates = self.class.monthly_dates.map(&:to_s)
  213 + $redis.hmget(Download.history_key(self), *key_dates).map(&:to_i)
  214 + end
  215 +
  216 + def self.monthly_dates
  217 + (2..31).map { |n| n.days.ago.to_date }.reverse
  218 + end
  219 +
  220 + def self.monthly_short_dates
  221 + monthly_dates.map { |date| date.strftime("%m/%d") }
  222 + end
  223 +
211 224 def self.versions_key(name)
212 225 "r:#{name}"
213 226 end
35 app/views/profiles/show.html.erb
@@ -18,25 +18,26 @@
18 18 <%= javascript_include_tag "raphael", "g.raphael", "g.bar", :cache => true %>
19 19 <script type="text/javascript">
20 20 $(document).ready(function() {
  21 + var dates = <%= Rubygem.monthly_short_dates.to_json.html_safe %>;
  22 + <% @rubygems.each do |rubygem| %>
  23 + $.data(document.body, "graph-<%= rubygem.id %>", <%= rubygem.monthly_downloads.to_json.html_safe %>);
  24 + <% end %>
  25 +
21 26 $(".profile-graph").each(function() {
22   - var r = Raphael($(this).attr("id")),
  27 + var id = $(this).attr("id"),
  28 + r = Raphael(id),
23 29 fin = function () {
24   - this.flag = r.g.popup(this.bar.x, this.bar.y, "9/13: " + this.bar.value || "0").insertBefore(this);
  30 + var currentDate = dates[Math.floor(this.bar.x / 23)]
  31 + this.flag = r.g.popup(this.bar.x, this.bar.y, currentDate + ": " + this.bar.value || "0").insertBefore(this);
25 32 },
26 33 fout = function () {
27 34 this.flag.animate({opacity: 0}, 300, function () {this.remove();});
28 35 };
29   - r.g.barchart(1, 9, 690, 125, [
30   - [38, 92, 37, 98, 38,
31   - 87, 83, 30, 19, 10,
32   - 38, 93, 47, 57, 55,
33   - 87, 83, 30, 19, 10,
34   - 38, 93, 47, 57, 55,
35   - 20, 13, 32, 28, 10]
36   - ],
37   - { type: "soft", colors : { 0 : "rgb(200, 164, 164)" } }
38 36
39   - ).hover(fin, fout);
  37 + r.g.barchart(15, 9, 655, 125,
  38 + [ $.data(document.body, id) ],
  39 + { type: "soft", colors : { 0 : "rgb(200, 164, 164)" } }
  40 + ).hover(fin, fout);
40 41 });
41 42 });
42 43 </script>
@@ -45,15 +46,15 @@
45 46 <div id="profile">
46 47 <div class="profile-list">
47 48 <ol>
48   - <% @user.rubygems.each do |rubygem| %>
  49 + <% @rubygems.each do |rubygem| %>
49 50 <li>
50   - <a href="<%=rubygem_path(rubygem)%>" class="profile-rubygem">
  51 + <a href="<%= rubygem_path(rubygem) %>" class="profile-rubygem">
51 52 <%= rubygem.name %>
52 53 <em><%= rubygem.versions.most_recent %></em>
53 54 </a>
54   - <a href="" class="profile-downloads">
55   - <div><span>8,990</span> downloads</div>
56   - <div><span>1,337</span> today</div>
  55 + <a href="<%= rubygem_stats_path(rubygem) %>" class="profile-downloads">
  56 + <div><span><%= number_with_delimiter rubygem.downloads %></span> downloads</div>
  57 + <div><span><%= number_with_delimiter rubygem.downloads_today %></span> today</div>
57 58 </a>
58 59 <div id="graph-<%= rubygem.id %>" class="profile-graph">
59 60 </div>
3  public/stylesheets/screen.css
@@ -1553,6 +1553,7 @@ h5#downloads {
1553 1553 text-shadow: 0 -1px 3px #000000;
1554 1554 vertical-align: top;
1555 1555 padding-top: 5px;
  1556 + width: 178px;
1556 1557 }
1557 1558
1558 1559 .main .info .profile-list ol li a.profile-downloads span {
@@ -1579,7 +1580,7 @@ h5#downloads {
1579 1580 font-weight: 900;
1580 1581 color: #fff;
1581 1582 display: inline-block;
1582   - width: 575px;
  1583 + width: 500px;
1583 1584 overflow: hidden;
1584 1585 height: 21px;
1585 1586 line-height: 23px;
24 test/functional/profiles_controller_test.rb
@@ -8,8 +8,28 @@ class ProfilesControllerTest < ActionController::TestCase
8 8 sign_in_as(@user)
9 9 end
10 10
  11 + context "on GET to show" do
  12 + setup do
  13 + @rubygems = (0..10).map do |n|
  14 + Factory(:rubygem, :downloads => n * 100).tap do |rubygem|
  15 + Factory(:ownership, :rubygem => rubygem, :user => @user, :approved => true)
  16 + end
  17 + end.reverse
  18 + get :show, :id => @user.handle
  19 + end
  20 +
  21 + should respond_with :success
  22 + should render_template :show
  23 + should assign_to(:user) { @user }
  24 + should "assign the last 10 most downloaded gems" do
  25 + assert_equal @rubygems[0..9], assigns[:rubygems]
  26 + end
  27 + end
  28 +
11 29 context "on GET to show with handle" do
12   - setup {get :show, :id => @user.handle}
  30 + setup do
  31 + get :show, :id => @user.handle
  32 + end
13 33
14 34 should respond_with :success
15 35 should render_template :show
@@ -56,6 +76,4 @@ class ProfilesControllerTest < ActionController::TestCase
56 76 should respond_with :redirect
57 77 should redirect_to('the homepage') { root_url }
58 78 end
59   -
60 79 end
61   -
48 test/unit/rubygem_test.rb
@@ -535,4 +535,52 @@ class RubygemTest < ActiveSupport::TestCase
535 535 end
536 536 end
537 537 end
  538 +
  539 + context "downloads" do
  540 + setup do
  541 + @rubygem = Factory(:rubygem)
  542 + @version = Factory(:version, :rubygem => @rubygem)
  543 +
  544 + Timecop.freeze DateTime.parse("10/2/2010")
  545 + 1.times { Download.incr(@rubygem.name, @version.full_name) }
  546 + Download.rollover
  547 +
  548 + Timecop.freeze DateTime.parse("10/3/2010")
  549 + 6.times { Download.incr(@rubygem.name, @version.full_name) }
  550 + Download.rollover
  551 +
  552 + Timecop.freeze DateTime.parse("10/16/2010")
  553 + 4.times { Download.incr(@rubygem.name, @version.full_name) }
  554 + Download.rollover
  555 +
  556 + Timecop.freeze DateTime.parse("11/1/2010")
  557 + 2.times { Download.incr(@rubygem.name, @version.full_name) }
  558 + Download.rollover
  559 +
  560 + Timecop.freeze DateTime.parse("11/2/2010")
  561 + end
  562 +
  563 + should "give counts from the past 30 days" do
  564 + downloads = @rubygem.monthly_downloads
  565 +
  566 + assert_equal 30, downloads.size
  567 + assert_equal 6, downloads.first
  568 + (3..14).each do |n|
  569 + assert_equal 0, downloads[n.to_i - 2]
  570 + end
  571 + assert_equal 4, downloads[13]
  572 + (16..30).each do |n|
  573 + assert_equal 0, downloads[n.to_i - 2]
  574 + end
  575 + assert_equal 2, downloads.last
  576 + end
  577 +
  578 + should "give the monthly dates back" do
  579 + assert_equal ("02".."31").map { |date| "10/#{date}" }, Rubygem.monthly_short_dates
  580 + end
  581 +
  582 + teardown do
  583 + Timecop.return
  584 + end
  585 + end
538 586 end

0 comments on commit eede2b6

Please sign in to comment.
Something went wrong with that request. Please try again.