From c26cca5fa05bf1d660214e441d6154b131d5e0b6 Mon Sep 17 00:00:00 2001 From: f Date: Tue, 26 Jun 2018 20:04:28 -0300 Subject: [PATCH] autocompletar los valores #51 --- app/models/post/template_field.rb | 107 +++++++++++++++++++----------- 1 file changed, 69 insertions(+), 38 deletions(-) diff --git a/app/models/post/template_field.rb b/app/models/post/template_field.rb index 12b721ee..59f4800c 100644 --- a/app/models/post/template_field.rb +++ b/app/models/post/template_field.rb @@ -183,6 +183,10 @@ class Post contents.fetch('open', value.count < 2) end + def closed? + !open? + end + # Determina si los valores del campo serán públicos después # # XXX Esto es solo una indicación, el theme Jekyll tiene que @@ -221,55 +225,82 @@ class Post # Obtiene los valores posibles para el campo de la plantilla def values - return '' if STRING_VALUES.include? value + # XXX por alguna razón `value` no refiere a value() :/ + return '' if STRING_VALUES.include? self.value + # Las listas cerradas no necesitan mayor procesamiento + return self.value if array? && closed? && self.value.count > 1 + # Y las vacías tampoco + return self.value if array? && self.value.empty? + # Ahorrarnos el trabajo + return @values if @values + + # Duplicar el valor para no tener efectos secundarios luego (?) + value = self.value.dup # 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 array? && value.count == 1 - values = value.first - else - values = value + # tenemos que rellenarla con los valores que indica. + # + # El primer valor es el que trae la string de autocompletado + values = array? ? value.shift : value + + # Si el valor es un array con más de un elemento, queremos usar + # esas opciones. Pero si además es abierto, queremos traer los + # valores cargados anteriormente. + + # Procesamos el valor, buscando : como separador de campos que + # queremos encontrar y luego los unimos + _value = (values.try(:split, ':', 2) || []).map do |v| + # Tenemos hasta tres niveles de búsqueda + collection, attr, subattr = v.split('/', 3) + + 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) + # Si hay un subatributo, tenemos que averiguar todos los + # valores dentro de el + # TODO volver elegante! + elsif subattr + post.site.everything_of(attr, lang: collection) + .compact + .map { |sv| sv[subattr] } + .uniq + else + post.site.everything_of(attr, lang: collection).compact + end end - # Procesar el valor - if values.is_a?(String) - value = values.split(':', 2).map do |v| - collection, attr, subattr = v.split('/', 3) - - 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) - # Si hay un subatributo, tenemos que averiguar todos los - # valores dentro de el - # TODO volver elegante! - elsif subattr - post.site.everything_of(attr, lang: collection).compact.map do |v| - tv = v.dig('value') - if tv.is_a? Array - tv.map do |sv| - sv[subattr] - end - else - tv.try :dig, subattr - end - end - else - post.site.everything_of(attr, lang: collection).compact + # Si el valor es abierto, sumar los valores auto-completados a + # lo pre-cargados. + # + # En este punto _value es un array de 1 o 2 arrays, si es de uno, + # value tambien tiene que serlo. Si es de 2, hay que unir cada + # una + if open? + if _value.count == 1 + _value = [(_value.first + value).uniq] + elsif _value.count == 2 + _value = _value.each_with_index.map do |v,i| + v + value[i] end end - - values = value.last.zip value.first end - # En última instancia, traer el valor por defecto - values + binding.pry if _value.last.nil? + + # Crea un array de arrays, útil para los select + # [ [ 1, a ], [ 2, b ] ] + # aunque si no hay un : en el autocompletado, el array queda + # [ [ 1, 1 ], [ 2, 2 ] ] + values = _value.last.zip _value.first + + # En última instancia, traer el valor por defecto y ahorrarnos + # volver a procesar + @values = values end end end