concord-consortium/rigse

View on GitHub
rails/app/models/image.rb

Summary

Maintainability
A
25 mins
Test Coverage
class Image < ApplicationRecord
  attr_accessor :is_reprocessing

  belongs_to :user
  belongs_to :license,
    :class_name  => 'CommonsLicense',
    :primary_key => 'code',
    :foreign_key => 'license_code'

  # resize the attributed version to fit within the default-sized activity window
  has_attached_file :image,
    :styles => {:thumb => {:geometry => "50x50#"},
    :attributed => {:geometry => "650x400>"}},
    :processors => [:attributor_append, :thumbnail]

  before_create :check_image_presence
  before_save :check_image_presence
  before_update :redo_watermark
  after_update :clear_flags
  before_image_post_process :clean_image_filename
  after_post_process :save_image_dimensions

  validates_presence_of :user_id, :name, :publication_status

  scope :published, -> { where(publication_status: 'published') }
  scope :private_status, -> { where(publication_status:'private') }
  scope :draft_status, -> { where(publication_status: 'draft') }
  scope :by_user, proc { |u| where(:user_id => u.id) }
  scope :with_status, proc { |s| where(:publication_status => s ) }
  scope :not_private, -> { where("#{self.table_name}.publication_status IN ('published', 'draft')") }

  scope :visible_to_user, proc { |u| where(
    "#{self.table_name}.publication_status = 'published' OR
      (#{self.table_name}.publication_status = 'draft' AND #{self.table_name}.user_id = ?) OR
      (#{self.table_name}.publication_status = 'private' AND #{self.table_name}.user_id = ?)", u.nil? ? u : u.id , u.nil? ? u : u.id )
  }
  scope :visible_to_user_with_drafts, proc { |u| where(
    "#{self.table_name}.publication_status IN ('published', 'draft') OR
      (#{self.table_name}.publication_status = 'private' AND #{self.table_name}.user_id = ?)", u.nil? ? u : u.id )
  }
  scope :no_drafts, -> { where("#{self.table_name}.publication_status NOT IN ('draft')") }

  scope :like, lambda { |name|
    name = "%#{name}%"
    where("#{self.table_name}.name LIKE ? OR #{self.table_name}.attribution LIKE ?", name, name)
  }

  scope :ordered_by, lambda { |order| order(order) }

  include Changeable
  include Publishable

  self.extend SearchableModel
  @@searchable_attributes = %w{name attribution}
  class <<self
    def can_be_created_by?(user)
      user.has_role?('admin', 'manager', 'researcher', 'author') || (Admin::Settings.default_settings.teachers_can_author? && user.portal_teacher)
    end

    def searchable_attributes
      @@searchable_attributes
    end

    def search_list(options)
      sortMapping  = {
        'Newest'       => "updated_at DESC",
        'Oldest'       => :updated_at,
        'Alphabetical' => :name,
      }

      name = options[:name]
      name_matches = Image.like(name)
      images = options[:only_current_users] ? name_matches.by_user(options[:user]) : name_matches.visible_to_user(options[:user])

      unless options[:sort_order].blank?
        images = images.order(sortMapping[options[:sort_order]])
      end

      if options[:paginate]
        images = images.paginate(:page => options[:page] || 1, :per_page => options[:per_page] || 20)
      end

      images
    end
  end

  def check_image_presence
    if self.image_file_name.blank?
      self.errors.add(:image, :blank)
      # in Rails 5 instead of returning false to terminate the chain you throw :abort
      throw(:abort)
    end
    return true
  end

  def display_name
    res = []
    res << "[#{self.publication_status.upcase}]" if %w(draft private).include?(self.publication_status)
    res << self.name
    res.join(" ")
  end

  def clean_image_filename
    new_filename = image_file_name.downcase.gsub(/[^a-z0-9\-\_\.]+/, '-').gsub(/[-]+/,'-')
    self.image.instance_write(:file_name, new_filename)
  end

  def save_image_dimensions
    geo = Paperclip::Geometry.from_file(image.queued_for_write[:attributed])
    self.width  = geo.width.round
    self.height = geo.height.round
  end

  # when the attribution changes
  # we need to trigger this, but it can recurse without flag
  def redo_watermark
    return true if self.is_reprocessing
    self.is_reprocessing = true
    if attribution_changed?
      if self.image
        self.image.reprocess!
      end
    end
  end

  def clear_flags
    self.is_reprocessing = false
  end

  def dimensions
    "%{width}x%{height}" % {
      :width  => self.width,
      :height => self.height
    }
  end

  def image_size
    size = 0
    begin
        size   = self.image.size || 0
    rescue ::Exception => e
      Rails.logger.warn("Unexpected error sizing image in models/image.rb:  #{e}")
    end
    size
  end
end