diff --git a/.rubocop.yml b/.rubocop.yml index 9e60da6c..487320c0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,7 @@ AllCops: - TargetRubyVersion: '2.7' - NewCops: enable - + TargetRubyVersion: "3.1" + NewCops: "enable" Style/AsciiComments: Enabled: false +Style/MultilineBlockChain: + Enabled: false diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index b33ccf4d..8ad46032 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -15,6 +15,22 @@ module ActiveStorage end end + # Obtiene Blob#key desde la ubicación, la inversa de path_for + # + # @param :path [String,Pathname] + # @return [String] + def key_from_path(path) + Pathname.new(path).dirname.basename.to_s + end + + # Elimina el archivo + # + # @param :key [String] + # @return [nil] + def delete(key) + FileUtils.rm_f(path_for(key)) + end + # Solo copiamos el archivo si no existe # # @param :key [String] @@ -87,7 +103,15 @@ module ActiveStorage # @param :key [String] # @return [String] def path_for(key) - File.join root, folder_for(key), filename_for(key) + File.join absolute_path_for(key), filename_for(key) + end + + # La ruta absoluta del directorio donde se almacena el archivo + # + # @param :key [String] + # @return [String] + def absolute_path_for(key) + File.join root, folder_for(key) end # @return [Site] diff --git a/app/models/metadata_file.rb b/app/models/metadata_file.rb index 3ac89c9b..e5b2f1ce 100644 --- a/app/models/metadata_file.rb +++ b/app/models/metadata_file.rb @@ -88,7 +88,7 @@ class MetadataFile < MetadataTemplate # # @return [String] def key_from_path - @key_from_path ||= pathname.dirname.basename.to_s + @key_from_path ||= site.blob_service.key_from_path(path: pathname) end def path? diff --git a/app/models/site/index.rb b/app/models/site/index.rb index cfa4030a..9d7ca08f 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -10,10 +10,13 @@ class Site included do has_many :indexed_posts, dependent: :destroy - MODIFIED_STATUSES = %i[added modified].freeze - DELETED_STATUSES = %i[deleted].freeze + MODIFIED_STATUSES = %i[added modified renamed].freeze LOCALE_FROM_PATH = /\A_/.freeze + def blob_service + @blob_service ||= ActiveStorage::Service::JekyllService.build_for_site(site: self) + end + def index_posts! Site.transaction do docs.each(&:index!) @@ -67,7 +70,7 @@ class Site # Obtiene todos los archivos a reindexar # - # @return [Array] + # @return [Array] def indexable_posts @indexable_posts ||= diff_with_head.each_delta.select do |delta| @@ -77,12 +80,25 @@ class Site end end + # Encuentra todos los archivos estáticos a reindexar, si fueron + # borrados necesitamos saber la ubicación anterior, si son nuevos, + # la nueva. + # + # @return [Array] + def indexable_static_files + @indexable_static_files ||= + diff_with_head.each_delta.select do |delta| + ( + delta.status == :deleted && + delta.old_file[:path].start_with?('public/') + ) || delta.new_file[:path].start_with?('public/') + end + end + # Elimina los artículos eliminados o que cambiaron de ubicación # del índice def remove_deleted_posts! - indexable_posts.select do |delta| - DELETED_STATUSES.include? delta.status - end.each do |delta| + indexable_posts.select(&:deleted?).each do |delta| locale, path = locale_and_path_from(delta.old_file[:path]) indexed_posts.destroy_by(locale: locale, path: path).tap do |destroyed_posts| @@ -93,6 +109,45 @@ class Site end end + # Elimina de ActiveStorage los archivos borrados, renombrados o + # modificados, para poder recalcular su contenido y nueva + # ubicación. + # + # Los renombrados o modificados se vuelven a crear en + # reindex_modified_static_files! + def remove_deleted_or_renamed_static_files! + indexable_static_files.select do |delta| + delta.deleted? || delta.modified? || delta.renamed? + end.each do |delta| + key = blob_service.key_from_path(delta.old_file[:path]) + + static_files.blobs.find_by(service_name: name, key: key).tap do |blob| + next unless blob + + transaction do + static_files.where(blob_id: blob.id).destroy_all + blob.destroy + end + end + end + end + + # Reindexa los archivos estáticos modificados + def reindex_modified_static_files! + indexable_static_files.select do |delta| + MODIFIED_STATUSES.include?(delta.status) || delta.renamed? + end.each do |delta| + transaction do + path = blob_service.absolute_path_for(delta.new_file[:path].sub(%r{\Apublic/}, '')) + key = blob_service.key_from_path(path) + pathname = Pathname.new(path) + blob = ActiveStorage::Blob.create_after_unfurling!(key: key, io: pathname.open, filename: pathname.basename, service_name: name) + + ActiveStorage::Attachment.create!(name: 'static_files', record: self, blob: blob) + end + end + end + # Reindexa artículos que cambiaron de ubicación, se agregaron # o fueron modificados def reindex_modified_posts!