relacion de uno a muchos
This commit is contained in:
parent
ec02a45002
commit
52d26918b5
6 changed files with 118 additions and 12 deletions
|
@ -73,6 +73,14 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
@belonged_to ||= posts.find(document.data[name.to_s], uuid: true)
|
@belonged_to ||= posts.find(document.data[name.to_s], uuid: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def related_posts?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def related_methods
|
||||||
|
@related_methods ||= %i[belongs_to belonged_to].freeze
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def sanitize(uuid)
|
def sanitize(uuid)
|
||||||
|
|
71
app/models/metadata_has_many.rb
Normal file
71
app/models/metadata_has_many.rb
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# La diferencia con MetadataRelatedPosts es que la relación también
|
||||||
|
# actualiza los Posts remotos.
|
||||||
|
#
|
||||||
|
# Localmente tenemos un Array de UUIDs. Remotamente tenemos una String
|
||||||
|
# apuntando a un Post, que se mantiene actualizado como el actual.
|
||||||
|
class MetadataHasMany < MetadataRelatedPosts
|
||||||
|
# Todos los Post relacionados según la relación remota
|
||||||
|
def has_many_remote
|
||||||
|
@has_many_remote ||= posts.where(inverse => post.uuid.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Todos los Post relacionados
|
||||||
|
def has_many
|
||||||
|
@has_many ||= {}
|
||||||
|
@has_many[value.hash.to_s] ||= posts.where(uuid: value)
|
||||||
|
end
|
||||||
|
|
||||||
|
# La relación anterior
|
||||||
|
def had_many
|
||||||
|
return [] if document.data[name.to_s].blank?
|
||||||
|
|
||||||
|
@had_many ||= posts.where(uuid: document.data[name.to_s])
|
||||||
|
end
|
||||||
|
|
||||||
|
def inverse?
|
||||||
|
inverse.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
# La relación inversa
|
||||||
|
#
|
||||||
|
# @return [Nil,Symbol]
|
||||||
|
def inverse
|
||||||
|
layout.metadata.dig(name, 'inverse')&.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
# Actualizar las relaciones inversas. Hay que buscar la diferencia
|
||||||
|
# entre had y has_many.
|
||||||
|
def save
|
||||||
|
self[:value] = sanitize value
|
||||||
|
|
||||||
|
return true unless inverse?
|
||||||
|
|
||||||
|
(had_many - has_many).each do |remove|
|
||||||
|
remove[inverse].value = remove[inverse].default_value
|
||||||
|
end
|
||||||
|
|
||||||
|
(has_many - had_many).each do |add|
|
||||||
|
add[inverse].value = post.uuid.value
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def related_posts?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def related_methods
|
||||||
|
@related_methods ||= %i[has_many had_many].freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def sanitize(sanitizable)
|
||||||
|
sanitizable.map do |uuid|
|
||||||
|
uuid.gsub(/[^a-f0-9\-]/, '')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,14 +10,6 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
:layout, keyword_init: true) do
|
:layout, keyword_init: true) do
|
||||||
include ActionText::ContentHelper
|
include ActionText::ContentHelper
|
||||||
|
|
||||||
# Métodos que tienen artículos relacionados
|
|
||||||
#
|
|
||||||
# Ver el final del archivo.
|
|
||||||
#
|
|
||||||
# XXX: Por alguna razón no se pueden definir constantes en un Struct
|
|
||||||
#
|
|
||||||
# RELATED_METHODS = %i[]
|
|
||||||
|
|
||||||
# El valor por defecto
|
# El valor por defecto
|
||||||
def default_value
|
def default_value
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -85,6 +77,14 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def related_posts?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def related_methods
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Si es obligatorio no puede estar vacío
|
# Si es obligatorio no puede estar vacío
|
||||||
|
@ -106,6 +106,3 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/BlockLength
|
# rubocop:enable Metrics/BlockLength
|
||||||
|
|
||||||
# Definir la constante después de definir el Struct.
|
|
||||||
MetadataTemplate.const_set 'RELATED_METHODS', %i[belongs_to belonged_to].freeze
|
|
||||||
|
|
|
@ -118,7 +118,9 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
files = [post.path.absolute]
|
files = [post.path.absolute]
|
||||||
|
|
||||||
post.attributes.each do |a|
|
post.attributes.each do |a|
|
||||||
MetadataTemplate::RELATED_METHODS.each do |m|
|
next unless post[a].related_posts?
|
||||||
|
|
||||||
|
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
|
||||||
|
|
6
app/views/posts/attribute_ro/_has_many.haml
Normal file
6
app/views/posts/attribute_ro/_has_many.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%tr{ id: attribute }
|
||||||
|
%th= post_label_t(attribute, post: post)
|
||||||
|
%td
|
||||||
|
%ul{ dir: dir, lang: locale }
|
||||||
|
- metadata.has_many.each do |p|
|
||||||
|
%li= link_to p.title.value, site_post_path(site, p.id)
|
22
app/views/posts/attributes/_has_many.haml
Normal file
22
app/views/posts/attributes/_has_many.haml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
.form-group
|
||||||
|
= label_tag "post_#{attribute}", post_label_t(attribute, post: post)
|
||||||
|
|
||||||
|
.mapable{ dir: dir, lang: locale,
|
||||||
|
data: { values: metadata.value.to_json,
|
||||||
|
'default-values': metadata.values.to_json,
|
||||||
|
name: "post[#{attribute}][]", list: id_for_datalist(attribute),
|
||||||
|
remove: 'false', legend: post_label_t(attribute, post: post),
|
||||||
|
button: t('posts.attributes.add'),
|
||||||
|
described: id_for_help(attribute) } }
|
||||||
|
|
||||||
|
= text_field(*field_name_for('post', attribute, '[]'),
|
||||||
|
value: metadata.value.join(', '),
|
||||||
|
dir: dir, lang: locale,
|
||||||
|
**field_options(attribute, metadata))
|
||||||
|
|
||||||
|
= render 'posts/attribute_feedback',
|
||||||
|
post: post, attribute: attribute, metadata: metadata
|
||||||
|
|
||||||
|
%datalist{ id: id_for_datalist(attribute) }
|
||||||
|
- metadata.values.keys.each do |value|
|
||||||
|
%option{ value: value }
|
Loading…
Reference in a new issue