module Locomotive class ThemeAsset include Locomotive::Mongoid::Document ## extensions ## include Concerns::Shared::SiteScope include Concerns::Asset::Types include Concerns::Asset::Checksum ## fields ## field :local_path field :content_type, type: Symbol field :width, type: Integer field :height, type: Integer field :size, type: Integer field :folder, default: nil mount_uploader :source, ThemeAssetUploader, mount_on: :source_filename, validate_integrity: true # indexes index site_id: 1, local_path: 1 ## callbacks ## before_validation :check_for_folder_changes before_validation :sanitize_folder before_validation :build_local_path ## validations ## validates_presence_of :source, on: :create validates_uniqueness_of :local_path, scope: :site_id ## named scopes ## ## methods ## def touch_site_attribute :template_version end def stylesheet_or_javascript? self.stylesheet? || self.javascript? end def local_path(short = false) if short && self.read_attribute(:local_path) self.read_attribute(:local_path).split('/')[1..-1].join('/') else self.read_attribute(:local_path) end end def self.all_grouped_by_folder(site) assets = site.theme_assets.order_by(:slug.asc) assets.group_by { |a| a.folder.split('/').first.to_sym } end def self.checksums {}.tap do |hash| self.only(:local_path, :checksum).each do |asset| hash[asset.local_path] = asset.checksum end end end protected def safe_source_filename self.source_filename || self.source.send(:original_filename) rescue nil end def sanitize_folder self.folder = self.content_type.to_s.pluralize if self.folder.blank? # no accents, no spaces, no leading and ending trails self.folder = ActiveSupport::Inflector.transliterate(self.folder).gsub(/(\s)+/, '_').gsub(/^\//, '').gsub(/\/$/, '') # folder should begin by a root folder if (self.folder =~ /^(stylesheets|javascripts|images|media|fonts|pdfs|others|misc)($|\/)+/).nil? self.folder = File.join(self.content_type.to_s.pluralize, self.folder) end end def build_local_path if filename = self.safe_source_filename self.local_path = File.join(self.folder, filename) else nil end end def check_for_folder_changes # https://github.com/jnicklas/carrierwave/issues/330 # https://github.com/jnicklas/carrierwave-mongoid/issues/23 if self.persisted? && self.folder_changed? && !self.changed_attributes.key?('source_filename') # a simple way to rename a file old_asset = self.class.where(_id: self._id).first # bypass memoization by mongoid file = old_asset.source.file file.content_type = File.mime_type?(file.path) if file.content_type.nil? self.source = file self.changed_attributes['source_filename'] = nil # delete the old file end end end end