SpeciesFileGroup/taxonworks

View on GitHub
app/models/pinboard_item.rb

Summary

Maintainability
A
0 mins
Test Coverage
# A PinboardItem is an object on a user's pinboard.
#
# @!attribute pinned_object_id
#   @return [Integer]
#      the id of the object being pinned
#
# @!attribute pinned_object_type
#   @return [String]
#     the type of the object being pinned
#
# @!attribute user_id
#   @return [Integer]
#      this identifies the pinboard
#
# @!attribute project_id
#   @return [Integer]
#   the project ID for which the object is pinned
#
# @!attribute position
#   @return [Integer]
#     the relative position of this object, nests within object type
#
# @!attribute is_inserted
#   @return [Boolean]
#     when true this pinboard item is automatically inserted into accepting form fields
#
# @!attribute is_cross_project
#   @return [Boolean]
#     pinboard item will show up regardless of which project is selected
#
# @!attribute inserted_count
#   @return [Integer]
#     (not implemented) - the number of times this item has been inserted
#
class PinboardItem < ApplicationRecord
  include Housekeeping

  acts_as_list scope: [:project_id, :pinned_object_type, :user_id]

  belongs_to :user
  belongs_to :pinned_object, polymorphic: true, validate: true, inverse_of: :pinboard_items

  before_validation  :validate_is_cross_project

  validates_presence_of :user_id, :pinned_object
  validates_uniqueness_of :user_id, scope: [ :pinned_object_id, :pinned_object_type, :project_id ]

  after_save :update_insertable

  scope :for_object, -> (object) { where(pinned_object_id: object.id, pinned_object_type: object.class.to_s) }

  def self.reorder_by(pinboard_item_ids)
    pinboard_item_ids.each_with_index do |id, i|
      PinboardItem.find(id).update_attribute(:position, i)
    end
  end

  def self.clear(klass: nil, user_id: nil, project_id: nil)
    PinboardItem.where(user_id:, project_id:, pinned_object_type: klass).delete_all
  end

  def is_inserted?
    is_inserted.present?
  end

  def is_cross_project?
    is_cross_project.present?
  end

  protected

  def update_insertable
    if is_inserted?
      r = PinboardItem.where(project_id:, pinned_object_type:, user_id:).where.not(id:)
      if pinned_object_type == 'ControlledVocabularyTerm'
        n = pinned_object.class.name
        r.each do |i|
          i.update_column(:is_inserted, false) if i.pinned_object.type == n
        end
      else
        r.update_all(is_inserted: false)
      end
    end
  end

  def validate_is_cross_project
    errors.add(:is_cross_project, 'model is not a cross project model') if is_cross_project? && !pinned_object.class.ancestors.map(&:name).include?('Shared::SharedAcrossProjects')
  end

end