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)
|
||||
end
|
||||
|
||||
def related_posts?
|
||||
true
|
||||
end
|
||||
|
||||
def related_methods
|
||||
@related_methods ||= %i[belongs_to belonged_to].freeze
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
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
|
||||
def default_value
|
||||
raise NotImplementedError
|
||||
|
@ -85,6 +77,14 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
true
|
||||
end
|
||||
|
||||
def related_posts?
|
||||
false
|
||||
end
|
||||
|
||||
def related_methods
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Si es obligatorio no puede estar vacío
|
||||
|
@ -106,6 +106,3 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
end
|
||||
end
|
||||
# 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]
|
||||
|
||||
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
|
||||
|
||||
# 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