require 'open-uri' # allows to load URLs using open() require 'json' class Package < ActiveRecord::Base # 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 # 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_xversion_y -1 else 0 end end end