metadata file & url

This commit is contained in:
f 2019-11-07 13:08:14 -03:00
parent 7ddc4e6150
commit 9c54518c8e
No known key found for this signature in database
GPG key ID: 2AE5A13E321F953D
9 changed files with 153 additions and 96 deletions

106
app/models/metadata_file.rb Normal file
View file

@ -0,0 +1,106 @@
# frozen_string_literal: true
# Define un campo de archivo
class MetadataFile < MetadataTemplate
# Una ruta vacía a la imagen con una descripción vacía
def default_value
{ 'path' => nil, 'description' => nil }
end
def empty?
value == default_value
end
def validate
super
errors << I18n.t('metadata.image.path_required') if path_missing?
errors.compact!
errors.empty?
end
# Determina si necesitamos la imagen pero no la tenemos
def path_missing?
required && !value['path'].blank?
end
# Determina si el archivo ya fue subido
def uploaded?
value['path'].is_a?(String)
end
# Determina si la ruta es opcional pero deja pasar si la ruta se
# especifica
def path_optional?
!required && value['path'].blank?
end
# Asociar la imagen subida al sitio y obtener la ruta
def save
return true if uploaded?
return true if path_optional?
return false unless hardlink.zero?
# Modificar el valor actual
value['path'] = relative_destination_path
true
end
def to_param
{ name => %i[description path] }
end
# Almacena el archivo en el sitio y lo devuelve
#
# @return ActiveStorage::Attachment
def static_file
ActiveRecord::Base.connection_pool.with_connection do
if uploaded?
blob = ActiveStorage::Blob.find_by(key: key_from_path)
@static_file ||= site.static_files.find_by(blob_id: blob.id)
elsif site.static_files.attach(value['path'])
@static_file ||= site.static_files.last
end
end
end
private
def key_from_path
# XXX: No podemos usar self#extension porque en este punto todavía
# no sabemos el static_file
File.basename(value['path'], '.*')
end
# Hacemos un link duro para colocar el archivo dentro del repositorio
# y no duplicar el espacio que ocupan. Esto requiere que ambos
# directorios estén dentro del mismo punto de montaje.
def hardlink
FileUtils.mkdir_p File.dirname(destination_path)
FileUtils.ln uploaded_path, destination_path
end
def extension
static_file.blob.content_type.split('/').last
end
# Obtener la ruta al archivo
# https://stackoverflow.com/a/53908358
def uploaded_relative_path
ActiveStorage::Blob.service.path_for(static_file.key)
end
def uploaded_path
Rails.root.join uploaded_relative_path
end
def relative_destination_path
File.join('public', [static_file.key, extension].join('.'))
end
def destination_path
File.join(site.path, relative_destination_path)
end
end

View file

@ -1,37 +1,16 @@
# frozen_string_literal: true
# Define un campo de imagen
# TODO: Validar que sea una imagen
class MetadataImage < MetadataTemplate
# Una ruta vacía a la imagen con una descripción vacía
def default_value
{ 'path' => nil, 'description' => nil }
end
def empty?
value == default_value
end
class MetadataImage < MetadataFile
def validate
super
errors << I18n.t('metadata.image.path_required') if path_missing?
errors << I18n.t('metadata.image.not_an_image') unless image?
errors.compact!
errors.empty?
end
# Determina si necesitamos la imagen pero no la tenemos
def path_missing?
required && !value['path'].blank?
end
# Determina si el archivo ya fue subido
def uploaded?
value['path'].is_a?(String)
end
# Determina si es una imagen antes de subirla
def image?
if value['path'].is_a? ActionDispatch::Http::UploadedFile
@ -44,78 +23,4 @@ class MetadataImage < MetadataTemplate
true
end
end
# Determina si la ruta es opcional pero deja pasar si la ruta se
# especifica
def path_optional?
!required && value['path'].blank?
end
# Asociar la imagen subida al sitio y obtener la ruta
def save
return true if uploaded?
return true if path_optional?
return false unless hardlink.zero?
# Modificar el valor actual
value['path'] = relative_destination_path
true
end
def to_param
{ name => %i[description path] }
end
# Almacena el archivo en el sitio y lo devuelve
#
# @return ActiveStorage::Attachment
def static_file
ActiveRecord::Base.connection_pool.with_connection do
if uploaded?
blob = ActiveStorage::Blob.find_by(key: key_from_path)
@static_file ||= site.static_files.find_by(blob_id: blob.id)
elsif site.static_files.attach(value['path'])
@static_file ||= site.static_files.last
end
end
end
private
def key_from_path
# XXX: No podemos usar self#extension porque en este punto todavía
# no sabemos el static_file
File.basename(value['path'], '.*')
end
# Hacemos un link duro para colocar el archivo dentro del repositorio
# y no duplicar el espacio que ocupan. Esto requiere que ambos
# directorios estén dentro del mismo punto de montaje.
def hardlink
FileUtils.mkdir_p File.dirname(destination_path)
FileUtils.ln uploaded_path, destination_path
end
def extension
static_file.blob.content_type.split('/').last
end
# Obtener la ruta al archivo
# https://stackoverflow.com/a/53908358
def uploaded_relative_path
ActiveStorage::Blob.service.path_for(static_file.key)
end
def uploaded_path
Rails.root.join uploaded_relative_path
end
def relative_destination_path
File.join('public', [static_file.key, extension].join('.'))
end
def destination_path
File.join(site.path, relative_destination_path)
end
end

View file

@ -0,0 +1,4 @@
# frozen_string_literal: true
# Un campo de URL
class MetadataUrl < MetadataString; end

View file

@ -0,0 +1,7 @@
%tr{ id: attribute }
%th= post_label_t(attribute, :path, post: post)
%td
- if metadata.value['path'].present?
%figure
= link_to url_for(metadata.static_file)
%figcaption= metadata.value['description']

View file

@ -0,0 +1,3 @@
%tr{ id: attribute }
%th= post_label_t(attribute, post: post)
%td= metadata.value

View file

@ -0,0 +1,3 @@
%tr{ id: attribute }
%th= post_label_t(attribute, post: post)
%td= link_to metadata.value

View file

@ -0,0 +1,22 @@
.form-group
- if metadata.uploaded?
= hidden_field_tag "post[#{attribute}][path]", metadata.value['path']
.custom-file
= file_field(*field_name_for('post', attribute, :path),
**field_options(attribute, metadata),
class: "custom-file-input #{invalid(post, attribute)}",
data: { preview: "#{attribute}-preview" })
= label_tag "post_#{attribute}_path",
post_label_t(attribute, :path, post: post), class: 'custom-file-label'
= render 'posts/attribute_feedback',
post: post, attribute: [attribute, :path], metadata: metadata
.form-group
= label_tag "post_#{attribute}_description",
post_label_t(attribute, :description, post: post)
= text_field(*field_name_for('post', attribute, :description),
value: metadata.value['description'],
**field_options(attribute, metadata))
= render 'posts/attribute_feedback',
post: post, attribute: [attribute, :description], metadata: metadata

View file

@ -0,0 +1 @@
-# nada

View file

@ -0,0 +1,6 @@
.form-group
= label_tag "post_#{attribute}", post_label_t(attribute, post: post)
= url_field 'post', attribute, value: metadata.value,
**field_options(attribute, metadata)
= render 'posts/attribute_feedback',
post: post, attribute: attribute, metadata: metadata