module Hubstats class Repo < ActiveRecord::Base def self.record_timestamps; false; end # Various checks that can be used to filter and find info about repos. scope :with_recent_activity, lambda {|start_date, end_date| where("hubstats_repos.updated_at BETWEEN ? AND ?", start_date, end_date).order("updated_at DESC")} scope :with_id, lambda {|repo_id| where(id: repo_id.split(',')) if repo_id} # Public - Counts all of the deploys for selected repo that occurred between the start_date and end_date. # # start_date - the start of the date range # end_date - the end of the data range # # Returns - count of deploys scope :deploys_count, lambda {|start_date, end_date| select("hubstats_repos.id as repo_id") .select("IFNULL(COUNT(DISTINCT hubstats_deploys.id),0) AS deploy_count") .joins(sanitize_sql_array(["LEFT JOIN hubstats_deploys ON hubstats_deploys.repo_id = hubstats_repos.id AND (hubstats_deploys.deployed_at BETWEEN ? AND ?)", start_date, end_date])) .group("hubstats_repos.id") } # Public - Counts all of the comments for selected repo that occurred between the start_date and end_date. # # start_date - the start of the date range # end_date - the end of the data range # # Returns - count of comments scope :comments_count, lambda {|start_date, end_date| select("hubstats_repos.id as repo_id") .select("IFNULL(COUNT(DISTINCT hubstats_comments.id),0) AS comment_count") .joins(sanitize_sql_array(["LEFT JOIN hubstats_comments ON hubstats_comments.repo_id = hubstats_repos.id AND (hubstats_comments.created_at BETWEEN ? AND ?)", start_date, end_date])) .group("hubstats_repos.id") } # Public - Counts all of the merged pull requests for selected repo that occurred between the start_date and end_date. # # start_date - the start of the date range # end_date - the end of the data range # # Returns - count of pull requests scope :pull_requests_count, lambda {|start_date, end_date| select("hubstats_repos.id as repo_id") .select("IFNULL(COUNT(DISTINCT hubstats_pull_requests.id),0) AS pull_request_count") .joins(sanitize_sql_array(["LEFT JOIN hubstats_pull_requests ON hubstats_pull_requests.repo_id = hubstats_repos.id AND (hubstats_pull_requests.merged_at BETWEEN ? AND ?) AND hubstats_pull_requests.merged = ?", start_date, end_date, true])) .group("hubstats_repos.id") } # Public - Averages all of the additions and deletions of the merged PRs for selected repo. # # start_date - the start of the date range # end_date - the end of the data range # # Returns - the average additions and deletions scope :averages, lambda {|start_date, end_date| select("hubstats_repos.id as repo_id") .select("ROUND(IFNULL(AVG(hubstats_pull_requests.additions),0)) AS average_additions") .select("ROUND(IFNULL(AVG(hubstats_pull_requests.deletions),0)) AS average_deletions") .joins(sanitize_sql_array(["LEFT JOIN hubstats_pull_requests ON hubstats_pull_requests.repo_id = hubstats_repos.id AND hubstats_pull_requests.merged = ? AND (hubstats_pull_requests.merged_at BETWEEN ? AND ?)", true, start_date, end_date])) .group("hubstats_repos.id") } # Public - Joins all of the metrics together for selected repository: average additions and deletions, comments, pull requests, and deploys. # # start_date - the start of the date range # end_date - the end of the data range # # Returns - all of the stats about the repo scope :with_all_metrics, lambda {|start_date, end_date| select("hubstats_repos.*, deploy_count, pull_request_count, comment_count, average_additions, average_deletions") .joins("LEFT JOIN (#{averages(start_date, end_date).to_sql}) AS averages ON averages.repo_id = hubstats_repos.id") .joins("LEFT JOIN (#{pull_requests_count(start_date, end_date).to_sql}) AS pull_requests ON pull_requests.repo_id = hubstats_repos.id") .joins("LEFT JOIN (#{comments_count(start_date, end_date).to_sql}) AS comments ON comments.repo_id = hubstats_repos.id") .joins("LEFT JOIN (#{deploys_count(start_date, end_date).to_sql}) AS deploys ON deploys.repo_id = hubstats_repos.id") .group("hubstats_repos.id") } has_many :pull_requests has_many :deploys has_many :comments belongs_to :owner, :class_name => "User", :foreign_key => "id" # Public - Makes a new repository based on a GitHub webhook. Sets a user (owner) based on users that are already in the database. # # github_repo - the info about the new or updated repository # # Returns - the repository def self.create_or_update(github_repo) github_repo = github_repo.to_h.with_indifferent_access if github_repo.respond_to? :to_h repo_data = github_repo.slice(*column_names.map(&:to_sym)) if github_repo[:owner] user = Hubstats::User.create_or_update(github_repo[:owner]) repo_data[:owner_id] = user[:id] end repo = where(:id => repo_data[:id]).first_or_create(repo_data) return repo if repo.update_attributes(repo_data) Rails.logger.warn repo.errors.inspect end # Public - Designed so that the list of repositories can be ordered based on deploys, pulls, comments, additions, deletions, or name. # if none of these are selected, then the default is to order by pull request count in descending order. # # order_params - the param of what the repos should be sorted by # # Returns - the repo data ordered def self.custom_order(order_params) if order_params order = order_params.include?('asc') ? "ASC" : "DESC" case order_params.split('-').first when 'deploys' order("deploy_count #{order}") when 'pulls' order("pull_request_count #{order}") when 'comments' order("comment_count #{order}") when 'additions' order("average_additions #{order}") when 'deletions' order("average_deletions #{order}") when 'name' order("name #{order}") else order("pull_request_count #{order}") end else order("pull_request_count DESC") end end # Public - Designed to make a path for the show page when a repository is selected. # # Returns - the show page of self.name def to_param self.name end end end