revisión de habtm

This commit is contained in:
f 2021-02-11 16:44:36 -03:00
parent bbdbfc4ee1
commit c5cd07a82e
6 changed files with 38 additions and 60 deletions

View file

@ -23,7 +23,7 @@ class MetadataBelongsTo < MetadataRelatedPosts
def validate def validate
super super
errors << I18n.t('metadata.belongs_to.missing_post') if value.present? && !post_exists? errors << I18n.t('metadata.belongs_to.missing_post') unless post_exists?
errors.empty? errors.empty?
end end
@ -59,7 +59,7 @@ class MetadataBelongsTo < MetadataRelatedPosts
# El campo que es la relación inversa de este # El campo que es la relación inversa de este
def inverse def inverse
layout.metadata.dig name, 'inverse' @inverse ||= layout.metadata.dig(name, 'inverse')&.to_sym
end end
# El Post relacionado con este artículo # El Post relacionado con este artículo
@ -90,7 +90,7 @@ class MetadataBelongsTo < MetadataRelatedPosts
private private
def post_exists? def post_exists?
posts.find(value, uuid: true).present? value.present? && belongs_to.nil?
end end
def sanitize(uuid) def sanitize(uuid)

View file

@ -10,40 +10,7 @@
# el libro actual. La relación belongs_to tiene que traer todes les # el libro actual. La relación belongs_to tiene que traer todes les
# autores que tienen este libro. La relación es bidireccional, no hay # autores que tienen este libro. La relación es bidireccional, no hay
# diferencia entre has_many y belongs_to. # diferencia entre has_many y belongs_to.
class MetadataHasAndBelongsToMany < MetadataBelongsTo class MetadataHasAndBelongsToMany < MetadataHasMany
def default_value
[]
end
# Posts a los que pertenece. Memoizamos por value para obtener
# siempre la última relación.
#
# Buscamos todos los Post contenidos en el valor actual. No
# garantizamos el orden.
#
# @return [PostRelation] Posts
def belongs_to
@belongs_to ||= {}
@belongs_to[value.hash.to_s] ||= posts.where(uuid: value)
end
# Devuelve la lista de Posts relacionados con este buscándolos en la
# relación inversa. #save debería mantenerlos sincronizados.
#
# @return [PostRelation]
def has_many
@has_many ||= {}
@has_many[value.hash.to_s] ||= posts.where(inverse.to_sym => post.uuid.value)
end
alias had_many has_many
# Posts a los que pertenecía
#
# @return [PostRelation] Posts
def belonged_to
@belonged_to ||= posts.where(uuid: document.data.fetch(name.to_s, []))
end
# Mantiene la relación inversa si existe. # Mantiene la relación inversa si existe.
# #
# La relación belongs_to se mantiene actualizada en la modificación # La relación belongs_to se mantiene actualizada en la modificación
@ -52,39 +19,33 @@ class MetadataHasAndBelongsToMany < MetadataBelongsTo
# Buscamos en belongs_to la relación local, si se eliminó hay que # Buscamos en belongs_to la relación local, si se eliminó hay que
# quitarla de la relación remota, sino hay que agregarla. # quitarla de la relación remota, sino hay que agregarla.
def save def save
return true unless changed? # XXX: No usamos super
self[:value] = sanitize value self[:value] = sanitize value
return true unless inverse? && !included? return true unless changed?
return true unless inverse?
(belonged_to - belongs_to).each do |p| (had_many - has_many).each do |remove|
p[inverse].value.delete post.uuid.value remove[inverse]&.value&.delete post.uuid.value
end end
(belongs_to - belonged_to).each do |p| (has_many - had_many).each do |add|
p[inverse].value << post.uuid.value next unless add[inverse]
next if add[inverse].value.include? post.uuid.value
add[inverse].value << post.uuid.value
end end
true true
end end
def sanitize(sanitizable) private
sanitizable.map do |v|
super v
end
end
def post_exists? # Igual que en MetadataRelatedPosts
return true if empty? && can_be_empty? # TODO: Mover a un módulo
def sanitize(uuid)
!belongs_to.empty? super(uuid.map do |u|
end u.to_s.gsub(/[^a-f0-9\-]/i, '')
end)
# Todos los artículos relacionados incluyen a este?
def included?
belongs_to.map do |p|
p[inverse].value.include? post.uuid.value
end.all?
end end
end end

View file

@ -14,6 +14,14 @@ class MetadataHasMany < MetadataRelatedPosts
super(new_value) super(new_value)
end end
def validate
super
errors << I18n.t('metadata.has_many.missing_posts') unless posts_exist?
errors.empty?
end
# Todos los Post relacionados # Todos los Post relacionados
def has_many def has_many
@has_many ||= posts.where(uuid: value) @has_many ||= posts.where(uuid: value)
@ -63,4 +71,8 @@ class MetadataHasMany < MetadataRelatedPosts
def related_methods def related_methods
@related_methods ||= %i[has_many had_many].freeze @related_methods ||= %i[has_many had_many].freeze
end end
def posts_exist?
has_many.size == value.size
end
end end

View file

@ -1,5 +1,6 @@
.form-group .form-group
= label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post) = label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post)
= hidden_field_tag "#{base}[#{attribute}][]", ''
.mapable{ dir: dir, lang: locale, .mapable{ dir: dir, lang: locale,
data: { values: metadata.value.to_json, data: { values: metadata.value.to_json,

View file

@ -48,6 +48,8 @@ en:
end_in_the_past: "Event end can't happen before the start" end_in_the_past: "Event end can't happen before the start"
belongs_to: belongs_to:
missing_post: "Couldn't find the related post" missing_post: "Couldn't find the related post"
has_many:
missing_posts: "Couldn't find some related posts"
exceptions: exceptions:
post: post:
site_missing: 'Needs an instance of Site' site_missing: 'Needs an instance of Site'

View file

@ -48,6 +48,8 @@ es:
end_in_the_past: 'El fin del evento no puede ser anterior al comienzo' end_in_the_past: 'El fin del evento no puede ser anterior al comienzo'
belongs_to: belongs_to:
missing_post: 'No se pudo encontrar el artículo relacionado' missing_post: 'No se pudo encontrar el artículo relacionado'
has_many:
missing_posts: 'No se pudieron encontrar algunos artículos relacionados'
exceptions: exceptions:
post: post:
site_missing: 'Necesita una instancia de Site' site_missing: 'Necesita una instancia de Site'