debshots/app/models/package.rb

114 lines
3.9 KiB
Ruby

require 'open-uri' # allows to load URLs using open()
require 'json'
class Package < ApplicationRecord
# PostgreSQL-based full-text search:
# https://github.com/Casecommons/pg_search
include PgSearch
# TODO: Make search weighted on users' rating
pg_search_scope :general_search,
# :against => [:name, :description, :long_description],
:against => [
[:name, 'A'],
[:description, 'B'],
[:long_description, 'C']
],
:using => {
:tsearch => {:dictionary => "english"}
}
# I am using "destroy_all" here so that when a package gets destroys the
# callbacks for all dependent screenshots are executed - thus removing the
# screenshot files from disk.
has_many :screenshots, :inverse_of=>:package, :dependent => :destroy
# default_scope {
# order('name ASC')
# }
# Return a query of all packages that have screenshots
def self.with_screenshots
# Query for all packages who's ID appears in a screenshot's "package_id" field
subselect = Screenshot.select(:package_id)
where(id: subselect )
end
# Return a query of all packages that have screenshots
def self.without_screenshots
# Query for all packages who's ID does not appear in a screenshot's "package_id" field
subselect = Screenshot.select(:package_id)
where.not(id: subselect)
end
# Packages that need screenshots and have most visits.
# These packages are most likely to need a screenshot.
def self.without_screenshots_most_visits
self.without_screenshots.order(visits: :desc)
end
# Return a query of all approved/public screenshots of this package
def screenshots_approved
self.screenshots.find_by(approved: true)
end
# Return a query of all approved/public screenshots of this package
def screenshots_pending
self.screenshots.where('approved=false or markedfordelete=true')
end
# Return a list of packages that have unapproved screenshots
def self.requiring_moderation
self.joins(:screenshots).where(screenshots: {approved:false}).distinct(:name)
end
# Get all screenshots and have them sorted descendingly by their version number (Debian style).
def screenshots_sorted_by_version
self.screenshots.to_a.sort { |x,y| version_compare(x.version,y.version) }
end
# Get reviews of this package from the Ubuntu API
def ubuntu_reviews
# Use the URL defined in the configuration to get a JSON string
json = open(Rails.configuration.ubuntu_reviews_api_url % self.name).read
# Turn JSON into a Ruby data structure
json = JSON.parse(json)
# Only show english reviews
# TODO: Support further languages
json = json.select {|x| x['language']=='en'}
# Sort by 'usefulness_total' (how many people found this review useful)
json = json.sort { |x,y| y['usefulness_total'].to_i <=> x['usefulness_total'].to_i}
return json
end
# Return the newest screenshot that is not newer than the given version.
# This algorithm collects all image
# versions of a package and determines the (second) newest version.
# E.g. if there are version 1.0 and 2.0 and the user is looking for
# a screenshot of version 1.5 then the 1.0 version is returned.
# This way the user does not see a screenshot of version 2.0 because
# 2.0 might contain features that were not there in version 1.5.
def best_screenshot_for_version(version)
sorted_screenshots = self.screenshots_sorted_by_version
sorted_screenshots.each do |ss|
logger.debug { "Comparing version #{version} against #{ss.version}" }
return ss if version_compare(version, ss.version)<=0
end
return sorted_screenshots.last
end
private
def version_compare(x,y)
x = '0' unless x.present?
y = '0' unless y.present?
version_x = DebImporter::Version.new(x)
version_y = DebImporter::Version.new(y)
if version_x<version_y
1
elsif version_x>version_y
-1
else
0
end
end
end