app/models/asset.rb
class Asset
include Mongoid::Document
include Mongoid::Timestamps
include MongoSearch::Searchable
include Mongoid::Paperclip
IMAGE_REGEX = /(jpg|jpeg|gif|png)/
NORMALIZED_EXTENSIONS = { ".jpeg" => ".jpg" }
validates_with PaperclipValidator
field :file_content_type, type: String
field :file_file_name, type: String
field :file_file_size, type: Integer
field :file_fingerprint, type: String
field :file_dimensions, type: Hash, default: {}
field :tags, type: String
field :page_cache, type: Array, default: []
text_search_in :file_file_name, :tags, :search_page_cache
has_mongoid_attached_file :file,
default_style: :admin,
max_size: 50.megabytes,
url: '/system/:attachment/:mon_year/:id/:style/:filename',
path: ':rails_root/public:url',
only_process: [:admin],
styles: Slices::Config.asset_styles,
convert_options: Slices::Config.asset_convert_options
before_file_post_process :is_image?
after_file_post_process :store_dimensions, if: :is_image?
before_save :reset_file_dimensions!, if: :file_fingerprint_changed?
before_save :rename_file
after_destroy :remove_asset_from_pages
has_and_belongs_to_many :pages
index({ file_fingerprint: 1 })
index({ _keywords: 1 }, { background: true })
def self.make(*args)
Slices::Asset::Maker.run(*args)
end
def self.search_for(term = nil)
if term.present?
all.ordered_active.text_search term
else
all.ordered_active
end
end
def self.ordered_active
desc(:created_at)
end
def as_json(options = nil)
{
id: id.to_s,
name: name,
file_file_name: file_file_name,
file_file_size: file_file_size,
file_content_type: file_content_type,
asset_url: admin_image_url,
original_url: file.url(:original),
errors: errors,
created_at: created_at,
tags: tags,
pages: page_cache
}
end
# Returns the url for the asset style. The style is created if it has not already
# been generated
#
# @param [Symbol] style The asset style is defined in Slice::Config.asset_styles
def url_for(style)
reprocess_for(style)
file.url(style)
end
# Returns the dimensions the asset style. The style is created if it has not already
# been generated
#
# asset.dimensions_for(:main)
# "100x100"
#
# @param [Symbol] style The asset style is defined in Slice::Config.asset_styles
def dimensions_for(style)
reprocess_for(style)
file_dimensions[style.to_s]
end
def reprocess_for(style)
if file.styles.has_key?(style) && ! file_dimensions.has_key?(style.to_s)
file.reprocess!(style)
save
end
rescue Errors::NotIdentifiedByImageMagickError, Errno::ENOENT
end
def reprocess_for!(style)
file.clear(style)
file_dimensions.delete(style.to_s)
file.flush_deletes
reprocess_for(style)
end
def store_dimensions
file.queued_for_write.each do |style, adapter|
geometry = Paperclip::Geometry.from_file(adapter)
self.file_dimensions[style.to_s] = geometry.to_s
end
end
def is_image?
file_content_type.present? && file_content_type.match(IMAGE_REGEX).present?
end
def file_extension
if file_file_name.present?
file_file_name.split('.').last.downcase
else
''
end
end
def admin_image_url
if !new_record? && is_image?
url_for(:admin)
end
end
def remove_asset_from_pages
pages.each do |page|
page.remove_asset(self)
page.save if page.changed?
end
end
def name
@new_name || file_file_name
end
def name=(new_name)
@new_name = new_name
end
def update_page_cache
self.page_cache = pages.collect do |page|
{ id: page.id, name: page.name, path: page.path }
end
end
def search_page_cache
page_cache.inject([]) do |memo, page|
memo << page['name']
memo << page['path']
end.join ' '
end
# Reset all stored file dimensions except for the origin and admin styles,
# this is used when a new version of an asset is uploaded
#
def reset_file_dimensions!
self.file_dimensions.keys.each do |key|
next if key == 'original' || key == 'admin'
self.file_dimensions.delete key
end
end
private
def rename_file
return if @new_name.blank?
new_file_name = sanitize(@new_name)
Slices::Asset::Rename.run(file, new_file_name)
file.instance_write(:file_name, new_file_name)
set_keywords
@new_name = nil
end
def sanitize(filename)
file.send(:cleanup_filename, filename).tap do |name|
if self.file && self.file.original_filename
extension = normalized_extension
name << extension unless name.ends_with?(extension)
end
end
end
def normalized_extension
extname = File.extname(file.original_filename).downcase
NORMALIZED_EXTENSIONS.fetch(extname, extname)
end
end