mostrar el valor de la relación y actualizarla bidireccionalmente
closes #226
This commit is contained in:
parent
69159e6749
commit
5fdc170db0
4 changed files with 42 additions and 32 deletions
|
@ -16,7 +16,7 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
def validate
|
def validate
|
||||||
super
|
super
|
||||||
|
|
||||||
errors << I18n.t('metadata.belongs_to.missing_post') unless post_exists?
|
errors << I18n.t('metadata.belongs_to.missing_post') if value.present? && !post_exists?
|
||||||
|
|
||||||
errors.empty?
|
errors.empty?
|
||||||
end
|
end
|
||||||
|
@ -30,24 +30,27 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
# nos ahorra recursos en la búsqueda al cachear la información. En
|
# nos ahorra recursos en la búsqueda al cachear la información. En
|
||||||
# una relación HABTM también vamos a hacer lo mismo.
|
# una relación HABTM también vamos a hacer lo mismo.
|
||||||
def save
|
def save
|
||||||
return super unless inverse? && !included?
|
# Si no hay relación inversa, no hacer nada más
|
||||||
|
return super unless inverse?
|
||||||
|
|
||||||
# Evitar que se cambie el orden de la relación
|
# Si estamos cambiando la relación, tenemos que eliminar la relación
|
||||||
belonged_to&.dig(inverse)&.value&.delete post.uuid.value if belonged_to != belongs_to
|
# anterior
|
||||||
|
belonged_to[inverse].value.delete post.uuid.value if changed? && belonged_to.present?
|
||||||
|
|
||||||
belongs_to[inverse].value << post.uuid.value unless belongs_to[inverse].value.include? post.uuid.value
|
# No duplicar las relaciones
|
||||||
|
belongs_to[inverse].value << post.uuid.value unless belongs_to.blank? || included?
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# El Post actual está incluido en la relación inversa?
|
# El Post actual está incluido en la relación inversa?
|
||||||
def included?
|
def included?
|
||||||
belongs_to[inverse].value.include? post.uuid.value
|
belongs_to[inverse].value.include?(post.uuid.value)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Hay una relación inversa y el artículo existe?
|
# Hay una relación inversa y el artículo existe?
|
||||||
def inverse?
|
def inverse?
|
||||||
inverse.present? && belongs_to.present?
|
inverse.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
# El campo que es la relación inversa de este
|
# El campo que es la relación inversa de este
|
||||||
|
@ -66,11 +69,11 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
@belongs_to[value] ||= posts.find(value, uuid: true)
|
@belongs_to[value] ||= posts.find(value, uuid: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# El anterior artículo relacionado
|
# El artículo relacionado anterior
|
||||||
def belonged_to
|
def belonged_to
|
||||||
return if document.data[name.to_s].blank?
|
return if value_was.blank?
|
||||||
|
|
||||||
@belonged_to ||= posts.find(document.data[name.to_s], uuid: true)
|
@belonged_to ||= posts.find(value_was, uuid: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def related_posts?
|
def related_posts?
|
||||||
|
@ -88,6 +91,6 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_exists?
|
def post_exists?
|
||||||
!value.blank? && posts.find(sanitize(value), uuid: true)
|
posts.find(sanitize(value), uuid: true).present?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
:value, :help, :required, :errors, :post,
|
:value, :help, :required, :errors, :post,
|
||||||
:layout, keyword_init: true) do
|
:layout, keyword_init: true) do
|
||||||
attr_reader :value_was
|
|
||||||
|
|
||||||
# Queremos que los artículos nuevos siempre cacheen, si usamos el UUID
|
# Queremos que los artículos nuevos siempre cacheen, si usamos el UUID
|
||||||
# siempre vamos a obtener un item nuevo.
|
# siempre vamos a obtener un item nuevo.
|
||||||
def cache_key
|
def cache_key
|
||||||
|
@ -30,8 +28,20 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
self[:value] = new_value
|
self[:value] = new_value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Siempre obtener el valor actual y solo obtenerlo del documento una
|
||||||
|
# vez.
|
||||||
|
def value_was
|
||||||
|
return @value_was if instance_variable_defined? '@value_was'
|
||||||
|
|
||||||
|
@value_was = value_from_document
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_from_document
|
||||||
|
@value_from_document ||= document.data[name.to_s]
|
||||||
|
end
|
||||||
|
|
||||||
def changed?
|
def changed?
|
||||||
!value_was.nil? && value_was != value
|
value_was != value
|
||||||
end
|
end
|
||||||
|
|
||||||
# Obtiene el valor del JekyllDocument
|
# Obtiene el valor del JekyllDocument
|
||||||
|
@ -59,7 +69,7 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
# Valor actual o por defecto. Al memoizarlo podemos modificarlo
|
# Valor actual o por defecto. Al memoizarlo podemos modificarlo
|
||||||
# usando otros métodos que el de asignación.
|
# usando otros métodos que el de asignación.
|
||||||
def value
|
def value
|
||||||
self[:value] ||= if (data = document.data[name.to_s]).present?
|
self[:value] ||= if (data = value_from_document).present?
|
||||||
private? ? decrypt(data) : data
|
private? ? decrypt(data) : data
|
||||||
else
|
else
|
||||||
default_value
|
default_value
|
||||||
|
@ -123,7 +133,7 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
end
|
end
|
||||||
|
|
||||||
def related_methods
|
def related_methods
|
||||||
raise NotImplementedError
|
@related_methods ||= [].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determina si el campo es privado y debería ser cifrado
|
# Determina si el campo es privado y debería ser cifrado
|
||||||
|
|
|
@ -36,6 +36,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
post.usuaries << usuarie
|
post.usuaries << usuarie
|
||||||
params[:post][:draft] = true if site.invitade? usuarie
|
params[:post][:draft] = true if site.invitade? usuarie
|
||||||
|
|
||||||
|
# Es importante que el artículo se guarde primero y luego los
|
||||||
|
# relacionados.
|
||||||
commit(action: :updated, file: update_related_posts) if post.update(post_params)
|
commit(action: :updated, file: update_related_posts) if post.update(post_params)
|
||||||
|
|
||||||
# Devolver el post aunque no se haya salvado para poder rescatar los
|
# Devolver el post aunque no se haya salvado para poder rescatar los
|
||||||
|
@ -111,23 +113,24 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
# Actualiza los artículos relacionados según los métodos que los
|
# Actualiza los artículos relacionados según los métodos que los
|
||||||
# metadatos declaren.
|
# metadatos declaren.
|
||||||
#
|
#
|
||||||
|
# Este método se asegura que todos los artículos se guardan una sola
|
||||||
|
# vez.
|
||||||
|
#
|
||||||
# @return [Array] Lista de archivos modificados
|
# @return [Array] Lista de archivos modificados
|
||||||
def update_related_posts
|
def update_related_posts
|
||||||
files = [post.path.absolute]
|
posts = Set.new
|
||||||
|
|
||||||
post.attributes.each do |a|
|
post.attributes.each do |a|
|
||||||
next unless post[a].related_posts?
|
|
||||||
|
|
||||||
post[a].related_methods.each do |m|
|
post[a].related_methods.each do |m|
|
||||||
next unless post[a].respond_to? m
|
next unless post[a].respond_to? m
|
||||||
|
|
||||||
# La respuesta puede ser una PostRelation también
|
# La respuesta puede ser una PostRelation también
|
||||||
[post[a].public_send(m)].flatten.compact.uniq.each do |p|
|
posts.merge [post[a].public_send(m)].flatten.compact
|
||||||
files << p.path.absolute if p.save(validate: false)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
files
|
posts.map do |p|
|
||||||
|
p.path.absolute if p.save(validate: false)
|
||||||
|
end.compact << post.path.absolute
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
.form-group
|
.form-group
|
||||||
= label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post)
|
= label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post)
|
||||||
= text_field base, attribute, value: metadata.value,
|
= select_tag(plain_field_name_for(base, attribute),
|
||||||
dir: dir, lang: locale, list: id_for_datalist(attribute),
|
options_for_select(metadata.values, metadata.value),
|
||||||
pattern: metadata.values.values.join('|'), autocomplete: 'off',
|
**field_options(attribute, metadata), include_blank: true)
|
||||||
**field_options(attribute, metadata)
|
|
||||||
= render 'posts/attribute_feedback',
|
= render 'posts/attribute_feedback',
|
||||||
post: post, attribute: attribute, metadata: metadata
|
post: post, attribute: attribute, metadata: metadata
|
||||||
|
|
||||||
-# TODO: Ocultar el UUID
|
|
||||||
%datalist{ id: id_for_datalist(attribute) }
|
|
||||||
- metadata.values.each_pair do |key, value|
|
|
||||||
%option{ value: value }= key
|
|
||||||
|
|
Loading…
Reference in a new issue