mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-15 04:51:43 +00:00
WIP de subir archivos
This commit is contained in:
parent
c791620f3c
commit
a1fe309e6a
10 changed files with 139 additions and 5 deletions
4
Gemfile
4
Gemfile
|
@ -40,6 +40,10 @@ gem 'jquery-rails'
|
||||||
gem 'font-awesome-rails'
|
gem 'font-awesome-rails'
|
||||||
gem 'exception_notification'
|
gem 'exception_notification'
|
||||||
gem 'whenever', require: false
|
gem 'whenever', require: false
|
||||||
|
gem 'carrierwave'
|
||||||
|
gem 'carrierwave-i18n'
|
||||||
|
gem 'mini_magick'
|
||||||
|
gem 'carrierwave-bombshelter'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
|
|
18
Gemfile.lock
18
Gemfile.lock
|
@ -75,6 +75,15 @@ GEM
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
xpath (>= 2.0, < 4.0)
|
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)
|
childprocess (0.9.0)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
chronic (0.10.2)
|
chronic (0.10.2)
|
||||||
|
@ -101,6 +110,7 @@ GEM
|
||||||
actionmailer (>= 4.0, < 6)
|
actionmailer (>= 4.0, < 6)
|
||||||
activesupport (>= 4.0, < 6)
|
activesupport (>= 4.0, < 6)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
|
fastimage (2.1.3)
|
||||||
ffi (1.9.23)
|
ffi (1.9.23)
|
||||||
font-awesome-rails (4.7.0.4)
|
font-awesome-rails (4.7.0.4)
|
||||||
railties (>= 3.2, < 6.0)
|
railties (>= 3.2, < 6.0)
|
||||||
|
@ -161,6 +171,10 @@ GEM
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
mercenary (0.3.6)
|
mercenary (0.3.6)
|
||||||
method_source (0.9.0)
|
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_mime (1.0.0)
|
||||||
mini_portile2 (2.3.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.11.3)
|
minitest (5.11.3)
|
||||||
|
@ -296,6 +310,9 @@ DEPENDENCIES
|
||||||
capistrano-rails
|
capistrano-rails
|
||||||
capistrano-rbenv
|
capistrano-rbenv
|
||||||
capybara (~> 2.13)
|
capybara (~> 2.13)
|
||||||
|
carrierwave
|
||||||
|
carrierwave-bombshelter
|
||||||
|
carrierwave-i18n
|
||||||
commonmarker
|
commonmarker
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
email_address
|
email_address
|
||||||
|
@ -306,6 +323,7 @@ DEPENDENCIES
|
||||||
jekyll
|
jekyll
|
||||||
jquery-rails
|
jquery-rails
|
||||||
listen (>= 3.0.5, < 3.2)
|
listen (>= 3.0.5, < 3.2)
|
||||||
|
mini_magick
|
||||||
pry
|
pry
|
||||||
puma (~> 3.7)
|
puma (~> 3.7)
|
||||||
rails (~> 5.1.4)
|
rails (~> 5.1.4)
|
||||||
|
|
|
@ -199,9 +199,23 @@ class Post
|
||||||
# HashWithIndifferentAccess
|
# HashWithIndifferentAccess
|
||||||
attrs = attrs.to_h.map do |k,v|
|
attrs = attrs.to_h.map do |k,v|
|
||||||
t = template_fields.find { |t| t.key == k }
|
t = template_fields.find { |t| t.key == k }
|
||||||
if t && t.nested?
|
if t
|
||||||
v = t.array? ? v.values.map(&:to_h) : v.to_h
|
# 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
|
end
|
||||||
|
|
||||||
{ k => v }
|
{ k => v }
|
||||||
end.reduce(Hash.new, :merge).stringify_keys
|
end.reduce(Hash.new, :merge).stringify_keys
|
||||||
|
|
||||||
|
@ -209,10 +223,20 @@ class Post
|
||||||
end
|
end
|
||||||
|
|
||||||
# Requisitos para que el post sea válido
|
# Requisitos para que el post sea válido
|
||||||
|
# TODO verificar que el id sea único
|
||||||
|
# TODO validar los parametros de la plantilla
|
||||||
def validate
|
def validate
|
||||||
add_error validate: I18n.t('posts.errors.date') unless date.is_a? Time
|
add_error validate: I18n.t('posts.errors.date') unless date.is_a? Time
|
||||||
add_error validate: I18n.t('posts.errors.title') if title.blank?
|
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
|
end
|
||||||
|
|
||||||
def valid?
|
def valid?
|
||||||
|
|
39
app/models/post/image_uploader.rb
Normal file
39
app/models/post/image_uploader.rb
Normal 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
|
|
@ -4,7 +4,11 @@ class Post
|
||||||
class TemplateField
|
class TemplateField
|
||||||
attr_reader :post, :contents, :key
|
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)
|
def initialize(post, key, contents)
|
||||||
@post = post
|
@post = post
|
||||||
|
@ -32,6 +36,8 @@ class Post
|
||||||
return @type if @type
|
return @type if @type
|
||||||
|
|
||||||
case
|
case
|
||||||
|
when image?
|
||||||
|
@type = 'image'
|
||||||
when email?
|
when email?
|
||||||
@type = 'email'
|
@type = 'email'
|
||||||
when url?
|
when url?
|
||||||
|
@ -120,6 +126,14 @@ class Post
|
||||||
value == 'year'
|
value == 'year'
|
||||||
end
|
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
|
# Si la plantilla es simple no está admitiendo Hashes como valores
|
||||||
def simple?
|
def simple?
|
||||||
!complex?
|
!complex?
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
- else
|
- else
|
||||||
- url = site_post_path(@site, @post, lang: @lang)
|
- url = site_post_path(@site, @post, lang: @lang)
|
||||||
- method = :patch
|
- 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]
|
= hidden_field_tag 'template', params[:template]
|
||||||
.form-group
|
.form-group
|
||||||
= submit_tag t('posts.save'), class: 'btn btn-success'
|
= submit_tag t('posts.save'), class: 'btn btn-success'
|
||||||
|
|
3
app/views/posts/template_field/_image.haml
Normal file
3
app/views/posts/template_field/_image.haml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
= file_field_tag field_name_for_post_as_string(name),
|
||||||
|
class: 'form-control',
|
||||||
|
required: template.required?
|
|
@ -51,4 +51,10 @@ Rails.application.configure do
|
||||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||||
# routes, locales, etc. This feature depends on the listen gem.
|
# routes, locales, etc. This feature depends on the listen gem.
|
||||||
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
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
|
end
|
||||||
|
|
5
config/initializers/carrierwave.rb
Normal file
5
config/initializers/carrierwave.rb
Normal 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
21
doc/uploads.md
Normal 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.
|
Loading…
Reference in a new issue