Skip to content
This repository has been archived by the owner on May 28, 2020. It is now read-only.

Commit

Permalink
refactor from class method
Browse files Browse the repository at this point in the history
  • Loading branch information
rob-murray committed Jul 23, 2015
1 parent 8246c79 commit 6413dd3
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 109 deletions.
16 changes: 9 additions & 7 deletions app/controllers/repository_controller.rb
Expand Up @@ -13,12 +13,14 @@ def show
@repo = fetch_and_rate_repo

respond_to do |format|
format.html
format.html do
@letter_rating = letter_for_rating(@repo.rating)
end
format.svg do
badge = badge_for_rating(@repo.rating)

expires_now
if stale?(etag: [RepoEtag.etag(@repo), "VERSION_001"])
if stale?(etag: [RepoEtag.etag(@repo), AppConfig.badge_version])
render inline: ImageProxy.fetch(badge.display)
end
end
Expand Down Expand Up @@ -74,18 +76,18 @@ def render_error(status, message = '')

def fetch_and_rate_repo
repo = Repository.from_owner_and_name(params[:user_id], params[:id])
repo_fetcher.rate_repo(repo)
GithubRepo.new(repo, github_client).rate_with(RepoRater)
end

def github_client
@github_client ||= GithubAdapter.new(Rails.application.secrets.github_api_key)
end

def repo_fetcher
@repo_fetcher ||= RepositoryFetcher.new(github_client)
end

def badge_for_rating(repo_rating)
BadgeUrlRatingPresenter.new(repo_rating)
end

def letter_for_rating(rating)
LetterRatingPresenter.new(rating).letter
end
end
2 changes: 1 addition & 1 deletion app/models/commit.rb
Expand Up @@ -5,7 +5,7 @@ class Commit
attribute :sha, String
attribute :author_name, String
attribute :date, Time
attribute :message, String
attribute :message, String, default: ""
end

class << self
Expand Down
29 changes: 29 additions & 0 deletions app/models/github_repo.rb
@@ -0,0 +1,29 @@
# A repository model with the Github Api so it can fetch data
#
class GithubRepo < SimpleDelegator
def initialize(repo, api_client)
@api_client = api_client

super post_initialize(repo, api_client)
end

private

attr_reader :api_client

def post_initialize(repo, api_client)
repo.commits = latest_commits(repo.path)
repo
end

def latest_commits(repo_path, branch = 'master')
api_client.list_commits(repo_path, branch).map do |api_response|
Commit.build(
api_response.sha,
api_response.commit.author.name,
api_response.commit.author.date,
api_response.commit.message
)
end
end
end
20 changes: 16 additions & 4 deletions app/models/image_proxy.rb
Expand Up @@ -2,9 +2,21 @@

class ImageProxy
def self.fetch(url)
open(url).read
rescue => e
Rails.logger.warn e
raise BadgeRequestError
new(url).fetch
end

def initialize(url)
@url = url
end

def fetch
open(url, read_timeout: 10).read
rescue => e
Rails.logger.error e
raise BadgeRequestError
end

private

attr_reader :url
end
67 changes: 65 additions & 2 deletions app/models/repo_rater.rb
@@ -1,8 +1,71 @@
class RepoRater
class << self
def build(repo, rating_klasses = default)
raters = Array(rating_klasses).map { |klass| klass.new(repo) }
new(repo).rate_with(raters)
end

def default
TimeBasedRepoRater
end

def rating_klass
RepoRater::Rater
end
end

MIN = 0
MAX = 10

def rate(github_repo)
fail NotImplementedError, 'This method should be implemented'
def initialize(repo)
@repo = repo
@raters = []
end

def rate_with(rating_instances)
@raters = Array(rating_instances)
self
end

def rate
total = raters_or_default.sum(&:rate)

mean_avg(total)
end

class Rater
def initialize(repo)
@repo = repo
end

def rate
Rails.logger.warn 'This is the default method and should be implemented in subclass'

min
end

protected

attr_reader :repo

def min
MIN
end

def max
MAX
end
end

private

attr_reader :repo, :raters

def raters_or_default
@raters_or_default ||= raters.empty? ? Array(Rater.new(repo)) : raters
end

def mean_avg(total)
total / raters_or_default.size
end
end
10 changes: 6 additions & 4 deletions app/models/repository.rb
@@ -1,7 +1,7 @@
class Repository
include Virtus.model

attribute :commits, Array, default: [], writer: :private
attribute :commits, Array[Commit], default: []
attribute :rating, Integer, default: 0, writer: :private
attribute :owner, String
attribute :name, String
Expand All @@ -25,14 +25,16 @@ def add_commit(commit)
end

def latest_commit
commits.last
commits.first
end

def latest_commit_date
latest_commit.date
end

def rate_with(rating_strategy)
@rating = rating_strategy.rate(self)
def rate_with(rater)
self.rating = rater.build(self).rate
self
end

end
19 changes: 9 additions & 10 deletions app/models/time_based_repo_rater.rb
@@ -1,25 +1,24 @@
require 'date'
require_relative 'repo_rater'

class TimeBasedRepoRater < RepoRater
def rate(github_repo)
time_now = DateTime.now
return MIN if github_repo.nil?
class TimeBasedRepoRater < RepoRater.rating_klass
def rate
time_now = Time.zone.now
return min if repo.nil?

last_commit_time = github_repo.latest_commit_date
last_commit_time = repo.latest_commit_date

if last_commit_time.nil? || !last_commit_time.is_a?(Time) # catch when not Time object?
return MIN
return min
end

rating = case (time_now - last_commit_time.to_datetime).round
when 0..7 then MAX
rating = case (time_now.to_date - last_commit_time.to_date).round
when 0..7 then max
when 8..30 then 8
when 31..90 then 6
when 91..180 then 4
when 181..365 then 2
when 366..Float::INFINITY then 1
else MIN
else min
end

rating
Expand Down
26 changes: 17 additions & 9 deletions app/presenters/badge_url_rating_presenter.rb
Expand Up @@ -2,23 +2,31 @@ class BadgeUrlRatingPresenter
BASE_URI = "http://img.shields.io/badge/".freeze
SUBJECT = "Haz%20Commitz".freeze
SEPARATOR = "-".freeze
FORMAT = ".svg".freeze
FORMAT = ".svg?style=flat".freeze

def initialize(rating)
@rating = rating
end

def display
status_colour_segment = case @rating
when 1 then '%3E%201%20year-red' # > 1 year
when 2..3 then '%3C%201%20year-orange' # < 1 year
when 4..5 then '%3C%206%20months-yellow' # < 6 months
when 6..7 then '%3C%203%20months-yellowgreen' # < 3 months
when 8..9 then '%3C%201%20month-brightgreen' # < 1 month
when 10 then '%3C%201%20week-brightgreen' # < 1 week
else 'None-red'
status_colour_segment = case rating
when 1 then "%s-red" % rating_letter
when 2..3 then "%s-orange" % rating_letter
when 4..5 then "%s-yellow" % rating_letter
when 6..7 then "%s-yellowgreen" % rating_letter
when 8..9 then "%s-brightgreen" % rating_letter
when 10 then "%s-brightgreen" % rating_letter
else "None-red"
end

[BASE_URI, SUBJECT, SEPARATOR, status_colour_segment, FORMAT].join
end

private

attr_reader :rating

def rating_letter
LetterRatingPresenter.new(rating).letter
end
end
17 changes: 17 additions & 0 deletions app/presenters/letter_rating_presenter.rb
@@ -0,0 +1,17 @@
class LetterRatingPresenter
def initialize(rating)
@rating = rating
end

def letter
case @rating
when 1 then "F"
when 2..3 then "E"
when 4..5 then "D"
when 6..7 then "C"
when 8..9 then "B"
when 10 then "A"
else "None"
end
end
end
16 changes: 0 additions & 16 deletions app/services/latest_commit_builder.rb

This file was deleted.

26 changes: 0 additions & 26 deletions app/services/repository_fetcher.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/views/repository/show.html.erb
Expand Up @@ -6,7 +6,7 @@
<h4><%= @repo.owner %> / <%= @repo.name %>
<%= render partial: 'github_repo_link', locals: { path: @repo.path } %></h4>

<p>Haz Commitz rating: <span id="rating" class="badge"><%= @repo.rating %></span></p>
<p>Haz Commitz rating: <span id="rating" class="badge"><%= @letter_rating %></span></p>
</div>

<h4>Last commit</h4>
Expand Down
28 changes: 28 additions & 0 deletions lib/app_config.rb
@@ -0,0 +1,28 @@
module AppConfig
class << self
attr_accessor :configuration

delegate :badge_version, to: :configuration

def configuration
@configuration ||= Configuration.new
end

def configure
@configuration ||= Configuration.new
yield(configuration)
end

def reset
@configuration = Configuration.new
end
end

class Configuration
attr_accessor :badge_version

def initialize
@badge_version = "VERSION_001"
end
end
end

0 comments on commit 6413dd3

Please sign in to comment.