2018-01-29 22:19:10 +00:00
|
|
|
# frozen_string_literal: true
|
2019-03-26 15:32:20 +00:00
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# Esta clase representa un post en un sitio jekyll e incluye métodos
|
2019-08-06 23:17:29 +00:00
|
|
|
# para modificarlos y crear nuevos.
|
2018-02-03 22:37:09 +00:00
|
|
|
#
|
2021-02-17 21:38:02 +00:00
|
|
|
# * Los metadatos se tienen que cargar dinámicamente, solo usamos los
|
|
|
|
# que necesitamos
|
|
|
|
#
|
|
|
|
#
|
|
|
|
class Post
|
2019-08-06 23:17:29 +00:00
|
|
|
# Atributos por defecto
|
|
|
|
DEFAULT_ATTRIBUTES = %i[site document layout].freeze
|
|
|
|
# Otros atributos que no vienen en los metadatos
|
2019-09-17 21:27:51 +00:00
|
|
|
PRIVATE_ATTRIBUTES = %i[path slug attributes errors].freeze
|
2023-09-13 20:52:21 +00:00
|
|
|
PUBLIC_ATTRIBUTES = %i[lang date uuid created_at].freeze
|
2020-10-04 01:32:52 +00:00
|
|
|
ATTR_SUFFIXES = %w[? =].freeze
|
2019-08-06 23:17:29 +00:00
|
|
|
|
2024-04-17 21:05:01 +00:00
|
|
|
class PostError < StandardError; end
|
|
|
|
class UnknownAttributeError < PostError; end
|
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
attr_reader :attributes, :errors, :layout, :site, :document
|
|
|
|
|
2021-05-07 21:06:49 +00:00
|
|
|
# TODO: Modificar el historial de Git con callbacks en lugar de
|
|
|
|
# services. De esta forma podríamos agregar soporte para distintos
|
|
|
|
# backends.
|
2021-05-06 22:46:36 +00:00
|
|
|
include ActiveRecord::Callbacks
|
2021-05-06 15:52:30 +00:00
|
|
|
include Post::Indexable
|
|
|
|
|
2020-01-02 23:20:41 +00:00
|
|
|
class << self
|
|
|
|
# Obtiene el layout sin leer el Document
|
2020-06-16 22:21:38 +00:00
|
|
|
#
|
|
|
|
# TODO: Reemplazar cuando leamos el contenido del Document
|
|
|
|
# a demanda?
|
2020-10-04 00:32:32 +00:00
|
|
|
def find_layout(path)
|
2022-04-11 17:57:28 +00:00
|
|
|
File.foreach(path).lazy.grep(/^layout: /).take(1).first&.split(' ')&.last&.tr('\'', '')&.tr('"', '')&.to_sym
|
2020-01-02 23:20:41 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-08-06 23:17:29 +00:00
|
|
|
# Redefinir el inicializador de OpenStruct
|
|
|
|
#
|
|
|
|
# @param site: [Site] el sitio en Sutty
|
|
|
|
# @param document: [Jekyll::Document] el documento leído por Jekyll
|
|
|
|
# @param layout: [Layout] la plantilla
|
|
|
|
#
|
|
|
|
def initialize(**args)
|
2020-09-29 21:22:28 +00:00
|
|
|
default_attributes_missing(**args)
|
2019-08-06 23:17:29 +00:00
|
|
|
|
|
|
|
# Genera un método con todos los atributos disponibles
|
2021-02-17 21:38:02 +00:00
|
|
|
@layout = args[:layout]
|
|
|
|
@site = args[:site]
|
|
|
|
@document = args[:document]
|
|
|
|
@attributes = layout.attributes + PUBLIC_ATTRIBUTES
|
|
|
|
@errors = {}
|
|
|
|
@metadata = {}
|
|
|
|
|
2024-04-17 21:05:01 +00:00
|
|
|
# Leer el documento si existe
|
|
|
|
# @todo Asignar todos los valores a self[:value] luego de leer
|
|
|
|
document&.read! unless new?
|
|
|
|
|
|
|
|
# Inicializar valores o modificar los que vengan del documento
|
|
|
|
assignable_attributes = args.slice(*attributes)
|
|
|
|
assign_attributes(assignable_attributes) if assignable_attributes.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
# Asignar atributos, ignorando atributos que no se pueden modificar
|
|
|
|
# o inexistentes
|
|
|
|
#
|
|
|
|
# @param attrs [Hash]
|
|
|
|
def assign_attributes(attrs)
|
|
|
|
attrs = attrs.transform_keys(&:to_sym)
|
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
attributes.each do |attr|
|
2024-04-17 21:05:01 +00:00
|
|
|
self[attr].value = attrs[attr] if attrs.key?(attr) && self[attr].writable?
|
2018-02-03 22:37:09 +00:00
|
|
|
end
|
2019-08-07 21:35:37 +00:00
|
|
|
|
2024-04-17 21:05:01 +00:00
|
|
|
unknown_attrs = attrs.keys.map(&:to_sym) - attributes
|
|
|
|
|
|
|
|
if unknown_attrs.present?
|
|
|
|
raise UnknownAttributeError, "Unknown attribute(s) #{unknown_attrs.map(&:to_s).join(', ')} for Post"
|
|
|
|
end
|
|
|
|
|
|
|
|
nil
|
2018-02-03 22:37:09 +00:00
|
|
|
end
|
|
|
|
|
2020-06-16 22:21:38 +00:00
|
|
|
def inspect
|
|
|
|
"#<Post id=\"#{id}\">"
|
|
|
|
end
|
|
|
|
|
2020-10-30 21:57:46 +00:00
|
|
|
# Renderiza el artículo para poder previsualizarlo. Leemos solo la
|
|
|
|
# información básica, con lo que no van a funcionar artículos
|
|
|
|
# relacionados y otras cuestiones.
|
|
|
|
#
|
|
|
|
# @see app/lib/jekyll/tags/base.rb
|
|
|
|
def render
|
|
|
|
Dir.chdir site.path do
|
|
|
|
# Compatibilidad con jekyll-locales, necesario para el filtro
|
|
|
|
# date_local
|
|
|
|
#
|
|
|
|
# TODO: Cambiar el locale en otro lado
|
2021-03-03 12:43:15 +00:00
|
|
|
l = lang.value.to_s
|
|
|
|
site.jekyll.config['locale'] = site.jekyll.config['lang'] = l
|
2021-06-07 16:37:18 +00:00
|
|
|
# XXX: Es necesario leer los layouts para poder renderizar el
|
|
|
|
# sitio
|
|
|
|
site.theme_layouts
|
2020-10-30 21:57:46 +00:00
|
|
|
|
|
|
|
# Payload básico con traducciones.
|
|
|
|
document.renderer.payload = {
|
|
|
|
'site' => {
|
|
|
|
'data' => site.data,
|
2021-03-03 12:43:15 +00:00
|
|
|
'i18n' => site.data[l],
|
|
|
|
'lang' => l,
|
|
|
|
'locale' => l
|
2020-10-30 21:57:46 +00:00
|
|
|
},
|
|
|
|
'page' => document.to_liquid
|
|
|
|
}
|
|
|
|
|
2022-11-09 21:44:27 +00:00
|
|
|
# No tener errores de Liquid
|
|
|
|
site.jekyll.config['liquid']['strict_filters'] = false
|
|
|
|
site.jekyll.config['liquid']['strict_variables'] = false
|
|
|
|
|
2020-10-30 21:57:46 +00:00
|
|
|
# Renderizar lo estrictamente necesario y convertir a HTML para
|
|
|
|
# poder reemplazar valores.
|
|
|
|
html = Nokogiri::HTML document.renderer.render_document
|
2022-04-11 17:56:58 +00:00
|
|
|
# Los archivos se cargan directamente desde el repositorio, porque
|
2020-10-30 21:57:46 +00:00
|
|
|
# no son públicas hasta que se publica el artículo.
|
2022-04-11 17:56:58 +00:00
|
|
|
html.css('img,audio,video,iframe').each do |element|
|
|
|
|
src = element.attributes['src']
|
2020-10-30 21:57:46 +00:00
|
|
|
|
2022-04-11 17:56:58 +00:00
|
|
|
next unless src&.value&.start_with? 'public/'
|
2024-01-11 21:14:21 +00:00
|
|
|
file = MetadataFile.new(site: site, post: self, document: document, layout: layout)
|
|
|
|
file.value['path'] = src.value
|
2022-04-11 17:56:58 +00:00
|
|
|
|
2024-01-11 21:14:21 +00:00
|
|
|
src.value = Rails.application.routes.url_helpers.url_for(file.static_file)
|
2020-10-30 21:57:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Notificar a les usuaries que están viendo una previsualización
|
|
|
|
# XXX: Asume que estamos usando Bootstrap :B
|
2020-12-02 13:16:56 +00:00
|
|
|
html.at_css('body')&.first_element_child&.before("<div class=\"alert alert-warning text-center\">#{I18n.t('posts.preview.message')}</div>")
|
2020-10-30 21:57:46 +00:00
|
|
|
|
|
|
|
# Cacofonía
|
|
|
|
html.to_html.html_safe
|
2023-03-09 18:13:43 +00:00
|
|
|
rescue Liquid::Error => e
|
|
|
|
ExceptionNotifier.notify(e, data: { site: site.name, post: post.id })
|
|
|
|
|
|
|
|
''
|
2020-10-30 21:57:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-11 20:28:38 +00:00
|
|
|
# Devuelve una llave para poder guardar el post en una cache
|
|
|
|
def cache_key
|
2022-04-11 17:57:28 +00:00
|
|
|
"posts/#{uuid.value}"
|
2020-05-11 20:28:38 +00:00
|
|
|
end
|
|
|
|
|
2020-05-12 15:50:22 +00:00
|
|
|
def cache_version
|
2021-05-06 21:10:31 +00:00
|
|
|
(updated_at || modified_at).utc.to_s(:usec)
|
2020-05-12 15:50:22 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Agregar el timestamp para saber si cambió, siguiendo el módulo
|
|
|
|
# ActiveRecord::Integration
|
|
|
|
def cache_key_with_version
|
2022-04-11 17:57:28 +00:00
|
|
|
"#{cache_key}-#{cache_version}"
|
2020-05-12 15:50:22 +00:00
|
|
|
end
|
|
|
|
|
2020-01-02 23:29:04 +00:00
|
|
|
# TODO: Convertir a UUID?
|
2019-08-13 19:09:23 +00:00
|
|
|
def id
|
|
|
|
path.basename
|
|
|
|
end
|
2020-05-12 15:50:22 +00:00
|
|
|
alias to_param id
|
2019-08-13 19:09:23 +00:00
|
|
|
|
2021-01-25 18:29:14 +00:00
|
|
|
# Fecha de última modificación del archivo
|
2020-01-02 23:29:04 +00:00
|
|
|
def updated_at
|
2021-05-06 21:10:31 +00:00
|
|
|
return if new?
|
|
|
|
|
2020-01-02 23:29:04 +00:00
|
|
|
File.mtime(path.absolute)
|
2019-11-06 22:35:48 +00:00
|
|
|
end
|
|
|
|
|
2021-01-25 18:29:14 +00:00
|
|
|
# Obtiene la fecha actual de modificación y la guarda hasta la próxima
|
|
|
|
# vez.
|
|
|
|
def modified_at
|
|
|
|
@modified_at ||= Time.now
|
|
|
|
end
|
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
def [](attr)
|
|
|
|
public_send attr
|
|
|
|
end
|
|
|
|
|
|
|
|
# Define metadatos a demanda
|
|
|
|
def method_missing(name, *_args)
|
2020-01-02 23:29:53 +00:00
|
|
|
# Limpiar el nombre del atributo, para que todos los ayudantes
|
|
|
|
# reciban el método en limpio
|
|
|
|
unless attribute? name
|
2024-04-17 21:05:01 +00:00
|
|
|
raise UnknownAttributeError, I18n.t('exceptions.post.no_method', method: name)
|
2019-08-06 23:17:29 +00:00
|
|
|
end
|
2018-12-14 15:27:50 +00:00
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
define_singleton_method(name) do
|
|
|
|
template = layout.metadata[name.to_s]
|
|
|
|
|
|
|
|
@metadata[name] ||=
|
|
|
|
MetadataFactory.build(document: document,
|
|
|
|
post: self,
|
|
|
|
site: site,
|
|
|
|
name: name,
|
|
|
|
layout: layout,
|
|
|
|
type: template['type'],
|
|
|
|
label: template['label'],
|
|
|
|
help: template['help'],
|
|
|
|
required: template['required'])
|
|
|
|
end
|
|
|
|
|
|
|
|
public_send name
|
|
|
|
end
|
|
|
|
|
|
|
|
# TODO: Mover a method_missing
|
|
|
|
def slug
|
|
|
|
@metadata[:slug] ||= MetadataSlug.new(document: document, site: site, layout: layout, name: :slug, type: :slug,
|
|
|
|
post: self, required: true)
|
|
|
|
end
|
2019-08-07 21:35:37 +00:00
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
# TODO: Mover a method_missing
|
|
|
|
def date
|
|
|
|
@metadata[:date] ||= MetadataDocumentDate.new(document: document, site: site, layout: layout, name: :date,
|
|
|
|
type: :document_date, post: self, required: true)
|
|
|
|
end
|
|
|
|
|
|
|
|
# TODO: Mover a method_missing
|
|
|
|
def path
|
|
|
|
@metadata[:path] ||= MetadataPath.new(document: document, site: site, layout: layout, name: :path, type: :path,
|
|
|
|
post: self, required: true)
|
|
|
|
end
|
|
|
|
|
|
|
|
# TODO: Mover a method_missing
|
|
|
|
def lang
|
|
|
|
@metadata[:lang] ||= MetadataLang.new(document: document, site: site, layout: layout, name: :lang, type: :lang,
|
|
|
|
post: self, required: true)
|
|
|
|
end
|
|
|
|
|
2021-05-06 15:52:30 +00:00
|
|
|
alias locale lang
|
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
# TODO: Mover a method_missing
|
|
|
|
def uuid
|
|
|
|
@metadata[:uuid] ||= MetadataUuid.new(document: document, site: site, layout: layout, name: :uuid, type: :uuid,
|
|
|
|
post: self, required: true)
|
2018-12-14 15:27:50 +00:00
|
|
|
end
|
|
|
|
|
2023-09-13 20:52:21 +00:00
|
|
|
# La fecha de creación inmodificable del post
|
|
|
|
def created_at
|
2023-09-13 20:53:51 +00:00
|
|
|
@metadata[:created_at] ||= MetadataCreatedAt.new(document: document, site: site, layout: layout, name: :created_at, type: :created_at, post: self, required: true)
|
2023-09-13 20:52:21 +00:00
|
|
|
end
|
|
|
|
|
2019-08-06 23:17:29 +00:00
|
|
|
# Detecta si es un atributo válido o no, a partir de la tabla de la
|
|
|
|
# plantilla
|
|
|
|
def attribute?(mid)
|
2020-01-02 18:08:45 +00:00
|
|
|
included = DEFAULT_ATTRIBUTES.include?(mid) ||
|
|
|
|
PRIVATE_ATTRIBUTES.include?(mid) ||
|
|
|
|
PUBLIC_ATTRIBUTES.include?(mid)
|
|
|
|
|
2020-06-16 22:21:38 +00:00
|
|
|
included = attributes.include? mid if !included && singleton_class.method_defined?(:attributes)
|
2020-01-02 18:08:45 +00:00
|
|
|
|
|
|
|
included
|
2018-04-27 18:48:26 +00:00
|
|
|
end
|
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
# Devuelve los strong params para el layout.
|
|
|
|
#
|
|
|
|
# XXX: Nos gustaría no tener que instanciar Metadata acá, pero depende
|
|
|
|
# del valor por defecto que a su vez depende de Layout.
|
2019-08-13 23:33:57 +00:00
|
|
|
def params
|
|
|
|
attributes.map do |attr|
|
2021-02-17 21:38:02 +00:00
|
|
|
public_send(attr)&.to_param
|
|
|
|
end.compact
|
2019-08-13 23:33:57 +00:00
|
|
|
end
|
|
|
|
|
2019-08-06 23:17:29 +00:00
|
|
|
# Genera el post con metadatos en YAML
|
2020-06-16 22:21:38 +00:00
|
|
|
#
|
|
|
|
# TODO: Cachear por un minuto
|
2019-08-06 23:17:29 +00:00
|
|
|
def full_content
|
2019-08-13 23:33:57 +00:00
|
|
|
body = ''
|
2021-02-17 21:38:02 +00:00
|
|
|
yaml = layout.attributes.map do |attr|
|
|
|
|
template = public_send attr
|
2018-04-27 18:48:26 +00:00
|
|
|
|
2019-08-13 23:33:57 +00:00
|
|
|
unless template.front_matter?
|
2021-05-14 14:15:32 +00:00
|
|
|
body += "\n\n" if body.present?
|
2019-08-13 23:33:57 +00:00
|
|
|
body += template.value
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
2021-05-14 14:15:32 +00:00
|
|
|
# Queremos mantener los Array en el resultado final para que
|
|
|
|
# siempre respondan a {% for %} en Liquid.
|
|
|
|
next if template.empty? && !template.value.is_a?(Array)
|
2019-08-13 23:33:57 +00:00
|
|
|
|
2021-02-17 21:38:02 +00:00
|
|
|
[attr.to_s, template.value]
|
2020-11-07 23:51:00 +00:00
|
|
|
end.compact.to_h
|
2018-02-22 19:01:11 +00:00
|
|
|
|
2020-01-02 23:29:04 +00:00
|
|
|
# TODO: Convertir a Metadata?
|
2019-08-07 15:10:14 +00:00
|
|
|
# Asegurarse que haya un layout
|
|
|
|
yaml['layout'] = layout.name.to_s
|
2020-01-02 23:29:04 +00:00
|
|
|
yaml['uuid'] = uuid.value
|
2019-08-16 23:32:17 +00:00
|
|
|
# Y que no se procese liquid
|
2023-09-20 18:18:09 +00:00
|
|
|
yaml['render_with_liquid'] = false
|
2019-09-25 22:31:33 +00:00
|
|
|
yaml['usuaries'] = usuaries.map(&:id).uniq
|
2023-09-13 20:59:50 +00:00
|
|
|
yaml['created_at'] = created_at.value
|
2021-01-25 18:29:14 +00:00
|
|
|
yaml['last_modified_at'] = modified_at
|
2019-08-07 15:10:14 +00:00
|
|
|
|
2019-08-13 23:33:57 +00:00
|
|
|
"#{yaml.to_yaml}---\n\n#{body}"
|
2018-02-24 21:24:11 +00:00
|
|
|
end
|
|
|
|
|
2019-08-06 23:17:29 +00:00
|
|
|
# Eliminar el artículo del repositorio y de la lista de artículos del
|
2021-05-07 21:06:49 +00:00
|
|
|
# sitio.
|
|
|
|
#
|
|
|
|
# TODO: Si el callback falla deberíamos recuperar el archivo.
|
|
|
|
#
|
|
|
|
# @return [Post]
|
2019-08-06 23:17:29 +00:00
|
|
|
def destroy
|
2021-05-07 21:06:49 +00:00
|
|
|
run_callbacks :destroy do
|
|
|
|
FileUtils.rm_f path.absolute
|
2018-02-26 18:58:56 +00:00
|
|
|
|
2021-05-07 21:06:49 +00:00
|
|
|
site.delete_post self
|
|
|
|
end
|
2018-02-22 19:01:11 +00:00
|
|
|
end
|
2019-08-06 23:17:29 +00:00
|
|
|
alias destroy! destroy
|
2018-02-22 19:01:11 +00:00
|
|
|
|
2019-08-07 15:10:14 +00:00
|
|
|
# Guarda los cambios
|
2020-06-16 22:21:38 +00:00
|
|
|
# TODO: Agregar una forma de congelar todos los valores y solo guardar
|
|
|
|
# uno, para no incorporar modificaciones
|
2019-08-22 01:09:29 +00:00
|
|
|
# rubocop:disable Metrics/CyclomaticComplexity
|
2019-12-11 20:05:31 +00:00
|
|
|
def save(validate: true)
|
|
|
|
return false if validate && !valid?
|
2019-08-08 18:28:23 +00:00
|
|
|
# Salir si tenemos que cambiar el nombre del archivo y no pudimos
|
2020-10-04 01:32:52 +00:00
|
|
|
return false if !new? && path.changed? && !update_path!
|
2021-03-25 22:17:34 +00:00
|
|
|
|
|
|
|
# Si el archivo va a estar duplicado, agregar un número al slug
|
|
|
|
if new? && written?
|
|
|
|
original_slug = slug.value
|
|
|
|
count = 1
|
|
|
|
|
|
|
|
while written?
|
|
|
|
count += 1
|
|
|
|
slug.value = "#{original_slug}-#{count}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-05-06 22:46:36 +00:00
|
|
|
run_callbacks :save do
|
|
|
|
return false unless save_attributes!
|
|
|
|
return false unless write
|
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
|
|
|
|
# Vuelve a leer el post para tomar los cambios
|
2021-05-14 14:15:32 +00:00
|
|
|
document.reset
|
2019-08-08 18:28:23 +00:00
|
|
|
read
|
2019-08-07 15:10:14 +00:00
|
|
|
|
2019-09-16 17:56:34 +00:00
|
|
|
written?
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|
2019-08-22 01:09:29 +00:00
|
|
|
# rubocop:enable Metrics/CyclomaticComplexity
|
2019-03-26 15:32:20 +00:00
|
|
|
alias save! save
|
2018-01-29 22:19:10 +00:00
|
|
|
|
2019-09-16 17:56:34 +00:00
|
|
|
# Actualiza la ruta del documento y lo lee
|
2019-08-07 21:35:37 +00:00
|
|
|
def read
|
2019-09-16 17:56:34 +00:00
|
|
|
return unless written?
|
|
|
|
|
|
|
|
document.path = path.absolute
|
2020-01-02 23:20:41 +00:00
|
|
|
document.read!
|
2019-08-08 19:26:47 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def new?
|
|
|
|
document.path.blank?
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|
2019-08-07 21:35:37 +00:00
|
|
|
|
2019-09-16 17:56:34 +00:00
|
|
|
def written?
|
|
|
|
File.exist? path.absolute
|
|
|
|
end
|
|
|
|
|
2019-08-08 18:28:23 +00:00
|
|
|
# Actualizar la ubicación del archivo si cambió de lugar y si no
|
|
|
|
# existe el destino
|
|
|
|
def update_path!
|
|
|
|
!File.exist?(path.absolute) &&
|
2020-10-04 01:32:52 +00:00
|
|
|
FileUtils.mv(path.value_was, path.absolute) &&
|
2019-08-08 18:28:23 +00:00
|
|
|
document.path = path.absolute
|
2019-08-07 21:35:37 +00:00
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
|
2019-08-06 23:17:29 +00:00
|
|
|
# Detecta si el artículo es válido para guardar
|
|
|
|
def valid?
|
2021-02-17 21:38:02 +00:00
|
|
|
@errors = {}
|
2018-02-02 22:20:31 +00:00
|
|
|
|
2021-02-24 16:05:51 +00:00
|
|
|
attributes.each do |attr|
|
|
|
|
errors[attr] = self[attr].errors unless self[attr].valid?
|
2018-07-27 13:45:32 +00:00
|
|
|
end
|
2019-12-11 20:05:31 +00:00
|
|
|
|
|
|
|
errors.blank?
|
2018-06-25 20:44:47 +00:00
|
|
|
end
|
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# Guarda los cambios en el archivo destino
|
|
|
|
def write
|
2019-08-07 15:10:14 +00:00
|
|
|
return true if persisted?
|
2018-01-29 22:19:10 +00:00
|
|
|
|
2019-08-08 18:28:23 +00:00
|
|
|
Site::Writer.new(site: site, file: path.absolute,
|
2019-08-09 18:45:08 +00:00
|
|
|
content: full_content).save
|
2019-08-07 15:10:14 +00:00
|
|
|
end
|
2018-02-02 22:20:31 +00:00
|
|
|
|
2019-08-07 15:10:14 +00:00
|
|
|
# Verifica si hace falta escribir cambios
|
2020-06-16 22:21:38 +00:00
|
|
|
#
|
|
|
|
# TODO: Cachear el resultado o usar otro método, por ejemplo guardando
|
|
|
|
# la fecha de modificación al leer y compararla al hacer cambios sin
|
|
|
|
# escribirlos.
|
2019-08-07 15:10:14 +00:00
|
|
|
def persisted?
|
2019-08-08 18:28:23 +00:00
|
|
|
File.exist?(path.absolute) && full_content == File.read(path.absolute)
|
2018-02-02 22:20:31 +00:00
|
|
|
end
|
2018-02-03 22:37:09 +00:00
|
|
|
|
2019-08-16 23:12:22 +00:00
|
|
|
def destroyed?
|
|
|
|
!File.exist?(path.absolute)
|
|
|
|
end
|
|
|
|
|
2019-08-13 23:33:57 +00:00
|
|
|
def update_attributes(hashable)
|
2024-04-17 21:05:01 +00:00
|
|
|
assign_attributes(hashable)
|
2019-08-13 23:33:57 +00:00
|
|
|
|
|
|
|
save
|
|
|
|
end
|
2019-09-17 21:27:51 +00:00
|
|
|
alias update update_attributes
|
2019-08-13 23:33:57 +00:00
|
|
|
|
2019-12-11 20:10:01 +00:00
|
|
|
# El Document guarda un Array de los ids de Usuarie. Si está vacío,
|
|
|
|
# no hacemos una consulta vacía. Si no, traemos todes les Usuaries
|
|
|
|
# por su id y convertimos a Array para poder agregar o quitar luego
|
|
|
|
# sin pasar por ActiveRecord.
|
2019-09-25 22:31:33 +00:00
|
|
|
def usuaries
|
2021-02-24 16:05:51 +00:00
|
|
|
@usuaries ||= document_usuaries.empty? ? [] : Usuarie.where(id: document_usuaries).to_a
|
2019-09-25 22:31:33 +00:00
|
|
|
end
|
|
|
|
|
2019-08-07 15:10:14 +00:00
|
|
|
private
|
|
|
|
|
2020-01-02 18:08:45 +00:00
|
|
|
# Levanta un error si al construir el artículo no pasamos un atributo.
|
|
|
|
def default_attributes_missing(**args)
|
|
|
|
DEFAULT_ATTRIBUTES.each do |attr|
|
2021-02-17 21:38:02 +00:00
|
|
|
raise ArgumentError, I18n.t("exceptions.post.#{attr}_missing") unless args[attr].present?
|
2020-01-02 18:08:45 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-09-25 22:31:33 +00:00
|
|
|
def document_usuaries
|
2021-02-24 16:05:51 +00:00
|
|
|
@document_usuaries ||= document.data.fetch('usuaries', [])
|
2019-09-25 22:31:33 +00:00
|
|
|
end
|
|
|
|
|
2021-02-24 16:05:51 +00:00
|
|
|
# Ejecuta la acción de guardado en cada atributo.
|
2019-08-22 01:09:29 +00:00
|
|
|
def save_attributes!
|
2021-04-16 17:11:28 +00:00
|
|
|
attributes.map do |attr|
|
2021-04-11 19:43:59 +00:00
|
|
|
self[attr].save
|
2019-08-22 01:09:29 +00:00
|
|
|
end.all?
|
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|