empezar a mover la logica de plantillas a su propio modelo

This commit is contained in:
f 2018-06-15 18:34:33 -03:00
parent c0c0e060ce
commit 1bcb91b6ec
No known key found for this signature in database
GPG key ID: F3FDAB97B5F9F7E7
4 changed files with 150 additions and 79 deletions

View file

@ -224,88 +224,20 @@ class Post
def template_fields
return [] unless template
@template_fields ||= template.front_matter.reject do |key, _|
REJECT_FROM_TEMPLATE.include? key
end.keys
@template_fields ||= template.front_matter.map do |key, contents|
next if REJECT_FROM_TEMPLATE.include? key
Post::TemplateField.new(self, key, contents)
end.compact
end
# devuelve las plantillas como strong params
def template_params
@template_params ||= template_fields.map do |k|
v = template.get_front_matter(k)
if v.is_a? Array
{ k.to_sym => [] }
else
k.to_sym
end
k.to_param
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
@template ||= template_from_layout
end

View 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

View file

@ -76,11 +76,11 @@
{ class: 'form-control select2' }
%small.text-muted.form-text= t('posts.lang_help')
- @post.template_fields.each do |template|
- next unless type = @post.template_form_type_for(template)
- next unless type = template.type
.form-group
= label_tag "post_#{template}", template.humanize
= label_tag "post_#{template}", template.to_s.humanize
- 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
- when 'text'
= text_field 'post', template,
@ -92,8 +92,8 @@
= hidden_field 'post', template, value: 'false'
= check_box_tag name, 'true', value == 'true', class: 'form-control'
- 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',
multiple: @post.template_multiple_values?(template) }
multiple: template.multiple? }
.form-group
= submit_tag t('posts.save'), class: 'btn btn-success'

View file

@ -178,3 +178,33 @@ collections:
TODO: agregarlo especificamente en `app/models/site.rb` al cargar el
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
```