empezar a mover la logica de plantillas a su propio modelo
This commit is contained in:
parent
c0c0e060ce
commit
1bcb91b6ec
4 changed files with 150 additions and 79 deletions
|
@ -224,88 +224,20 @@ class Post
|
||||||
|
|
||||||
def template_fields
|
def template_fields
|
||||||
return [] unless template
|
return [] unless template
|
||||||
@template_fields ||= template.front_matter.reject do |key, _|
|
@template_fields ||= template.front_matter.map do |key, contents|
|
||||||
REJECT_FROM_TEMPLATE.include? key
|
next if REJECT_FROM_TEMPLATE.include? key
|
||||||
end.keys
|
|
||||||
|
Post::TemplateField.new(self, key, contents)
|
||||||
|
end.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
# devuelve las plantillas como strong params
|
# devuelve las plantillas como strong params
|
||||||
def template_params
|
def template_params
|
||||||
@template_params ||= template_fields.map do |k|
|
@template_params ||= template_fields.map do |k|
|
||||||
v = template.get_front_matter(k)
|
k.to_param
|
||||||
if v.is_a? Array
|
|
||||||
{ k.to_sym => [] }
|
|
||||||
else
|
|
||||||
k.to_sym
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Obtiene el tipo de campo para la plantilla
|
|
||||||
def template_form_type_for(field)
|
|
||||||
return if (tt = template.get_front_matter(field)).nil?
|
|
||||||
|
|
||||||
case
|
|
||||||
when tt == 'string'
|
|
||||||
type = 'text'
|
|
||||||
when tt == 'text'
|
|
||||||
type = 'text_area'
|
|
||||||
when tt.is_a?(String) && tt.split('/', 2).count == 2
|
|
||||||
type = 'select'
|
|
||||||
when tt.is_a?(Array)
|
|
||||||
type = 'select'
|
|
||||||
when tt.is_a?(FalseClass) || tt.is_a?(TrueClass)
|
|
||||||
type = 'check_box'
|
|
||||||
end
|
|
||||||
|
|
||||||
type
|
|
||||||
end
|
|
||||||
|
|
||||||
def template_multiple_values?(field)
|
|
||||||
template.get_front_matter(field).is_a? Array
|
|
||||||
end
|
|
||||||
|
|
||||||
# Obtiene los valores posibles para el campo de la plantilla
|
|
||||||
def template_values_for(field)
|
|
||||||
return '' if %w[string text].include? template.get_front_matter(field)
|
|
||||||
|
|
||||||
# Para obtener los valores posibles, hay que procesar la string y
|
|
||||||
# convertirla a parametros
|
|
||||||
#
|
|
||||||
# XXX Prestar atención a no enviar metodos privados
|
|
||||||
|
|
||||||
value = template.get_front_matter(field)
|
|
||||||
|
|
||||||
# Si es una array de un solo elemento, es un indicador de que
|
|
||||||
# tenemos que rellenarla con los valores que indica
|
|
||||||
if value.is_a?(Array) && value.count == 1
|
|
||||||
values = value.first
|
|
||||||
else
|
|
||||||
values = value
|
|
||||||
end
|
|
||||||
|
|
||||||
# Procesar el valor
|
|
||||||
if values.is_a?(String)
|
|
||||||
value = values.split(':', 2).map do |v|
|
|
||||||
collection, attr = v.split('/', 2)
|
|
||||||
|
|
||||||
if collection == 'site'
|
|
||||||
# TODO puede ser peligroso permitir acceder a cualquier
|
|
||||||
# atributo de site? No estamos trayendo nada fuera de
|
|
||||||
# lo normal
|
|
||||||
@site.send(attr.to_sym)
|
|
||||||
else
|
|
||||||
@site.everything_of(attr, lang: collection)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
value = value.last.zip value.first
|
|
||||||
end
|
|
||||||
|
|
||||||
# En última instancia, traer el valor por defecto
|
|
||||||
value
|
|
||||||
end
|
|
||||||
|
|
||||||
def template
|
def template
|
||||||
@template ||= template_from_layout
|
@template ||= template_from_layout
|
||||||
end
|
end
|
||||||
|
|
109
app/models/post/template_field.rb
Normal file
109
app/models/post/template_field.rb
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
# Representa los distintos tipos de campos que pueden venir de una
|
||||||
|
# plantilla compleja
|
||||||
|
class Post
|
||||||
|
class TemplateField
|
||||||
|
attr_reader :post, :contents, :key
|
||||||
|
|
||||||
|
def initialize(post, key, contents)
|
||||||
|
@post = post
|
||||||
|
@key = key
|
||||||
|
@contents = contents
|
||||||
|
end
|
||||||
|
|
||||||
|
def type
|
||||||
|
return @type if @type
|
||||||
|
return unless simple?
|
||||||
|
|
||||||
|
case
|
||||||
|
when contents == 'string'
|
||||||
|
@type = 'text'
|
||||||
|
when contents == 'text'
|
||||||
|
@type = 'text_area'
|
||||||
|
when contents.is_a?(String) && contents.split('/', 2).count == 2
|
||||||
|
@type = 'select'
|
||||||
|
when contents.is_a?(Array)
|
||||||
|
@type = 'select'
|
||||||
|
when contents.is_a?(FalseClass) || contents.is_a?(TrueClass)
|
||||||
|
@type = 'check_box'
|
||||||
|
end
|
||||||
|
|
||||||
|
@type
|
||||||
|
end
|
||||||
|
|
||||||
|
# Si la plantilla es simple no está admitiendo Hashes como valores
|
||||||
|
def simple?
|
||||||
|
!complex?
|
||||||
|
end
|
||||||
|
|
||||||
|
def complex?
|
||||||
|
contents.is_a? Hash
|
||||||
|
end
|
||||||
|
|
||||||
|
# XXX Retrocompatibilidad
|
||||||
|
def to_s
|
||||||
|
key
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_param
|
||||||
|
if array?
|
||||||
|
{ key.to_sym => [] }
|
||||||
|
else
|
||||||
|
key.to_sym
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def array?
|
||||||
|
@contents.is_a? Array
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO detectar cuando es complejo y tomar el valor de :multiple
|
||||||
|
def multiple?
|
||||||
|
array?
|
||||||
|
end
|
||||||
|
|
||||||
|
def value
|
||||||
|
@contents
|
||||||
|
end
|
||||||
|
|
||||||
|
# Obtiene los valores posibles para el campo de la plantilla
|
||||||
|
def values
|
||||||
|
return '' if %w[string text].include? value
|
||||||
|
|
||||||
|
# Para obtener los valores posibles, hay que procesar la string y
|
||||||
|
# convertirla a parametros
|
||||||
|
#
|
||||||
|
# XXX Prestar atención a no enviar metodos privados
|
||||||
|
|
||||||
|
# Si es una array de un solo elemento, es un indicador de que
|
||||||
|
# tenemos que rellenarla con los valores que indica
|
||||||
|
if value.is_a?(Array) && value.count == 1
|
||||||
|
values = value.first
|
||||||
|
else
|
||||||
|
values = value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Procesar el valor
|
||||||
|
if values.is_a?(String)
|
||||||
|
value = values.split(':', 2).map do |v|
|
||||||
|
collection, attr = v.split('/', 2)
|
||||||
|
|
||||||
|
if collection == 'site'
|
||||||
|
# TODO puede ser peligroso permitir acceder a cualquier
|
||||||
|
# atributo de site? No estamos trayendo nada fuera de
|
||||||
|
# lo normal
|
||||||
|
post.site.send(attr.to_sym)
|
||||||
|
else
|
||||||
|
post.site.everything_of(attr, lang: collection)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
value = value.last.zip value.first
|
||||||
|
end
|
||||||
|
|
||||||
|
# En última instancia, traer el valor por defecto
|
||||||
|
value
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -76,11 +76,11 @@
|
||||||
{ class: 'form-control select2' }
|
{ class: 'form-control select2' }
|
||||||
%small.text-muted.form-text= t('posts.lang_help')
|
%small.text-muted.form-text= t('posts.lang_help')
|
||||||
- @post.template_fields.each do |template|
|
- @post.template_fields.each do |template|
|
||||||
- next unless type = @post.template_form_type_for(template)
|
- next unless type = template.type
|
||||||
.form-group
|
.form-group
|
||||||
= label_tag "post_#{template}", template.humanize
|
= label_tag "post_#{template}", template.to_s.humanize
|
||||||
- name = "post[#{template}]"
|
- name = "post[#{template}]"
|
||||||
- value = @post.new? ? @post.template_values_for(template) : @post.get_front_matter(template)
|
- value = @post.new? ? template.values : @post.get_front_matter(template)
|
||||||
- case type
|
- case type
|
||||||
- when 'text'
|
- when 'text'
|
||||||
= text_field 'post', template,
|
= text_field 'post', template,
|
||||||
|
@ -92,8 +92,8 @@
|
||||||
= hidden_field 'post', template, value: 'false'
|
= hidden_field 'post', template, value: 'false'
|
||||||
= check_box_tag name, 'true', value == 'true', class: 'form-control'
|
= check_box_tag name, 'true', value == 'true', class: 'form-control'
|
||||||
- when 'select'
|
- when 'select'
|
||||||
= select_tag name, options_for_select(@post.template_values_for(template), @post.get_front_matter(template)),
|
= select_tag name, options_for_select(template.values, @post.get_front_matter(template)),
|
||||||
{ class: 'form-control select2',
|
{ class: 'form-control select2',
|
||||||
multiple: @post.template_multiple_values?(template) }
|
multiple: template.multiple? }
|
||||||
.form-group
|
.form-group
|
||||||
= submit_tag t('posts.save'), class: 'btn btn-success'
|
= submit_tag t('posts.save'), class: 'btn btn-success'
|
||||||
|
|
|
@ -178,3 +178,33 @@ collections:
|
||||||
|
|
||||||
TODO: agregarlo especificamente en `app/models/site.rb` al cargar el
|
TODO: agregarlo especificamente en `app/models/site.rb` al cargar el
|
||||||
sitio.
|
sitio.
|
||||||
|
|
||||||
|
## Plantillas complejas
|
||||||
|
|
||||||
|
Algunas plantillas necesitan comportamientos más complejos, por ejemplo
|
||||||
|
cuando un campo es requerido o no es público.
|
||||||
|
|
||||||
|
```
|
||||||
|
campo:
|
||||||
|
help: "Un texto de ayuda"
|
||||||
|
public: false
|
||||||
|
required: true
|
||||||
|
value: {bool,string,text,array,url,email}
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
multiple: false
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora los `value` pueden estar anidados, es decir que dentro de cada
|
||||||
|
value puede haber una serie de `campo` con los mismos valores.
|
||||||
|
|
||||||
|
Las plantillas más simples asumen ciertos valores por defecto:
|
||||||
|
|
||||||
|
```
|
||||||
|
help: nil
|
||||||
|
public: true
|
||||||
|
required: false
|
||||||
|
min: nil
|
||||||
|
max: nil
|
||||||
|
multiple: true
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in a new issue