WIP de subir archivos

This commit is contained in:
f 2018-07-02 17:45:32 -03:00
parent c791620f3c
commit a1fe309e6a
No known key found for this signature in database
GPG key ID: F3FDAB97B5F9F7E7
10 changed files with 139 additions and 5 deletions

View file

@ -40,6 +40,10 @@ gem 'jquery-rails'
gem 'font-awesome-rails'
gem 'exception_notification'
gem 'whenever', require: false
gem 'carrierwave'
gem 'carrierwave-i18n'
gem 'mini_magick'
gem 'carrierwave-bombshelter'
group :development, :test do
gem 'pry'

View file

@ -75,6 +75,15 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
carrierwave (1.2.3)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
carrierwave-bombshelter (0.2.2)
activesupport (>= 3.2.0)
carrierwave
fastimage
carrierwave-i18n (0.2.0)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2)
@ -101,6 +110,7 @@ GEM
actionmailer (>= 4.0, < 6)
activesupport (>= 4.0, < 6)
execjs (2.7.0)
fastimage (2.1.3)
ffi (1.9.23)
font-awesome-rails (4.7.0.4)
railties (>= 3.2, < 6.0)
@ -161,6 +171,10 @@ GEM
mini_mime (>= 0.1.1)
mercenary (0.3.6)
method_source (0.9.0)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_magick (4.8.0)
mini_mime (1.0.0)
mini_portile2 (2.3.0)
minitest (5.11.3)
@ -296,6 +310,9 @@ DEPENDENCIES
capistrano-rails
capistrano-rbenv
capybara (~> 2.13)
carrierwave
carrierwave-bombshelter
carrierwave-i18n
commonmarker
dotenv-rails
email_address
@ -306,6 +323,7 @@ DEPENDENCIES
jekyll
jquery-rails
listen (>= 3.0.5, < 3.2)
mini_magick
pry
puma (~> 3.7)
rails (~> 5.1.4)

View file

@ -199,9 +199,23 @@ class Post
# HashWithIndifferentAccess
attrs = attrs.to_h.map do |k,v|
t = template_fields.find { |t| t.key == k }
if t && t.nested?
v = t.array? ? v.values.map(&:to_h) : v.to_h
if t
# Subir la imagen!
if t.image?
begin
i = Post::ImageUploader.new(site)
i.store! v.tempfile
v = i.url
rescue CarrierWave::IntegrityError => e
v = e.message
end
end
if t.nested?
v = t.array? ? v.values.map(&:to_h) : v.to_h
end
end
{ k => v }
end.reduce(Hash.new, :merge).stringify_keys
@ -209,10 +223,20 @@ class Post
end
# Requisitos para que el post sea válido
# TODO verificar que el id sea único
# TODO validar los parametros de la plantilla
def validate
add_error validate: I18n.t('posts.errors.date') unless date.is_a? Time
add_error validate: I18n.t('posts.errors.title') if title.blank?
# TODO verificar que el id sea único
# XXX este es un principio de validación de plantillas, aunque no es
# recursivo
template_fields.each do |tf|
# TODO descubrir de mejor forma que el archivo no es del formato
# correcto
if tf.image? && get_front_matter(tf.key).split('/').to_a.count <= 1
add_error validate: get_front_matter(tf.key)
end
end
end
def valid?

View file

@ -0,0 +1,39 @@
# Una clase que permite adjuntar imágenes a artículos
class Post::ImageUploader < CarrierWave::Uploader::Base
attr_accessor :site
# Necesitamos pasar el sitio para poder acceder a los archivos locales
def initialize(site)
super
@site = site
end
# Solo aceptamos imágenes
def content_type_whitelist
/\Aimage\//
end
# Devuelve la ubicación del directorio dentro de Jekyll, para eso,
# tenemos que tener acceso al sitio que estamos editando
def store_dir
File.join site.path, 'public', 'images'
end
# Almacenar en el 'tmp' local
def cache_dir
File.join Rails.root, 'tmp', 'images'
end
# XXX los nombres de los archivos siempre son únicos, no chequeamos si
# están repetidos.
def filename
[SecureRandom.uuid, '.', file.extension].join
end
# Obtener la URL dentro del proyecto de Jekyll
def url
CGI.unescape(super).remove site.path
end
end

View file

@ -4,7 +4,11 @@ class Post
class TemplateField
attr_reader :post, :contents, :key
STRING_VALUES = %w[string text url number email password date year].freeze
STRING_VALUES = %w[string text url number email password date year
image video audio document].freeze
# Tipo de valores que son archivos
FILE_TYPES = %w[image video audio document].freeze
def initialize(post, key, contents)
@post = post
@ -32,6 +36,8 @@ class Post
return @type if @type
case
when image?
@type = 'image'
when email?
@type = 'email'
when url?
@ -120,6 +126,14 @@ class Post
value == 'year'
end
def file?
string? && FILE_TYPES.include?(value)
end
def image?
value == 'image'
end
# Si la plantilla es simple no está admitiendo Hashes como valores
def simple?
!complex?

View file

@ -15,7 +15,7 @@
- else
- url = site_post_path(@site, @post, lang: @lang)
- method = :patch
= form_tag url, method: method, class: 'form', novalidate: true do
= form_tag url, method: method, class: 'form', novalidate: true, multipart: true do
= hidden_field_tag 'template', params[:template]
.form-group
= submit_tag t('posts.save'), class: 'btn btn-success'

View file

@ -0,0 +1,3 @@
= file_field_tag field_name_for_post_as_string(name),
class: 'form-control',
required: template.required?

View file

@ -51,4 +51,10 @@ Rails.application.configure do
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
CarrierWave.configure do |config|
config.ignore_integrity_errors = false
config.ignore_processing_errors = false
config.ignore_download_errors = false
end
end

View file

@ -0,0 +1,5 @@
CarrierWave.configure do |config|
config.permissions = 0640
config.directory_permissions = 0750
config.storage = :file
end

21
doc/uploads.md Normal file
View file

@ -0,0 +1,21 @@
# Subida de archivos
La subida de archivos se genera a partir de agregar el valor a una
plantilla:
```yaml
---
cover: image
attachment: document
video: video
audio: audio
---
```
Donde `image` solo admite imágenes, `document` cualquier tipo de documento y
`video` y `audio` medios.
Al subir los archivos, se guardan en el directorio `public/` en la raíz
del proyecto Jekyll.
En el frontmatter solo sale la URL del archivo asociado.