115 lines
3.7 KiB
Ruby
115 lines
3.7 KiB
Ruby
require 'open-uri' # allows to load URLs using open()
|
|
require 'json'
|
|
require 'deb_importer'
|
|
|
|
class Package < ApplicationRecord
|
|
# PostgreSQL-based full-text search:
|
|
# https://github.com/Casecommons/pg_search
|
|
include PgSearch::Model
|
|
# 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,
|
|
-> { order(id: :desc) },
|
|
inverse_of: :package,
|
|
dependent: :destroy
|
|
|
|
# default_scope {
|
|
# order('name ASC')
|
|
# }
|
|
|
|
# Define the parameter(s) used for a /package/:name URL to an instance of this model
|
|
def to_param
|
|
name
|
|
end
|
|
|
|
# Return the first paragraph of the long description.
|
|
def long_description_first_paragraph
|
|
long_description.split(/\n\.\n/).first if long_description
|
|
end
|
|
|
|
# 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 approved screenshots
|
|
def self.with_public_screenshots
|
|
# Query for all packages who's ID appears in a screenshot's "package_id" field
|
|
subselect = Screenshot.visible.approved.select(:package_id)
|
|
where(id: subselect)
|
|
end
|
|
|
|
# Return a list of packages that have screenshots to be moderated
|
|
def self.need_moderation
|
|
Package.joins(:screenshots).where('screenshots.approved=false').distinct(:name)
|
|
end
|
|
|
|
# Return a query of all packages that do not 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
|
|
|
|
# Get all screenshots and have them sorted descendingly by their version number (Debian style).
|
|
def screenshots_sorted_by_version
|
|
screenshots.approved.to_a.sort { |x, y| version_compare(x.version, y.version) }
|
|
end
|
|
|
|
# Return all approved screenshots for this package
|
|
def approved_screenshots
|
|
screenshots.approved
|
|
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 = 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
|
|
sorted_screenshots.last
|
|
end
|
|
|
|
# Return the part of the version up to the first - or +
|
|
def upstream_version
|
|
version.split(/[-+]/).first
|
|
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
|