# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre # Departamento de Informatica - Universidade Federal do Parana # # This file is part of portalmec. # # portalmec is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # portalmec is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with portalmec. If not, see <http://www.gnu.org/licenses/>. # == Schema Information # # Table name: learning_objects # # id :integer not null, primary key # id_dspace :integer # name :string # author :string # description :text # published_at :datetime # score :float default("0.0") # metadata :jsonb default("{}") # publisher_id :integer # publisher_type :string # object_type_id :integer # created_at :datetime not null # updated_at :datetime not null # views_count :integer default("0") # downloads_count :integer default("0") # likes_count :integer default("0") # shares_count :integer default("0") # state :string default("0") # license_id :integer # link :string # software :string # review_average :float default("0.0") # curator :string # magnetlink :string # terms_of_service :boolean # submission_id :integer # legacy_dspace_id :string # thumbnail_file_name :string # thumbnail_content_type :string # thumbnail_file_size :integer # thumbnail_updated_at :datetime # attachment_id :integer # class LearningObject < ApplicationRecord include Metadatable include Reviewable include Sociable include Downloadable include Stateful include Scoreable include Thumbnailable include Taggable include Subjectable include Stageable include Highlights include Complainable # *current_user* create learning object # *current_user* update learning object # *current_user* destroy learning object include Trackable has_paper_trail has_many :collection_items, as: :collectionable, dependent: :destroy has_many :collections, through: :collection_items has_many :attachments, class_name: 'LearningObject::Attachment', autosave: true # autosave to allow import has_and_belongs_to_many :language belongs_to :publisher, polymorphic: true, counter_cache: true belongs_to :license, optional: true belongs_to :object_type, optional: true belongs_to :attachment, class_name: 'LearningObject::Attachment', optional: true has_one :submission validates :name, :publisher, :object_type, :author, presence: true, unless: :draft? validates :language, unless: :draft?, :length => { :minimum => 1 } validates :id_dspace, presence: true, uniqueness: true, unless: :published? #before_destroy :delete_index validates :terms_of_service, acceptance: true, unless: :draft? default_scope { includes(:object_type, :attachment, :attachments) } scope :missing_thumbnail, ->() { where(thumbnail_file_name: nil) } searchkick language: 'brazilian', match: :word_start, searchable: [:name, :description, :author, :object_type, :tags, :subjects, :educational_stages, :languages], callbacks: :async, index_prefix: Socket.gethostname.downcase, merge_mappings: true, mappings: { "properties": { "published_at": { "type": "date" } } } acts_as_paranoid scope :search_import, -> { includes(:object_type, :tags, :subjects, :educational_stages, :publisher) } def search_data source = !publisher.nil? ? publisher.name : "" type = object_type.try(:id) { name: name, description: description, author: author, object_type: type, score: score, published_at: published_at, tags: tags.map(&:name), subjects: subjects.pluck(:id), educational_stages: educational_stages.pluck(:id), languages: language.pluck(:id), source: source, state: LearningObject.states[state], likes: likes_count, downloads: downloads_count, review_average: review_ratings_average } end def name=(name) write_attribute(:name, name.strip) if !name.blank? end def should_index? (deleted_at.nil? and state == "published") end def delete_index LearningObject.searchkick_index.remove(self) end def categories get_metadata_value_of 'dc.subject.category' end def default_attachment return attachment unless attachment.nil? unless attachments.blank? if object_type.try(:name) == 'VĂdeo' at = attachments.where("name LIKE '%.mp4'").first return at unless at.nil? end at = attachments.where("name NOT LIKE '%.torrent' AND (bundle_name = 'ORIGINAL' OR bundle_name = 'ORE' OR bundle_name = 'TEMP')") # at = attachments.first if at.nil? unless at.blank? update(attachment: at.first) return attachment end end nil end # If a LO has more than one object, this gives the location of the main one def default_attachment_location default_attachment.try(:retrieve_url) end def default_thumbnail return thumbnail unless thumbnail.blank? return nil if attachments.blank? unless default_attachment.blank? return default_attachment.thumbnail unless default_attachment.thumbnail.blank? end attachments.each { |a| return a.thumbnail unless a.thumbnail.blank? } nil end def retrieve_link default_attachment.retrieve_url end def cache_link default_attachment.retrieve_cache_link end # Download link with all relevant objects (currently only one) def download_link return link unless link.blank? default_attachment_location end def ignore_changes super + %w(score views_count downloads_count likes_count shares_count) end ## score methods def normalized_collected max = CollectionItem.where(collectionable_type: 'LearningObject').group(:collectionable_id).order('count_all DESC').count value = CollectionItem.where(collectionable: self).count return 0.0 if max.blank? average_by_max(value, max.first[1]) end def user_category publisher.try('user_category') end def ignore_changes super + %w(score views_count downloads_count likes_count shares_count attachment_id) end def privacy return "public" if self.published? return "private" end def treat_complaintment #Uncomment the line below if an arbitrary number of complaints are necessary to suspend the LO. if (Complaint.where(complainable_id: self.complainable_id).count >= 2) LearningObject.find_by_id(self.complainable_id).update(state: 0); end end def complaint_accept(params) self.destroy end def complaint_reject(params) self.published! end def activity_owner proc { |controller, model| model.try(:publisher) || controller.try(:current_user) } end end