# frozen_string_literal: true # Almacena el UUID de otro Post y actualiza el valor en el Post # relacionado. class MetadataBelongsTo < MetadataRelatedPosts def value_was=(new_value) @belongs_to = nil @belonged_to = nil super(new_value) end # TODO: Convertir algunos tipos de valores en módulos para poder # implementar varios tipos de campo sin repetir código # # @include MetadataString # # Una string vacía def default_value '' end def validate super errors << I18n.t('metadata.belongs_to.missing_post') unless post_exists? errors.empty? end # Guardar y guardar la relación inversa también, eliminando la # relación anterior si existía. def save super # Si no hay relación inversa, no hacer nada más return true unless changed? return true unless inverse? # Si estamos cambiando la relación, tenemos que eliminar la relación # anterior belonged_to[inverse].value.delete post.uuid.value if changed? && belonged_to.present? # No duplicar las relaciones belongs_to[inverse].value << post.uuid.value unless belongs_to.blank? || included? true end # El Post actual está incluido en la relación inversa? def included? belongs_to[inverse].value.include?(post.uuid.value) end # Hay una relación inversa y el artículo existe? def inverse? inverse.present? end # El campo que es la relación inversa de este def inverse @inverse ||= layout.metadata.dig(name, 'inverse')&.to_sym end # El Post relacionado con este artículo # # XXX: Memoizamos usando el valor para tener el valor siempre # actualizado. def belongs_to return if value.blank? @belongs_to ||= posts.find(value, uuid: true) end # El artículo relacionado anterior def belonged_to return if value_was.blank? @belonged_to ||= posts.find(value_was, uuid: true) end def related_posts? true end def related_methods @related_methods ||= %i[belongs_to belonged_to].freeze end private def post_exists? value.present? && belongs_to.nil? end def sanitize(uuid) uuid.to_s.gsub(/[^a-f0-9\-]/i, '') end end