From 1e2c29f3090ee5cb39592ce3b9a63622791fa44d Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 12:47:51 -0300 Subject: [PATCH 01/65] feat: metadata has one #12985 --- app/models/metadata_has_one.rb | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 app/models/metadata_has_one.rb diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb new file mode 100644 index 00000000..49fd65bf --- /dev/null +++ b/app/models/metadata_has_one.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class MetadataHasOne < MetadataHasMany +end From b06751e62e5310a7b33c529c51cd8273e50db2c3 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:09:40 -0300 Subject: [PATCH 02/65] feat: establecer relaciones bidireccionales --- app/models/metadata_belongs_to.rb | 14 +++++++++++--- app/models/metadata_has_one.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index be1fa670..e1b84438 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -40,13 +40,21 @@ class MetadataBelongsTo < MetadataRelatedPosts # Si estamos cambiando la relación, tenemos que eliminar la relación # anterior if belonged_to.present? - belonged_to[inverse].value = belonged_to[inverse].value.reject do |rej| - rej == post.uuid.value + if belonged_to[inverse].respond_to? :has_one + belonged_to[inverse].value = nil + else + belonged_to[inverse].value = belonged_to[inverse].value.reject do |rej| + rej == post.uuid.value + end end end # No duplicar las relaciones - belongs_to[inverse].value = (belongs_to[inverse].value.dup << post.uuid.value) unless belongs_to.blank? || included? + if belongs_to[inverse].respond_to? :has_one + belongs_to[inverse].value = post.uuid.value + else + belongs_to[inverse].value = (belongs_to[inverse].value.dup << post.uuid.value) unless belongs_to.blank? || included? + end true end diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 49fd65bf..38911e1d 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -1,4 +1,34 @@ # frozen_string_literal: true class MetadataHasOne < MetadataHasMany + def had_one + return default_value if value_was.blank? + + posts.find(uuid: value) + end + + def has_one + return default_value if value.blank? + + posts.find(uuid: value) + end + + def had_many; end + def has_many; end + + def save + super + + return true unless changed? + return true unless inverse? + + had_one&.value = nil + has_one&.value = post.uuid.value + + true + end + + def related_methods + @related_methods ||= %i[has_one had_one].freeze + end end From a62039b50a1057b8f8b42689acda6a4c5871689a Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:26:56 -0300 Subject: [PATCH 03/65] fix: editar desde el panel --- app/views/posts/attribute_ro/_has_one.haml | 6 ++++++ app/views/posts/attributes/_has_one.haml | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 app/views/posts/attribute_ro/_has_one.haml create mode 100644 app/views/posts/attributes/_has_one.haml diff --git a/app/views/posts/attribute_ro/_has_one.haml b/app/views/posts/attribute_ro/_has_one.haml new file mode 100644 index 00000000..c7e06be8 --- /dev/null +++ b/app/views/posts/attribute_ro/_has_one.haml @@ -0,0 +1,6 @@ +%tr{ id: attribute } + %th= post_label_t(attribute, post: post) + %td{ dir: dir, lang: locale } + - p = metadata.belongs_to + - if p + = link_to p.title.value, site_post_path(site, p.id) diff --git a/app/views/posts/attributes/_has_one.haml b/app/views/posts/attributes/_has_one.haml new file mode 100644 index 00000000..b0d21f35 --- /dev/null +++ b/app/views/posts/attributes/_has_one.haml @@ -0,0 +1,7 @@ +.form-group + = label_tag "#{base}_#{attribute}", post_label_t(attribute, post: post) + = select_tag(plain_field_name_for(base, attribute), + options_for_select(metadata.values, metadata.value), + **field_options(attribute, metadata), include_blank: t('.empty')) + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata From 6e3408777790211724ef79b91dfc50ca7401086f Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:28:45 -0300 Subject: [PATCH 04/65] fixup! fix: editar desde el panel --- app/views/posts/attribute_ro/_has_one.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/posts/attribute_ro/_has_one.haml b/app/views/posts/attribute_ro/_has_one.haml index c7e06be8..425e659e 100644 --- a/app/views/posts/attribute_ro/_has_one.haml +++ b/app/views/posts/attribute_ro/_has_one.haml @@ -1,6 +1,6 @@ %tr{ id: attribute } %th= post_label_t(attribute, post: post) %td{ dir: dir, lang: locale } - - p = metadata.belongs_to + - p = metadata.has_one - if p = link_to p.title.value, site_post_path(site, p.id) From a053fe6239a2e3258b60cef96cdf6bb14c7bbf1a Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:36:13 -0300 Subject: [PATCH 05/65] fix: no comportarse como un array --- app/models/metadata_has_one.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 38911e1d..686afc6e 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class MetadataHasOne < MetadataHasMany +class MetadataHasOne < MetadataBelongsTo def had_one return default_value if value_was.blank? @@ -13,11 +13,18 @@ class MetadataHasOne < MetadataHasMany posts.find(uuid: value) end - def had_many; end - def has_many; end + def belonged_to; end + def belongs_to; end def save - super + # XXX: DRY + if !changed? + self[:value] = document_value + + return true + end + + self[:value] = sanitize value return true unless changed? return true unless inverse? @@ -31,4 +38,8 @@ class MetadataHasOne < MetadataHasMany def related_methods @related_methods ||= %i[has_one had_one].freeze end + + def indexable_values + has_one&.title&.value + end end From b09d051de19a9b8ea8a3063e079be30062e72d40 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:42:09 -0300 Subject: [PATCH 06/65] fix: sintaxis correcta para encontrar uno solo --- app/models/metadata_has_one.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 686afc6e..41b2f7cd 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -4,13 +4,13 @@ class MetadataHasOne < MetadataBelongsTo def had_one return default_value if value_was.blank? - posts.find(uuid: value) + posts.find(value, uuid: true) end def has_one return default_value if value.blank? - posts.find(uuid: value) + posts.find(value, uuid: true) end def belonged_to; end From ce7c7ffd96d07a421c9f0537cb161a71ac4265e4 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:45:02 -0300 Subject: [PATCH 07/65] fix: reusar belongs to --- app/models/metadata_has_one.rb | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 41b2f7cd..239bf2e8 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -1,20 +1,8 @@ # frozen_string_literal: true class MetadataHasOne < MetadataBelongsTo - def had_one - return default_value if value_was.blank? - - posts.find(value, uuid: true) - end - - def has_one - return default_value if value.blank? - - posts.find(value, uuid: true) - end - - def belonged_to; end - def belongs_to; end + alias has_one belongs_to + alias had_one belonged_to def save # XXX: DRY @@ -38,8 +26,4 @@ class MetadataHasOne < MetadataBelongsTo def related_methods @related_methods ||= %i[has_one had_one].freeze end - - def indexable_values - has_one&.title&.value - end end From 72dd7e66ad7abac6924d1eaa2dfd70be755336fd Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:50:49 -0300 Subject: [PATCH 08/65] fix: poder guardar --- app/models/metadata_belongs_to.rb | 2 +- app/models/metadata_has_one.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index e1b84438..8726f1b1 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -41,7 +41,7 @@ class MetadataBelongsTo < MetadataRelatedPosts # anterior if belonged_to.present? if belonged_to[inverse].respond_to? :has_one - belonged_to[inverse].value = nil + belonged_to[inverse].value = '' else belonged_to[inverse].value = belonged_to[inverse].value.reject do |rej| rej == post.uuid.value diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 239bf2e8..93aaba50 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -17,8 +17,8 @@ class MetadataHasOne < MetadataBelongsTo return true unless changed? return true unless inverse? - had_one&.value = nil - has_one&.value = post.uuid.value + had_one[inverse]&.value = '' + has_one[inverse]&.value = post.uuid.value true end From 29bae31e08b414f568cf862e27c6ed3d571a3e36 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:52:38 -0300 Subject: [PATCH 09/65] fix: quizas viene vacio --- app/models/metadata_has_one.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index 93aaba50..ae5c6617 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -17,8 +17,8 @@ class MetadataHasOne < MetadataBelongsTo return true unless changed? return true unless inverse? - had_one[inverse]&.value = '' - has_one[inverse]&.value = post.uuid.value + had_one&[inverse]&.value = '' + has_one&[inverse]&.value = post.uuid.value true end From e8c659be837b2435598794d55ff757aa12741c2c Mon Sep 17 00:00:00 2001 From: f Date: Sat, 8 Apr 2023 17:54:07 -0300 Subject: [PATCH 10/65] fixup! fix: quizas viene vacio --- app/models/metadata_has_one.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index ae5c6617..d1705e7d 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -17,8 +17,8 @@ class MetadataHasOne < MetadataBelongsTo return true unless changed? return true unless inverse? - had_one&[inverse]&.value = '' - has_one&[inverse]&.value = post.uuid.value + had_one[inverse]&.value = '' if had_one + has_one[inverse]&.value = post.uuid.value if has_one true end From 9ed22fb065d9c7367429b9034e298d6a9b4e0774 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 10 Apr 2023 18:06:01 -0300 Subject: [PATCH 11/65] =?UTF-8?q?fix:=20verificar=20que=20haya=20una=20rel?= =?UTF-8?q?aci=C3=B3n=20#13005?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_belongs_to.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index 8726f1b1..17ecaee8 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -50,10 +50,12 @@ class MetadataBelongsTo < MetadataRelatedPosts end # No duplicar las relaciones - if belongs_to[inverse].respond_to? :has_one - belongs_to[inverse].value = post.uuid.value - else - belongs_to[inverse].value = (belongs_to[inverse].value.dup << post.uuid.value) unless belongs_to.blank? || included? + if belongs_to.present? + if belongs_to[inverse].respond_to? :has_one + belongs_to[inverse].value = post.uuid.value + else + belongs_to[inverse].value = (belongs_to[inverse].value.dup << post.uuid.value) unless belongs_to.blank? || included? + end end true From d601f370455ce1ff7dad48210d74899de8639280 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 09:54:25 -0300 Subject: [PATCH 12/65] =?UTF-8?q?feat:=20a=20partir=20del=20post=20indexad?= =?UTF-8?q?o=20obtener=20la=20ubicaci=C3=B3n=20del=20archivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/indexed_post.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 7f6865f6..7e58b7bc 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -36,6 +36,13 @@ class IndexedPost < ApplicationRecord belongs_to :site + # La ubicación del Post en el disco + # + # @return [String] + def full_path + @full_path ||= File.join(site.path, "_#{locale}", "#{path}.markdown") + end + # Convertir locale a direccionario de PG # # @param [String,Symbol] From b928fa7bde27ecb5b4e9126253dff9a86fa3936b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 09:56:12 -0300 Subject: [PATCH 13/65] BREAKING CHANGE: las colecciones no generan instancias de document --- app/models/indexed_post.rb | 7 +++++++ app/models/site.rb | 13 +++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 7e58b7bc..e59e1a2f 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -43,6 +43,13 @@ class IndexedPost < ApplicationRecord @full_path ||= File.join(site.path, "_#{locale}", "#{path}.markdown") end + # La colección + # + # @return [Jekyll::Collection] + def collection + site.collections[locale.to_s] + end + # Convertir locale a direccionario de PG # # @param [String,Symbol] diff --git a/app/models/site.rb b/app/models/site.rb index a8c5e376..690264b4 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -218,17 +218,10 @@ class Site < ApplicationRecord jekyll.data end - # Traer las colecciones. Todos los artículos van a estar dentro de - # colecciones. + # Trae las colecciones desde el sitio, sin leer su contenido + # + # @return [Hash] def collections - unless @read - run_in_path do - jekyll.reader.read_collections - end - - @read = true - end - jekyll.collections end From ae745b3d46b830b55f0d60b7bba4755b9541a682 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 09:57:21 -0300 Subject: [PATCH 14/65] feat: obtener el document a partir del post indexado --- app/models/indexed_post.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index e59e1a2f..5c4b151e 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -50,6 +50,13 @@ class IndexedPost < ApplicationRecord site.collections[locale.to_s] end + # Obtiene el documento + # + # @return [Jekyll::Document] + def document + @document ||= Jekyll::Document.new(full_path, site: site.jekyll, collection: collection) + end + # Convertir locale a direccionario de PG # # @param [String,Symbol] From ecf44311eacb88ed88f0846cd5c67dcb7300fb04 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 09:57:44 -0300 Subject: [PATCH 15/65] feat: obtener el post a partir del post indexado --- app/models/indexed_post.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 5c4b151e..44a970c3 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -57,6 +57,22 @@ class IndexedPost < ApplicationRecord @document ||= Jekyll::Document.new(full_path, site: site.jekyll, collection: collection) end + # El Post + # + # @todo Decidir qué pasa si el archivo ya no existe + # @return [Post] + def post + @post ||= Post.new(document: document, site: site, layout: schema) + end + + # Devuelve el esquema de datos + # + # @todo Renombrar + # @return [Layout] + def schema + site.layouts[layout.to_sym] + end + # Convertir locale a direccionario de PG # # @param [String,Symbol] From 84419c05f815da0671e40601995237b2071f2bbf Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 09:59:42 -0300 Subject: [PATCH 16/65] feat: obtener valores desde la base de datos #7537 --- app/models/indexed_post.rb | 14 ++++++++++++++ app/models/metadata_template.rb | 4 +++- app/models/site.rb | 18 ------------------ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 44a970c3..ef239a7d 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -34,6 +34,20 @@ class IndexedPost < ApplicationRecord scope :in_category, ->(category) { where("front_matter->'categories' ? :category", category: category.to_s) } scope :by_usuarie, ->(usuarie) { where("front_matter->'usuaries' @> :usuarie::jsonb", usuarie: usuarie.to_s) } + # Trae todos los valores únicos para un atributo + # + # @param :attribute [String,Symbol] + # @return [Array] + scope :everything_of, ->(attribute) do + where('front_matter ? :attribute', attribute: attribute) + .pluck( + Arel.sql( + ActiveRecord::Base::sanitize_sql(['front_matter -> :attribute', attribute: attribute]) + ) + ) + .flatten.uniq + end + belongs_to :site # La ubicación del Post en el disco diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index 5de54be1..6012fe87 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -74,8 +74,10 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, # Valores posibles, busca todos los valores actuales en otros # artículos del mismo sitio + # + # @return [Array] def values - site.everything_of(name, lang: lang) + site.indexed_posts.everything_of(name) end # Valor actual o por defecto. Al memoizarlo podemos modificarlo diff --git a/app/models/site.rb b/app/models/site.rb index 690264b4..2f0c56bc 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -317,24 +317,6 @@ class Site < ApplicationRecord end end - # Trae todos los valores disponibles para un campo - # - # TODO: Traer recursivamente, si el campo contiene Hash - # - # TODO: Mover a PostRelation#pluck - # - # @param attr [Symbol|String] El atributo a buscar - # @return Array - def everything_of(attr, lang: nil) - Rails.cache.fetch("#{cache_key_with_version}/everything_of/#{lang}/#{attr}", expires_in: 1.hour) do - attr = attr.to_sym - - posts(lang: lang).flat_map do |p| - p[attr].value if p.attribute? attr - end.uniq.compact - end - end - # Poner en la cola de compilación def enqueue! update(status: 'enqueued') if waiting? From 6946e86a025a5729fea1d8b16ac8d1eccd8e89c5 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:00:50 -0300 Subject: [PATCH 17/65] feat: reordenar usando los posts indexados --- app/services/post_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 4631a9a4..d59bc8c0 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -74,7 +74,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # { uuid => 2, uuid => 1, uuid => 0 } def reorder reorder = params.require(:post).permit(reorder: {})&.dig(:reorder)&.transform_values(&:to_i) - posts = site.posts(lang: locale).where(uuid: reorder.keys) + posts = site.indexed_posts(locale: locale).where(post_id: reorder.keys).map(&:post) files = posts.map do |post| next unless post.attribute? :order From ab98119cfeb902ecab150e9b1898fa88890a2b25 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:04:53 -0300 Subject: [PATCH 18/65] =?UTF-8?q?feat:=20encontrar=20el=20post=20a=20edita?= =?UTF-8?q?r=20desde=20su=20indexaci=C3=B3n=20#7537?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/posts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 9720fe13..77354be1 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -160,7 +160,7 @@ class PostsController < ApplicationController end def post - @post ||= site.posts(lang: locale).find(params[:post_id] || params[:id]) + @post ||= site.indexed_posts.find_by!(locale: locale, path: params[:post_id] || params[:id]).post end # Recuerda el nombre del servicio de subida de archivos From d58cb05c7aef36b46f7ff3a1a79803a775f5c688 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:06:28 -0300 Subject: [PATCH 19/65] =?UTF-8?q?feat:=20relacionar=20posts=20desde=20su?= =?UTF-8?q?=20indexaci=C3=B3n=20#7537?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_belongs_to.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index be1fa670..204d7bed 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -67,13 +67,17 @@ class MetadataBelongsTo < MetadataRelatedPosts end # El Post relacionado con este artículo + # + # @return [Post,nil] def belongs_to - posts.find(value, uuid: true) if value.present? + posts.find_by(post_id: value)&.post if value.present? end # El artículo relacionado anterior + # + # @return [Post,nil] def belonged_to - posts.find(value_was, uuid: true) if value_was.present? + posts.find_by(post_id: value_was)&.post if value_was.present? end def related_posts? From 95e3defd8b2420a3f3fa82ce5b98fe67fd6cb62b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:11:30 -0300 Subject: [PATCH 20/65] =?UTF-8?q?feat:=20relacionar=20posts=20por=20su=20i?= =?UTF-8?q?ndexaci=C3=B3n=20#7537?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/metadata_has_many.rb | 8 ++++++-- app/models/metadata_related_posts.rb | 26 ++++++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/app/models/metadata_has_many.rb b/app/models/metadata_has_many.rb index 13f0dcf5..82ec333a 100644 --- a/app/models/metadata_has_many.rb +++ b/app/models/metadata_has_many.rb @@ -7,17 +7,21 @@ # apuntando a un Post, que se mantiene actualizado como el actual. class MetadataHasMany < MetadataRelatedPosts # Todos los Post relacionados + # + # @return [Array] def has_many return default_value if value.blank? - posts.where(uuid: value) + posts.where(post_id: value).map(&:post) end # La relación anterior + # + # @return [Array] def had_many return default_value if value_was.blank? - posts.where(uuid: value_was) + posts.where(post_id: value_was).map(&:post) end def inverse? diff --git a/app/models/metadata_related_posts.rb b/app/models/metadata_related_posts.rb index 092f219a..b1ebfe4e 100644 --- a/app/models/metadata_related_posts.rb +++ b/app/models/metadata_related_posts.rb @@ -3,14 +3,16 @@ # Devuelve una lista de títulos y UUID de todos los posts del mismo # idioma que el actual, para usar con input-map.js class MetadataRelatedPosts < MetadataArray - # Genera un Hash de { title | slug => uuid } y excluye el Post actual + # Genera un Hash de { title (schema) => uuid } para usar en + # options_for_select + # # @return [Hash] def values - @values ||= posts.map do |p| - next if p.uuid.value == post.uuid.value - - [title(p), p.uuid.value] - end.compact.to_h + @values ||= posts.pluck(:title, :layout, :post_id).map do |row| + row.tap do |value| + value[0] = "#{value[0]} (#{site.layouts[value.delete_at(1)].humanized_name})" + end + end.to_h end # Las relaciones nunca son privadas @@ -23,21 +25,25 @@ class MetadataRelatedPosts < MetadataArray end def indexable_values - posts.where(uuid: value).map(&:title).map(&:value) + posts.where(post_id: value).pluck(:title) end private - # Obtiene todos los posts y opcionalmente los filtra + # Obtiene todos los posts menos el actual y opcionalmente los filtra + # + # @return [IndexedPost::ActiveRecord_AssociationRelation] def posts - site.posts(lang: lang).where(**filter) + site.indexed_posts.where(locale: locale).where.not(post_id: post.uuid.value).where(**filter) end def title(post) "#{post&.title&.value || post&.slug&.value} (#{post.layout.humanized_name})" end - # Encuentra el filtro + # Encuentra el filtro desde el esquema del atributo + # + # @return [Hash] def filter layout.metadata.dig(name, 'filter')&.to_h&.symbolize_keys || {} end From ea251e5d5b3abfa9d8c0f7140bade9bff79d56f5 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:12:18 -0300 Subject: [PATCH 21/65] =?UTF-8?q?feat:=20indexar=20m=C3=A1s=20atributos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/post/indexable.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/models/post/indexable.rb b/app/models/post/indexable.rb index 4e46d7b2..9629efd0 100644 --- a/app/models/post/indexable.rb +++ b/app/models/post/indexable.rb @@ -40,16 +40,19 @@ class Post private - # Los metadatos que se almacenan como objetos JSON. Empezamos con - # las categorías porque se usan para filtrar en el listado de - # artículos. + # Los metadatos que se almacenan como objetos JSON. # # @return [Hash] def indexable_front_matter {}.tap do |ifm| ifm[:usuaries] = usuaries.map(&:id) ifm[:draft] = attribute?(:draft) ? draft.value : false - ifm[:categories] = categories.indexable_values if attribute? :categories + + indexable_attributes.select do |attr| + self[attr].front_matter? + end.each do |attr| + ifm[attr] = self[attr].indexable_values + end end end From 59828b3f6a735de6d6e82b0e279ae190e943d240 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:13:32 -0300 Subject: [PATCH 22/65] feat: generar un post nuevo --- app/models/post.rb | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index fab9ab06..fff9e17f 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -31,14 +31,34 @@ class Post def find_layout(path) File.foreach(path).lazy.grep(/^layout: /).take(1).first&.split(' ')&.last&.tr('\'', '')&.tr('"', '')&.to_sym end + + # Genera un Post nuevo + # + # @params :site [Site] + # @params :locale [String, Symbol] + # @params :document [Jekyll::Document] + # @params :layout [String,Symbol] + # @return [Post] + def build(**args) + args[:document] ||= + begin + site = args[:site] + collection = site.collections[args[:locale].to_s] + + Jekyll::Document.new('', site: site.jekyll, collection: collection).tap do |doc| + doc.data['date'] = Date.today.to_time + end + end + + Post.new(**args) + end end # Redefinir el inicializador de OpenStruct # - # @param site: [Site] el sitio en Sutty - # @param document: [Jekyll::Document] el documento leído por Jekyll - # @param layout: [Layout] la plantilla - # + # @param :site [Site] el sitio en Sutty + # @param :document [Jekyll::Document] el documento leído por Jekyll + # @param :layout [Layout] la plantilla def initialize(**args) default_attributes_missing(**args) From 1ad4eeccb4e93b5ccaa2ffdfca3f8b1c71f324af Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:14:13 -0300 Subject: [PATCH 23/65] fix: no usar PostRelation para instanciar un nuevo Post #7537 obligaba a cargar casi todo el sitio en memoria y muchas lecturas de disco --- app/controllers/posts_controller.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 77354be1..078e16f8 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -54,9 +54,11 @@ class PostsController < ApplicationController def new authorize Post - @post = site.posts(lang: locale).build(layout: params[:layout]) - breadcrumb I18n.t('loaf.breadcrumbs.posts.new', layout: @post.layout.humanized_name.downcase), '' + layout = site.layouts[params[:layout].to_sym] + @post = Post.build(locale: locale, layout: layout, site: site) + + breadcrumb I18n.t('loaf.breadcrumbs.posts.new', layout: layout.humanized_name.downcase), '' end def create From 15fa653a6ddd4288283806738a5d706ee643bd14 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:15:13 -0300 Subject: [PATCH 24/65] feat: obtener el post indexado a partir del post --- app/models/post.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index fff9e17f..ab91bd43 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -54,6 +54,11 @@ class Post end end + # @return [IndexedPost,nil] + def indexed_post + site.indexed_posts.find_by(locale: lang.value, path: id) + end + # Redefinir el inicializador de OpenStruct # # @param :site [Site] el sitio en Sutty @@ -307,8 +312,6 @@ class Post def destroy run_callbacks :destroy do FileUtils.rm_f path.absolute - - site.delete_post self end end alias destroy! destroy From 5c8d1df6c7fe3e5d70537b4dc999bc37a8f41ad9 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:15:43 -0300 Subject: [PATCH 25/65] BREAKING CHANGE: deprecar PostRelation --- app/models/post_relation.rb | 156 ------------------------------------ 1 file changed, 156 deletions(-) delete mode 100644 app/models/post_relation.rb diff --git a/app/models/post_relation.rb b/app/models/post_relation.rb deleted file mode 100644 index 531d3cc4..00000000 --- a/app/models/post_relation.rb +++ /dev/null @@ -1,156 +0,0 @@ -# frozen_string_literal: true - -# La relación de un sitio con sus artículos, esto nos permite generar -# artículos como si estuviésemos usando ActiveRecord. -class PostRelation < Array - # No necesitamos cambiar el sitio - attr_reader :site, :lang - - def initialize(site:, lang:) - @site = site - @lang = lang - # Proseguimos la inicialización sin valores por defecto - super() - end - - # Genera un artículo nuevo con los parámetros que le pasemos y lo suma - # al array - def build(**args) - args[:lang] = lang - args[:document] ||= build_document(collection: args[:lang]) - args[:layout] = build_layout(args[:layout]) - - post = Post.new(site: site, **args) - - self << post - post - end - - def create(**args) - post = build(**args) - post.save - post - end - - alias sort_by_generic sort_by - alias sort_by_generic! sort_by! - - # Permite ordenar los artículos por sus atributos - # - # XXX: Prestar atención cuando estamos mezclando artículos con - # diferentes tipos de atributos. - def sort_by(*attrs) - sort_by_generic do |post| - attrs.map do |attr| - # TODO: detectar el tipo de atributo faltante y obtener el valor - # por defecto para hacer la comparación - if post.attributes.include? attr - post.public_send(attr).value - else - 0 - end - end - end - end - - def sort_by!(*attrs) - replace sort_by(*attrs) - end - - alias find_generic find - - # Encontrar un post por su UUID - def find(id, uuid: false) - find_generic do |p| - if uuid - p.uuid.value == id - else - p.id == id - end - end - end - - # Encuentra el primer post por el valor de los atributos - # - # @param [Hash] - # @return [Post] - def find_by(**args) - find_generic do |post| - args.map do |attr, value| - post.attribute?(attr) && - post.public_send(attr).value == value - end.all? - end - end - - # Encuentra todos los Post que cumplan las condiciones - # - # TODO: Implementar caché - # - # @param [Hash] Mapa de atributo => valor. Valor puede ser un Array - # de valores - # @return [PostRelation] - def where(**args) - return self if args.empty? - - begin - PostRelation.new(site: site, lang: lang).concat(select do |post| - result = args.map do |attr, value| - next unless post.attribute?(attr) - - attribute = post[attr] - - # TODO: Si el valor del atributo también es un Array deberíamos - # cruzar ambas. - case value - when Array then value.include? attribute.value - else - case attribute.value - when Array then attribute.value.include? value - else attribute.value == value - end - end - end.compact - - # Un Array vacío devuelve true para all? - result.present? && result.all? - end) - end - end - - # Como Array#select devolviendo una relación - # - # @return [PostRelation] - alias array_select select - def select(&block) - PostRelation.new(site: site, lang: lang).concat array_select(&block) - end - - # Intenta guardar todos y devuelve true si pudo - def save_all(validate: true) - map do |post| - post.save(validate: validate) - end.all? - end - - private - - def build_layout(layout = nil) - return layout if layout.is_a? Layout - - site.layouts[layout&.to_sym || :post] - end - - # Devuelve una colección Jekyll que hace pasar el documento - def build_collection(label:) - Jekyll::Collection.new(site.jekyll, label.to_s) - end - - # Un documento borrador con algunas propiedades por defecto - def build_document(collection:) - col = build_collection(label: collection) - doc = Jekyll::Document.new('', site: site.jekyll, collection: col) - doc.data['date'] = Date.today.to_time - doc - end -end From d4f85da0188ba77c483f943f8558cd409e399a51 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:15:57 -0300 Subject: [PATCH 26/65] feat: detectar si un post existe en disco --- app/models/indexed_post.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index ef239a7d..02679ec0 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -87,6 +87,13 @@ class IndexedPost < ApplicationRecord site.layouts[layout.to_sym] end + # Existe físicamente? + # + # @return [Boolean] + def exist? + File.exist?(full_path) + end + # Convertir locale a direccionario de PG # # @param [String,Symbol] From b2e6b76870b2c7dc4088f4ec0fa576cc48dd5fea Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:16:47 -0300 Subject: [PATCH 27/65] fix: no usar post relation --- app/services/post_service.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index d59bc8c0..0d989871 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -7,8 +7,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # # @return Post def create - self.post = site.posts(lang: locale) - .build(layout: layout) + self.post = Post.build(site: site, locale: locale, layout: layout) post.usuaries << usuarie params[:post][:draft] = true if site.invitade? usuarie @@ -29,8 +28,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do def create_anonymous # XXX: Confiamos en el parámetro de idioma porque estamos # verificándolos en Site#posts - self.post = site.posts(lang: locale) - .build(layout: layout) + self.post = Post.build(site: site, locale: locale, layout: layouts) # Los artículos anónimos siempre son borradores params[:draft] = true @@ -118,12 +116,16 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end end + # @return [Symbol] def locale params.dig(:post, :lang)&.to_sym || I18n.locale end + # @return [Layout] def layout - params.dig(:post, :layout) || params[:layout] + site.layouts[ + (params.dig(:post, :layout) || params[:layout]).to_sym + ] end # Actualiza los artículos relacionados según los métodos que los From 7df1af2a5400e646218b5d00b3a22fa78a9e3e0a Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:17:26 -0300 Subject: [PATCH 28/65] BREAKING CHANGE: eliminar Site#posts --- app/models/site.rb | 50 ---------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 2f0c56bc..3ccd27d3 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -230,55 +230,6 @@ class Site < ApplicationRecord @config ||= Site::Config.new(self) end - # Los posts en el idioma actual o en uno en particular - # - # @param lang: [String|Symbol] traer los artículos de este idioma - def posts(lang: nil) - # Traemos los posts del idioma actual por defecto o el que haya - lang ||= locales.include?(I18n.locale) ? I18n.locale : default_locale - lang = lang.to_sym - - # Crea un Struct dinámico con los valores de los locales, si - # llegamos a pasar un idioma que no existe vamos a tener una - # excepción NoMethodError - @posts ||= Struct.new(*locales).new - - return @posts[lang] unless @posts[lang].blank? - - @posts[lang] = PostRelation.new site: self, lang: lang - - # No fallar si no existe colección para este idioma - # XXX: queremos fallar silenciosamente? - (collections[lang.to_s]&.docs || []).each do |doc| - layout = layouts[Post.find_layout(doc.path)] - - @posts[lang].build(document: doc, layout: layout, lang: lang) - rescue TypeError => e - ExceptionNotifier.notify_exception(e, data: { site: name, site_id: id, path: doc.path }) - end - - @posts[lang] - end - - # Todos los Post del sitio para poder buscar en todos. - # - # @return PostRelation - def docs - @docs ||= PostRelation.new(site: self, lang: :docs).push(locales.flat_map do |locale| - posts(lang: locale) - end).flatten! - end - - # Elimina un artículo de la colección - def delete_post(post) - lang = post.lang.value - - collections[lang.to_s].docs.delete(post.document) && - posts(lang: lang).delete(post) - - post - end - # Obtiene todas las plantillas de artículos # # @return [Hash] { post: Layout } @@ -433,7 +384,6 @@ class Site < ApplicationRecord @incompatible_layouts = nil @jekyll = nil @config = nil - @posts = nil @docs = nil end From 6f9fe8fdbc5f627753a887a160b1ee74bb2474b5 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:18:29 -0300 Subject: [PATCH 29/65] fix: encontrar la licencia por el post indexado --- app/services/site_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 7022244c..9d748f8f 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -144,7 +144,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do return true if site.licencia.custom? with_all_locales do |locale| - post = site.posts(lang: locale).find_by(layout: 'license') + post = site.indexed_posts(locale: locale).find_by(layout: 'license')&.post change_licencia(post: post) if post end.compact.map(&:valid?).all? From 9cb2850a13eefbbc1566d893108ffc4c870a3760 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 10:19:25 -0300 Subject: [PATCH 30/65] fix: encontrar el post relacionado por su indexacion --- app/views/posts/attribute_ro/_related_posts.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/posts/attribute_ro/_related_posts.haml b/app/views/posts/attribute_ro/_related_posts.haml index c43b589e..6014e160 100644 --- a/app/views/posts/attribute_ro/_related_posts.haml +++ b/app/views/posts/attribute_ro/_related_posts.haml @@ -3,7 +3,7 @@ %td %ul{ dir: dir, lang: locale } - metadata.value.each do |v| - - p = site.posts(lang: post.lang.value).find(v, uuid: true) + - p = site.indexed_posts(locale: post.lang.value).find_by(post_id: v)&.post -# XXX: Ignorar todos los posts no encontrados (ej: fueron borrados o el uuid cambió) From ad3d52e2e78ce58cb100728aa27b1ba6b159e7b6 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 17:23:55 -0300 Subject: [PATCH 31/65] fix: usar posts indexados para relacionar traducciones --- app/models/metadata_locales.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 37b50286..85419da8 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -33,17 +33,15 @@ class MetadataLocales < MetadataHasAndBelongsToMany # # @return [Array] def other_locales - site.locales.reject do |locale| - locale == post.lang.value.to_sym + @other_locales ||= site.locales.reject do |other_locale| + other_locale.to_s == locale end end # Obtiene todos los posts de los otros locales con el mismo layout # - # @return [PostRelation] + # @return [IndexedPost::ActiveRecord_AssociationRelation] def posts - other_locales.map do |locale| - site.posts(lang: locale).where(layout: post.layout.value) - end.reduce(&:concat) || PostRelation.new(site: site, lang: 'any') + site.indexed_posts(locale: other_locales).where(layout: post.layout.value).where.not(post_id: post.uuid.value) end end From 5b9df0d02013ee0b3d7ffce212390256e950e0e8 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 17:30:37 -0300 Subject: [PATCH 32/65] fix: locales --- app/models/metadata_locales.rb | 19 +++++++++++-------- app/models/metadata_related_posts.rb | 8 ++------ app/views/posts/attributes/_locales.haml | 1 - 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/app/models/metadata_locales.rb b/app/models/metadata_locales.rb index 85419da8..b4ddf485 100644 --- a/app/models/metadata_locales.rb +++ b/app/models/metadata_locales.rb @@ -6,11 +6,16 @@ class MetadataLocales < MetadataHasAndBelongsToMany # # @return { lang: { title: uuid } } def values - @values ||= site.locales.map do |locale| - [locale, posts.where(lang: locale).map do |post| - [title(post), post.uuid.value] - end.to_h] - end.to_h + @values ||= other_locales.to_h do |other_locale| + [ + other_locale, + posts.where(locale: other_locale).pluck(:title, :layout, :post_id).to_h do |row| + row.tap do |value| + value[0] = "#{value[0]} (#{site.layouts[value.delete_at(1)].humanized_name})" + end + end + ] + end end # Siempre hay una relación inversa @@ -33,9 +38,7 @@ class MetadataLocales < MetadataHasAndBelongsToMany # # @return [Array] def other_locales - @other_locales ||= site.locales.reject do |other_locale| - other_locale.to_s == locale - end + @other_locales ||= site.locales - [locale] end # Obtiene todos los posts de los otros locales con el mismo layout diff --git a/app/models/metadata_related_posts.rb b/app/models/metadata_related_posts.rb index b1ebfe4e..50b8660e 100644 --- a/app/models/metadata_related_posts.rb +++ b/app/models/metadata_related_posts.rb @@ -8,11 +8,11 @@ class MetadataRelatedPosts < MetadataArray # # @return [Hash] def values - @values ||= posts.pluck(:title, :layout, :post_id).map do |row| + @values ||= posts.pluck(:title, :layout, :post_id).to_h do |row| row.tap do |value| value[0] = "#{value[0]} (#{site.layouts[value.delete_at(1)].humanized_name})" end - end.to_h + end end # Las relaciones nunca son privadas @@ -37,10 +37,6 @@ class MetadataRelatedPosts < MetadataArray site.indexed_posts.where(locale: locale).where.not(post_id: post.uuid.value).where(**filter) end - def title(post) - "#{post&.title&.value || post&.slug&.value} (#{post.layout.humanized_name})" - end - # Encuentra el filtro desde el esquema del atributo # # @return [Hash] diff --git a/app/views/posts/attributes/_locales.haml b/app/views/posts/attributes/_locales.haml index 4978f6b4..05592fbd 100644 --- a/app/views/posts/attributes/_locales.haml +++ b/app/views/posts/attributes/_locales.haml @@ -6,7 +6,6 @@ post: post, attribute: attribute, metadata: metadata - site.locales.each do |locale| - - next if post.lang.value == locale - locale_t = t("locales.#{locale}.name", default: locale.to_s.humanize) - value = metadata.value.find do |v| - metadata.values[locale].values.include? v From 35e4ef045d8710a7b2200254d523f30dc0315f18 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 17:33:21 -0300 Subject: [PATCH 33/65] fix: usar el orden indexado --- app/models/metadata_order.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_order.rb b/app/models/metadata_order.rb index 1b33a388..577e3c85 100644 --- a/app/models/metadata_order.rb +++ b/app/models/metadata_order.rb @@ -5,7 +5,7 @@ class MetadataOrder < MetadataTemplate # El valor según la posición del post en la relación ordenada por # fecha, a fecha más alta, posición más alta def default_value - super || site.posts(lang: lang).sort_by(:date).index(post) + super || (site.indexed_posts(locale: locale).first.order + 1) end def save From c241f251056319acda6e6b7439bed4cda133d81c Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 17:34:30 -0300 Subject: [PATCH 34/65] fix: deprecar lang en favor de locale --- app/models/metadata_template.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index 6012fe87..a56f0bad 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -62,12 +62,15 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, end # Trae el idioma actual del sitio o del panel + # + # @deprecated Empezar a usar locale # @return [String] def lang @lang ||= post&.lang&.value || I18n.locale end - # El valor por defecto + alias_method :locale, :lang + def default_value layout.metadata.dig(name, 'default', lang.to_s) end From 833022c9c4d901634f2a431627060ea1754ad6ea Mon Sep 17 00:00:00 2001 From: f Date: Fri, 6 Oct 2023 17:35:54 -0300 Subject: [PATCH 35/65] fix: MetadataTemplate#locale es una String --- app/models/metadata_template.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/metadata_template.rb b/app/models/metadata_template.rb index a56f0bad..6e13aecd 100644 --- a/app/models/metadata_template.rb +++ b/app/models/metadata_template.rb @@ -66,13 +66,16 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type, # @deprecated Empezar a usar locale # @return [String] def lang - @lang ||= post&.lang&.value || I18n.locale + @lang ||= post&.lang&.value || I18n.locale.to_s end alias_method :locale, :lang + # El valor por defecto desde el esquema de datos + # + # @return [any] def default_value - layout.metadata.dig(name, 'default', lang.to_s) + layout.metadata.dig(name, 'default', lang) end # Valores posibles, busca todos los valores actuales en otros From f28ba4095388ae965b129ac5b69c51d3c532ecca Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 12:22:18 -0300 Subject: [PATCH 36/65] =?UTF-8?q?fix:=20leer=20el=20sitio=20completo=20dur?= =?UTF-8?q?ante=20la=20indexaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/site/index.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/site/index.rb b/app/models/site/index.rb index e11095e3..20914905 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -14,7 +14,14 @@ class Site def index_posts! Site.transaction do - docs.each(&:index!) + jekyll.read + jekyll.documents.each do |doc| + doc.read! + + Post.new(document: doc, site: self, layout: layouts[doc['layout'].to_sym).index! + end + + update(last_indexed_commit: repository.head_commit.oid) end end end From 5eafbaa5e98b66605298f4f062d3673bcc87a978 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 12:22:47 -0300 Subject: [PATCH 37/65] fix: poder indexar desde cero --- app/models/metadata_order.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/metadata_order.rb b/app/models/metadata_order.rb index 577e3c85..f63a7d49 100644 --- a/app/models/metadata_order.rb +++ b/app/models/metadata_order.rb @@ -5,7 +5,7 @@ class MetadataOrder < MetadataTemplate # El valor según la posición del post en la relación ordenada por # fecha, a fecha más alta, posición más alta def default_value - super || (site.indexed_posts(locale: locale).first.order + 1) + super || ((site.indexed_posts.where(locale: locale).first&.order || 0) + 1) end def save From 747ce788a25f3f3e48e83287aea6351515ebe3dd Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 12:23:01 -0300 Subject: [PATCH 38/65] =?UTF-8?q?fix:=20un=20filtro=20con=20par=C3=A1metro?= =?UTF-8?q?s=20vac=C3=ADos=20no=20devuelve=20una=20asociaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit en cambio where(nil) no produce ningún efecto --- app/models/metadata_related_posts.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/metadata_related_posts.rb b/app/models/metadata_related_posts.rb index 50b8660e..a9aaaa21 100644 --- a/app/models/metadata_related_posts.rb +++ b/app/models/metadata_related_posts.rb @@ -34,14 +34,14 @@ class MetadataRelatedPosts < MetadataArray # # @return [IndexedPost::ActiveRecord_AssociationRelation] def posts - site.indexed_posts.where(locale: locale).where.not(post_id: post.uuid.value).where(**filter) + site.indexed_posts.where(locale: locale).where.not(post_id: post.uuid.value).where(filter) end # Encuentra el filtro desde el esquema del atributo # - # @return [Hash] + # @return [Hash,nil] def filter - layout.metadata.dig(name, 'filter')&.to_h&.symbolize_keys || {} + layout.metadata.dig(name, 'filter')&.to_h&.symbolize_keys end def sanitize(uuid) From 40f5eca7abac7aa1a92f36373830c1f476d51431 Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 12:23:39 -0300 Subject: [PATCH 39/65] =?UTF-8?q?fix:=20algunos=20metadatos=20todav=C3=ADa?= =?UTF-8?q?=20no=20son=20indexables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/post/indexable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/post/indexable.rb b/app/models/post/indexable.rb index 9629efd0..3aa8ce59 100644 --- a/app/models/post/indexable.rb +++ b/app/models/post/indexable.rb @@ -51,7 +51,7 @@ class Post indexable_attributes.select do |attr| self[attr].front_matter? end.each do |attr| - ifm[attr] = self[attr].indexable_values + ifm[attr] = self[attr].try(:indexable_values) end end end From 8350bfdfeb971987abbf0d611f391280841bbd3f Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 12:23:57 -0300 Subject: [PATCH 40/65] fix: no leer los posts al obtener relaciones --- app/views/posts/attribute_ro/_related_posts.haml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/views/posts/attribute_ro/_related_posts.haml b/app/views/posts/attribute_ro/_related_posts.haml index 6014e160..aa4aff2e 100644 --- a/app/views/posts/attribute_ro/_related_posts.haml +++ b/app/views/posts/attribute_ro/_related_posts.haml @@ -2,10 +2,9 @@ %th= post_label_t(attribute, post: post) %td %ul{ dir: dir, lang: locale } - - metadata.value.each do |v| - - p = site.indexed_posts(locale: post.lang.value).find_by(post_id: v)&.post + - site.indexed_posts.where(locale: post.lang.value, post_id: metadata.value).find_each do |p| -# XXX: Ignorar todos los posts no encontrados (ej: fueron borrados o el uuid cambió) - next unless p - %li= link_to p.title.value, site_post_path(site, p.id) + %li= link_to p.title, site_post_path(site, p.path) From 98d1ec125a8cd57df0dc7e3b415419895f343b8e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 20 Oct 2023 13:10:53 -0300 Subject: [PATCH 41/65] fixup! fix: poder indexar desde cero --- app/models/site/index.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/site/index.rb b/app/models/site/index.rb index 20914905..2f2d1dc9 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -18,7 +18,7 @@ class Site jekyll.documents.each do |doc| doc.read! - Post.new(document: doc, site: self, layout: layouts[doc['layout'].to_sym).index! + Post.new(document: doc, site: self, layout: layouts[doc['layout'].to_sym]).index! end update(last_indexed_commit: repository.head_commit.oid) From 232cda13794f4ed3d2e22093802e48fb2ea55403 Mon Sep 17 00:00:00 2001 From: f Date: Wed, 25 Oct 2023 15:29:22 -0300 Subject: [PATCH 42/65] refactor: guardar las asociaciones en PostService (cherry picked from commit 4cf57a441a8d255cfd60a6e59c466f7b40934c04) --- .../concerns/metadata/inverse_concern.rb | 23 ++++ app/models/metadata_belongs_to.rb | 78 +---------- .../metadata_has_and_belongs_to_many.rb | 43 +----- app/models/metadata_has_many.rb | 56 +------- app/services/post_service.rb | 122 +++++++++++++----- app/views/posts/attribute_ro/_belongs_to.haml | 4 +- .../_has_and_belongs_to_many.haml | 4 +- app/views/posts/attribute_ro/_has_many.haml | 4 +- 8 files changed, 124 insertions(+), 210 deletions(-) create mode 100644 app/models/concerns/metadata/inverse_concern.rb diff --git a/app/models/concerns/metadata/inverse_concern.rb b/app/models/concerns/metadata/inverse_concern.rb new file mode 100644 index 00000000..aa300fa7 --- /dev/null +++ b/app/models/concerns/metadata/inverse_concern.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Metadata + module InverseConcern + extend ActiveSupport::Concern + + included do + # Hay una relación inversa? + # + # @return [Boolean] + def inverse? + inverse.present? + end + + # La relación inversa + # + # @return [Nil,Symbol] + def inverse + @inverse ||= layout.metadata.dig(name, 'inverse')&.to_sym + end + end + end +end diff --git a/app/models/metadata_belongs_to.rb b/app/models/metadata_belongs_to.rb index 204d7bed..93a1f710 100644 --- a/app/models/metadata_belongs_to.rb +++ b/app/models/metadata_belongs_to.rb @@ -3,6 +3,8 @@ # Almacena el UUID de otro Post y actualiza el valor en el Post # relacionado. class MetadataBelongsTo < MetadataRelatedPosts + include Metadata::InverseConcern + # TODO: Convertir algunos tipos de valores en módulos para poder # implementar varios tipos de campo sin repetir código # @@ -20,86 +22,12 @@ class MetadataBelongsTo < MetadataRelatedPosts document.data[name.to_s] 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 - if belonged_to.present? - belonged_to[inverse].value = belonged_to[inverse].value.reject do |rej| - rej == post.uuid.value - end - end - - # No duplicar las relaciones - belongs_to[inverse].value = (belongs_to[inverse].value.dup << 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 - # - # @return [Post,nil] - def belongs_to - posts.find_by(post_id: value)&.post if value.present? - end - - # El artículo relacionado anterior - # - # @return [Post,nil] - def belonged_to - posts.find_by(post_id: value_was)&.post if value_was.present? - end - - def related_posts? - true - end - - def related_methods - @related_methods ||= %i[belongs_to belonged_to].freeze - end - def indexable_values - belongs_to&.title&.value + posts.find_by_post_uuid(value).try(:title) end private - def post_exists? - return true if sanitize(value).blank? - - sanitize(value).present? && belongs_to.present? - end - def sanitize(uuid) uuid.to_s.gsub(/[^a-f0-9\-]/i, '') end diff --git a/app/models/metadata_has_and_belongs_to_many.rb b/app/models/metadata_has_and_belongs_to_many.rb index 2c4f3d43..2c1b0f96 100644 --- a/app/models/metadata_has_and_belongs_to_many.rb +++ b/app/models/metadata_has_and_belongs_to_many.rb @@ -1,46 +1,5 @@ # frozen_string_literal: true -# Establece una relación de muchos a muchos artículos. Cada campo es un -# Array de UUID que se mantienen sincronizados. -# -# Por ejemplo: -# -# Un libro puede tener muches autores y une autore muchos libros. La -# relación has_many tiene que traer todes les autores relacionades con -# 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 -# diferencia entre has_many y belongs_to. +# Establece una relación de muchos a muchos artículos class MetadataHasAndBelongsToMany < MetadataHasMany - # Mantiene la relación inversa si existe. - # - # La relación belongs_to se mantiene actualizada en la modificación - # actual. Lo que buscamos es mantener sincronizada esa relación. - # - # Buscamos en belongs_to la relación local, si se eliminó hay que - # quitarla de la relación remota, sino hay que agregarla. - # - def save - # XXX: No usamos super - self[:value] = sanitize value - - return true unless changed? - return true unless inverse? - - # XXX: Usamos asignación para aprovechar value= que setea el valor - # anterior en @value_was - (had_many - has_many).each do |remove| - remove[inverse].value = remove[inverse].value.reject do |rej| - rej == post.uuid.value - end - end - - (has_many - had_many).each do |add| - next unless add[inverse] - next if add[inverse].value.include? post.uuid.value - - add[inverse].value = (add[inverse].value.dup << post.uuid.value) - end - - true - end end diff --git a/app/models/metadata_has_many.rb b/app/models/metadata_has_many.rb index 82ec333a..c5f01f7c 100644 --- a/app/models/metadata_has_many.rb +++ b/app/models/metadata_has_many.rb @@ -6,59 +6,5 @@ # 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 - # - # @return [Array] - def has_many - return default_value if value.blank? - - posts.where(post_id: value).map(&:post) - end - - # La relación anterior - # - # @return [Array] - def had_many - return default_value if value_was.blank? - - posts.where(post_id: value_was).map(&:post) - end - - def inverse? - inverse.present? - end - - # La relación inversa - # - # @return [Nil,Symbol] - def inverse - @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 - super - - return true unless changed? - 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 + include Metadata::InverseConcern end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 0d989871..dc04dda6 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -3,7 +3,7 @@ # Este servicio se encarga de crear artículos y guardarlos en git, # asignándoselos a une usuarie PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do - # Crea un artículo nuevo + # Crea un artículo nuevo y modificar las asociaciones # # @return Post def create @@ -15,9 +15,21 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do post.slug.value = p[:slug] if p[:slug].present? end - commit(action: :created, add: update_related_posts) if post.update(post_params) + if post.update(post_params) + added_paths = [] + added_paths << post.path.value - update_site_license! + # Recorrer todas las asociaciones y agregarse donde corresponda + update_associations_forward(post) + + associated_posts_to_save.each do |associated_post| + next unless associated_post.save(validate: false) + + added_paths << associated_post.path.value + end + + commit(action: :created, add: added_paths) + end # Devolver el post aunque no se haya salvado para poder rescatar los # errores @@ -25,6 +37,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end # Crear un post anónimo, con opciones más limitadas. No usamos post. + # + # @todo Permitir asociaciones? def create_anonymous # XXX: Confiamos en el parámetro de idioma porque estamos # verificándolos en Site#posts @@ -36,20 +50,30 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do post end + # Al actualizar, modificamos un post pre-existente, todas las + # relaciones anteriores y las relaciones actuales. def update post.usuaries << usuarie params[:post][:draft] = true if site.invitade? usuarie - # Eliminar ("mover") el archivo si cambió de ubicación. if post.update(post_params) + # Eliminar ("mover") el archivo si cambió de ubicación. rm = [] rm << post.path.value_was if post.path.changed? - # Es importante que el artículo se guarde primero y luego los - # relacionados. - commit(action: :updated, add: update_related_posts, rm: rm) + added_paths = [] + added_paths << post.path.value - update_site_license! + # Recorrer todas las asociaciones y agregarse donde corresponda + update_associations_forward(post) + + associated_posts_to_save.each do |associated_post| + next unless associated_post.save(validate: false) + + added_paths << associated_post.path.value + end + + commit(action: :updated, add: added_paths, rm: rm) end # Devolver el post aunque no se haya salvado para poder rescatar los @@ -128,30 +152,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do ] end - # Actualiza los artículos relacionados según los métodos que los - # metadatos declaren. - # - # Este método se asegura que todos los artículos se guardan una sola - # vez. - # - # @return [Array] Lista de archivos modificados - def update_related_posts - posts = Set.new - - post.attributes.each do |a| - post[a].related_methods.each do |m| - next unless post[a].respond_to? m - - # La respuesta puede ser una PostRelation también - posts.merge [post[a].public_send(m)].flatten.compact - end - end - - posts.map do |p| - p.path.absolute if p.save(validate: false) - end.compact << post.path.absolute - end - # Si les usuaries modifican o crean una licencia, considerarla # personalizada en el panel. def update_site_license! @@ -159,4 +159,62 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do site.update licencia: Licencia.find_by_icons('custom') end end + + # @return [Array] + def associated_posts_to_save + @associated_posts_to_save ||= Set.new + end + + # Recolectar campos asociados que no estén vacíos + # + # @param [Post] + # @return [Array] + def association_attributes(post) + post.attributes.select do |attribute| + post[attribute].try(:inverse?) + end + end + + # @param :post_ids [Array] + # @return [Association] + def associated_posts(post_ids) + site.indexed_posts.where(post_id: post_ids).map(&:post) + end + + # Modificar las asociaciones. + # + # Si el valor actual es una String, es un BelongsTo + # + # + def update_associations_forward(post) + association_attributes(post).each do |attribute| + metadata = post[attribute] + + next unless metadata.changed? + + inverse_attribute = post[attribute].inverse + value_was = metadata.value_was.dup + value = metadata.value.dup + + case metadata.type + when 'has_and_belongs_to_many' + binding.pry + associated_posts(value_was - value).each do |remove_post| + remove_post[inverse_attribute].value.delete(post.uuid.value) + + associated_posts_to_save << remove_post + end + + associated_posts(value - value_was).each do |add_post| + add_post[inverse_attribute].value << post.uuid.value + add_post[inverse_attribute].value.uniq! + + associated_posts_to_save << add_post + end + when 'has_many' + when 'belongs_to' + when 'locales' + end + end + end end diff --git a/app/views/posts/attribute_ro/_belongs_to.haml b/app/views/posts/attribute_ro/_belongs_to.haml index c7e06be8..7410e921 100644 --- a/app/views/posts/attribute_ro/_belongs_to.haml +++ b/app/views/posts/attribute_ro/_belongs_to.haml @@ -1,6 +1,6 @@ %tr{ id: attribute } %th= post_label_t(attribute, post: post) %td{ dir: dir, lang: locale } - - p = metadata.belongs_to + - p = site.indexed_posts.find_by_post_id(metadata.value) - if p - = link_to p.title.value, site_post_path(site, p.id) + = link_to p.title, site_post_path(site, p.path) diff --git a/app/views/posts/attribute_ro/_has_and_belongs_to_many.haml b/app/views/posts/attribute_ro/_has_and_belongs_to_many.haml index d6b51a7a..29c0816f 100644 --- a/app/views/posts/attribute_ro/_has_and_belongs_to_many.haml +++ b/app/views/posts/attribute_ro/_has_and_belongs_to_many.haml @@ -2,5 +2,5 @@ %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) + - site.indexed_posts.where(post_id: metadata.value).find_each do |p| + %li= link_to p.title, site_post_path(site, p.path) diff --git a/app/views/posts/attribute_ro/_has_many.haml b/app/views/posts/attribute_ro/_has_many.haml index d6b51a7a..29c0816f 100644 --- a/app/views/posts/attribute_ro/_has_many.haml +++ b/app/views/posts/attribute_ro/_has_many.haml @@ -2,5 +2,5 @@ %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) + - site.indexed_posts.where(post_id: metadata.value).find_each do |p| + %li= link_to p.title, site_post_path(site, p.path) From ce299cc9d3906fbbe0c76e987b7f8a9279b1e927 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 12:24:41 -0300 Subject: [PATCH 43/65] feat: modificar relaciones en PostService (cherry picked from commit 3e88a98f5e9e1b31de8c058b7b5a41dfc4222f7c) --- app/services/post_service.rb | 47 ++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index dc04dda6..1d7e1a99 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -20,7 +20,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do added_paths << post.path.value # Recorrer todas las asociaciones y agregarse donde corresponda - update_associations_forward(post) + update_associations(post) associated_posts_to_save.each do |associated_post| next unless associated_post.save(validate: false) @@ -65,7 +65,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do added_paths << post.path.value # Recorrer todas las asociaciones y agregarse donde corresponda - update_associations_forward(post) + update_associations(post) associated_posts_to_save.each do |associated_post| next unless associated_post.save(validate: false) @@ -181,12 +181,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do site.indexed_posts.where(post_id: post_ids).map(&:post) end - # Modificar las asociaciones. - # - # Si el valor actual es una String, es un BelongsTo - # - # - def update_associations_forward(post) + # Modificar las asociaciones en cascada + def update_associations(post) association_attributes(post).each do |attribute| metadata = post[attribute] @@ -194,11 +190,10 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do inverse_attribute = post[attribute].inverse value_was = metadata.value_was.dup - value = metadata.value.dup + value = metadata.value.dup case metadata.type when 'has_and_belongs_to_many' - binding.pry associated_posts(value_was - value).each do |remove_post| remove_post[inverse_attribute].value.delete(post.uuid.value) @@ -212,7 +207,39 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do associated_posts_to_save << add_post end when 'has_many' + associated_posts(value_was - value).each do |remove_post| + # @todo por qué no podemos usar nil para deshabilitar un valor? + remove_post[inverse_attribute].value = '' + + associated_posts_to_save << remove_post + end + + associated_posts(value - value_was).each do |add_post| + associated_posts(add_post[inverse_attribute].value_was).each do |remove_post| + remove_post[attribute].value.delete(add_post.uuid.value) + + associated_posts_to_save << remove_post + end + + add_post[inverse_attribute].value = post.uuid.value + + associated_posts_to_save << add_post + end when 'belongs_to' + if value_was.present? + associated_posts(value_was).each do |remove_post| + remove_post[inverse_attribute].value.delete(value_was) + + associated_posts_to_save << remove_post + end + end + + associated_posts(value).each do |add_post| + add_post[inverse_attribute].value << post.uuid.value + add_post[inverse_attribute].value.uniq! + + associated_posts_to_save << add_post + end when 'locales' end end From fabcabc10057946d38f17297897d19d563a4ccd5 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:27:01 -0300 Subject: [PATCH 44/65] refactor: eliminar relaciones (cherry picked from commit b81e38e9ea830f1517f79f90ac99187a0ee9902e) --- app/services/post_service.rb | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 1d7e1a99..c82953e3 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -195,9 +195,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do case metadata.type when 'has_and_belongs_to_many' associated_posts(value_was - value).each do |remove_post| - remove_post[inverse_attribute].value.delete(post.uuid.value) - - associated_posts_to_save << remove_post + remove_relation_from(remove_post[inverse_attribute], post.uuid.value) end associated_posts(value - value_was).each do |add_post| @@ -208,17 +206,12 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end when 'has_many' associated_posts(value_was - value).each do |remove_post| - # @todo por qué no podemos usar nil para deshabilitar un valor? - remove_post[inverse_attribute].value = '' - - associated_posts_to_save << remove_post + remove_relation_from(remove_post[inverse_attribute], '') end associated_posts(value - value_was).each do |add_post| associated_posts(add_post[inverse_attribute].value_was).each do |remove_post| - remove_post[attribute].value.delete(add_post.uuid.value) - - associated_posts_to_save << remove_post + remove_relation_from(remove_post[attribute], add_post.uuid.value) end add_post[inverse_attribute].value = post.uuid.value @@ -228,9 +221,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do when 'belongs_to' if value_was.present? associated_posts(value_was).each do |remove_post| - remove_post[inverse_attribute].value.delete(value_was) - - associated_posts_to_save << remove_post + remove_relation_from(remove_post[inverse_attribute], value_was) end end @@ -244,4 +235,15 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end end end + + # @todo por qué no podemos usar nil para deshabilitar un valor? + def remove_relation_from(metadata, value) + case metadata.value + when Array then metadata.value.delete(value) + when String then metadata.value = '' + end + + associated_posts_to_save << metadata.post + nil + end end From 0eee4f17d34e510a9503752f37247cbb21eaf226 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:29:58 -0300 Subject: [PATCH 45/65] refactor: agregar relaciones (cherry picked from commit 66472d4b6f6f74197ad9e884dff3b716491cd33e) --- app/services/post_service.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index c82953e3..83d30a50 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -199,10 +199,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end associated_posts(value - value_was).each do |add_post| - add_post[inverse_attribute].value << post.uuid.value - add_post[inverse_attribute].value.uniq! - - associated_posts_to_save << add_post + add_relation_to(add_post[inverse_attribute], post.uuid.value) end when 'has_many' associated_posts(value_was - value).each do |remove_post| @@ -214,9 +211,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do remove_relation_from(remove_post[attribute], add_post.uuid.value) end - add_post[inverse_attribute].value = post.uuid.value - - associated_posts_to_save << add_post + add_relation_to(add_post[inverse_attribute], post.uuid.value) end when 'belongs_to' if value_was.present? @@ -226,10 +221,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end associated_posts(value).each do |add_post| - add_post[inverse_attribute].value << post.uuid.value - add_post[inverse_attribute].value.uniq! - - associated_posts_to_save << add_post + add_relation_to(add_post[inverse_attribute], post.uuid.value) end when 'locales' end @@ -246,4 +238,17 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do associated_posts_to_save << metadata.post nil end + + # @todo El validador ya debería eliminar valores duplicados + def add_relation_to(metadata, value) + case metadata.value + when Array + metadata.value << value + metadata.uniq! + when String then metadata.value = value + end + + associated_posts_to_save << metadata.post + nil + end end From 10610857b4f8a1fc42c3430d65bf0313e85ba64c Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:31:34 -0300 Subject: [PATCH 46/65] refactor: guardar las relaciones luego de actualizarlas (cherry picked from commit 67bb6e45df3f0540fb11576f68f41a627b1687ca) --- app/services/post_service.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 83d30a50..3e77896c 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -22,12 +22,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # Recorrer todas las asociaciones y agregarse donde corresponda update_associations(post) - associated_posts_to_save.each do |associated_post| - next unless associated_post.save(validate: false) - - added_paths << associated_post.path.value - end - commit(action: :created, add: added_paths) end @@ -67,12 +61,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # Recorrer todas las asociaciones y agregarse donde corresponda update_associations(post) - associated_posts_to_save.each do |associated_post| - next unless associated_post.save(validate: false) - - added_paths << associated_post.path.value - end - commit(action: :updated, add: added_paths, rm: rm) end @@ -226,6 +214,12 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do when 'locales' end end + + associated_posts_to_save.each do |associated_post| + next unless associated_post.save(validate: false) + + added_paths << associated_post.path.value + end end # @todo por qué no podemos usar nil para deshabilitar un valor? From 381467ecc06bae999ba21d3a28120f9b20141994 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:36:29 -0300 Subject: [PATCH 47/65] =?UTF-8?q?fix:=20la=20relaci=C3=B3n=20de=20traducci?= =?UTF-8?q?=C3=B3n=20es=20como=20habtm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 685845a558a5f9ba0ecbee9eee84cc63393cdc51) --- app/services/post_service.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 3e77896c..4b7c2d7d 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -181,7 +181,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do value = metadata.value.dup case metadata.type - when 'has_and_belongs_to_many' + when 'has_and_belongs_to_many', 'locales' associated_posts(value_was - value).each do |remove_post| remove_relation_from(remove_post[inverse_attribute], post.uuid.value) end @@ -211,7 +211,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do associated_posts(value).each do |add_post| add_relation_to(add_post[inverse_attribute], post.uuid.value) end - when 'locales' end end @@ -223,6 +222,9 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end # @todo por qué no podemos usar nil para deshabilitar un valor? + # @param :metadata [MetadataTemplate] + # @param :value [String] + # @return [nil] def remove_relation_from(metadata, value) case metadata.value when Array then metadata.value.delete(value) @@ -234,6 +236,9 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end # @todo El validador ya debería eliminar valores duplicados + # @param :metadata [MetadataTemplate] + # @param :value [String] + # @return [nil] def add_relation_to(metadata, value) case metadata.value when Array From 84d7b8f7c0eac7874c15e072d86e205e70ea85d3 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:41:33 -0300 Subject: [PATCH 48/65] docs: relaciones (cherry picked from commit 82fdf2518e7b3465e03fb4ba1a7074610aae70e7) --- app/services/post_service.rb | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 4b7c2d7d..da7673d0 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -169,7 +169,21 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do site.indexed_posts.where(post_id: post_ids).map(&:post) end - # Modificar las asociaciones en cascada + # Modificar las asociaciones en cascada, manteniendo reciprocidad + # y guardando los archivos correspondientes. + # + # HABTM, Locales: si se rompe de un lado se elimina en el otro y lo + # mismo si se agrega. + # + # HasMany: la relación es de uno a muchos. Al quitar uno, se elimina + # la relación inversa. Al agregar uno, se elimina su relación + # anterior en el tercer Post y se actualiza con la nueva. + # + # BelongsTo: la inversa de HasMany. Al cambiarla, se quita de la + # relación anterior y se agrega en la nueva. + # + # @param :post [Post] + # @return [nil] def update_associations(post) association_attributes(post).each do |attribute| metadata = post[attribute] @@ -219,6 +233,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do added_paths << associated_post.path.value end + + nil end # @todo por qué no podemos usar nil para deshabilitar un valor? From ed1fd9cdef67a2e9687d77d626a983e159cb1973 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:43:16 -0300 Subject: [PATCH 49/65] =?UTF-8?q?fix:=20mantener=20una=20lista=20=C3=BAnic?= =?UTF-8?q?a=20de=20archivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 0dc3a69a93c53eb8a59181503ddb12dca2e5a698) --- app/services/post_service.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index da7673d0..6c10b044 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -16,7 +16,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end if post.update(post_params) - added_paths = [] added_paths << post.path.value # Recorrer todas las asociaciones y agregarse donde corresponda @@ -55,7 +54,6 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do rm = [] rm << post.path.value_was if post.path.changed? - added_paths = [] added_paths << post.path.value # Recorrer todas las asociaciones y agregarse donde corresponda @@ -148,11 +146,16 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do end end - # @return [Array] + # @return [Set] def associated_posts_to_save @associated_posts_to_save ||= Set.new end + # @return [Set] + def added_paths + @added_paths ||= Set.new + end + # Recolectar campos asociados que no estén vacíos # # @param [Post] From d6e49bbd1e0d5ac82fbcc28f75ff44b31abc762a Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 16:46:23 -0300 Subject: [PATCH 50/65] fix: reordenar (cherry picked from commit f5f66bd95f86e5f85f4ef3fab5a7453c49c1f61f) --- app/services/post_service.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 6c10b044..91d8b8f6 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -67,6 +67,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do post end + # @todo Eliminar relaciones def destroy post.destroy! @@ -82,7 +83,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do # { uuid => 2, uuid => 1, uuid => 0 } def reorder reorder = params.require(:post).permit(reorder: {})&.dig(:reorder)&.transform_values(&:to_i) - posts = site.indexed_posts(locale: locale).where(post_id: reorder.keys).map(&:post) + posts = site.indexed_posts.where(locale: locale, post_id: reorder.keys).map(&:post) files = posts.map do |post| next unless post.attribute? :order @@ -98,8 +99,11 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do return if files.empty? # TODO: Implementar transacciones! - posts.save_all(validate: false) && - commit(action: :reorder, add: files) + posts.map do |post| + post.save(validate: false) + end + + commit(action: :reorder, add: files) end private From cd613b053df85bbcd3b7fad961b68d569166a6b4 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:05:58 -0300 Subject: [PATCH 51/65] fix: validar presencia de atributos (cherry picked from commit 2282acfc6e1b11f8ef23b3879d6c9c45ba6a1e7f) --- app/models/indexed_post.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 02679ec0..992c07c8 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -48,6 +48,8 @@ class IndexedPost < ApplicationRecord .flatten.uniq end + validates_presence_of :layout, :path, :locale + belongs_to :site # La ubicación del Post en el disco From 43ba7d78f0de49d569ca9187274c3667509cc1b2 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:06:43 -0300 Subject: [PATCH 52/65] =?UTF-8?q?fix:=20notificar=20la=20excepci=C3=B3n=20?= =?UTF-8?q?correctamente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 6e5195ca90490cf18fbf6457d4da70336aded108) --- app/models/post.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/post.rb b/app/models/post.rb index ab91bd43..84f18386 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -30,6 +30,10 @@ class Post # a demanda? def find_layout(path) File.foreach(path).lazy.grep(/^layout: /).take(1).first&.split(' ')&.last&.tr('\'', '')&.tr('"', '')&.to_sym + rescue Errno::ENOENT => e + ExceptionNotifier.notify_exception(e, data: { path: path }) + + :post end # Genera un Post nuevo From c07eb9773505279de9c6a90d36bc08263ef2d49b Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:07:03 -0300 Subject: [PATCH 53/65] fix: valor por defecto correcto (cherry picked from commit 9531a2004c8b8c1c83b44ea1110f31e9672fca2f) --- db/migrate/20210504224343_create_indexed_posts.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20210504224343_create_indexed_posts.rb b/db/migrate/20210504224343_create_indexed_posts.rb index 9cf21538..a88db1f3 100644 --- a/db/migrate/20210504224343_create_indexed_posts.rb +++ b/db/migrate/20210504224343_create_indexed_posts.rb @@ -27,7 +27,7 @@ class CreateIndexedPosts < ActiveRecord::Migration[6.1] # Queremos mostrar el título por separado t.string :title, default: '' # También vamos a mostrar las categorías - t.jsonb :front_matter, default: '{}' + t.jsonb :front_matter, default: {} t.string :content, default: '' t.tsvector :indexed_content From bbcfc701b4f7248e26d420f8abd6292e816bf112 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:08:14 -0300 Subject: [PATCH 54/65] feat: poder pasar la ruta a Post.build (cherry picked from commit b0c21f989e7b6cf77b41b732e0f08e88d676c4d8) --- app/models/post.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 84f18386..af2b48d4 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -38,19 +38,22 @@ class Post # Genera un Post nuevo # + # @todo Mergear en Post#initialize + # @params :path [String] # @params :site [Site] # @params :locale [String, Symbol] # @params :document [Jekyll::Document] # @params :layout [String,Symbol] # @return [Post] def build(**args) + args[:path] ||= '' args[:document] ||= begin site = args[:site] collection = site.collections[args[:locale].to_s] - Jekyll::Document.new('', site: site.jekyll, collection: collection).tap do |doc| - doc.data['date'] = Date.today.to_time + Jekyll::Document.new(args[:path], site: site.jekyll, collection: collection).tap do |doc| + doc.data['date'] ||= Date.today.to_time end end From dc83dfe00ab0d564d8c070b64730e52977fe1e41 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:08:44 -0300 Subject: [PATCH 55/65] =?UTF-8?q?feat:=20poder=20pasar=20el=20layout=20com?= =?UTF-8?q?o=20s=C3=ADmbolo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit e1d80e485369fbf031643f93f05a3410adba45b1) --- app/models/post.rb | 2 ++ app/models/site/index.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/post.rb b/app/models/post.rb index af2b48d4..5f6d5ff4 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -57,6 +57,8 @@ class Post end end + args[:layout] = args[:site].layouts[args[:layout]] if args[:layout].is_a? Symbol + Post.new(**args) end end diff --git a/app/models/site/index.rb b/app/models/site/index.rb index 2cb950cb..7a070e6d 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -20,7 +20,7 @@ class Site jekyll.documents.each do |doc| doc.read! - Post.new(document: doc, site: self, layout: layouts[doc['layout'].to_sym]).index! + Post.new(document: doc, site: self, layout: doc['layout'].to_sym).index! end update(last_indexed_commit: repository.head_commit.oid) From f5b1217a02f8e5b76a2a166aa547fcb825b0d84c Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:09:20 -0300 Subject: [PATCH 56/65] fix: indexar cambios sin leer todo el sitio (cherry picked from commit e34392e77c78d26a3fdb6afadbebdc9d72a77fca) --- app/models/site/index.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/site/index.rb b/app/models/site/index.rb index 7a070e6d..dc9f266f 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -104,9 +104,10 @@ class Site indexable_posts.select do |delta| MODIFIED_STATUSES.include? delta.status end.each do |delta| - locale, path = locale_and_path_from(delta.new_file[:path]) + locale, _ = locale_and_path_from(delta.new_file[:path]) + full_path = File.join(self.path, delta.new_file[:path]) - posts(lang: locale).find(path).index! + Post.build(path: full_path, site: self, layout: Post.find_layout(full_path), locale: locale).index! end end From 8c507752189474b57c43f6cb89d679904ca58961 Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:10:58 -0300 Subject: [PATCH 57/65] fix: obtener el post indexado a partir del post (cherry picked from commit 3b656f190852c9649cffa7cf86a50dedb592b7a2) --- app/models/post.rb | 5 ----- app/models/post/indexable.rb | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 5f6d5ff4..26611a41 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -63,11 +63,6 @@ class Post end end - # @return [IndexedPost,nil] - def indexed_post - site.indexed_posts.find_by(locale: lang.value, path: id) - end - # Redefinir el inicializador de OpenStruct # # @param :site [Site] el sitio en Sutty diff --git a/app/models/post/indexable.rb b/app/models/post/indexable.rb index 3aa8ce59..40be9b1c 100644 --- a/app/models/post/indexable.rb +++ b/app/models/post/indexable.rb @@ -10,6 +10,11 @@ class Post after_save :index! after_destroy :remove_from_index! + # @return [IndexedPost,nil] + def indexed_post + site.indexed_posts.find_by_post_id(uuid.value) + end + # Devuelve una versión indexable del Post # # @return [IndexedPost] From 0d781b6a157d6fe8c772c1f2440112312106793e Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:12:30 -0300 Subject: [PATCH 58/65] =?UTF-8?q?fix:=20garantizar=20que=20el=20sitio=20es?= =?UTF-8?q?t=C3=A1=20indexado=20antes=20de=20verlo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 39ea2d25fc34674d566f4a5de63be39adc24cc20) --- app/controllers/application_controller.rb | 4 +++- app/models/post/indexable.rb | 3 --- app/services/site_service.rb | 9 ++------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2746ab10..218e1e55 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -96,7 +96,9 @@ class ApplicationController < ActionController::Base end def site - @site ||= find_site + @site ||= find_site.tap do |s| + s.reindex_changes! + end end protected diff --git a/app/models/post/indexable.rb b/app/models/post/indexable.rb index 40be9b1c..38a98c2b 100644 --- a/app/models/post/indexable.rb +++ b/app/models/post/indexable.rb @@ -6,9 +6,6 @@ class Post extend ActiveSupport::Concern included do - # Indexa o reindexa el Post - after_save :index! - after_destroy :remove_from_index! # @return [IndexedPost,nil] def indexed_post diff --git a/app/services/site_service.rb b/app/services/site_service.rb index 34d5d43f..53165e1a 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -76,16 +76,11 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do commit_config(action: :tor) end - # Trae cambios desde la rama remota y reindexa los artículos. + # Trae cambios desde la rama remota # # @return [Boolean] def merge - result = site.repository.merge(usuarie) - - # TODO: Implementar callbacks - site.try(:index_posts!) if result - - result.present? + site.repository.merge(usuarie).present? end private From fca074bb0ec9cd78dfb02602ea94f77a79911c6b Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 18:17:42 -0300 Subject: [PATCH 59/65] fix: deprecar DeployReindex ya no es necesario porque estamos reindexando a demanda (cherry picked from commit a171aa24e3aa06f781a9b38c1db985239b73f39a) --- app/models/deploy_reindex.rb | 38 ------------------- ...20231026211607_deprecate_deploy_reindex.rb | 10 +++++ 2 files changed, 10 insertions(+), 38 deletions(-) delete mode 100644 app/models/deploy_reindex.rb create mode 100644 db/migrate/20231026211607_deprecate_deploy_reindex.rb diff --git a/app/models/deploy_reindex.rb b/app/models/deploy_reindex.rb deleted file mode 100644 index f3eb3d23..00000000 --- a/app/models/deploy_reindex.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -# Reindexa los artículos al terminar la compilación -class DeployReindex < Deploy - def deploy(**) - time_start - - site.reset - - Site.transaction do - site.indexed_posts.destroy_all - site.index_posts! - end - - time_stop - - build_stats.create action: 'reindex', - log: 'Reindex', - seconds: time_spent_in_seconds, - bytes: size, - status: true - site.touch - end - - def size - 0 - end - - def limit - 1 - end - - def hostname; end - - def url; end - - def destination; end -end diff --git a/db/migrate/20231026211607_deprecate_deploy_reindex.rb b/db/migrate/20231026211607_deprecate_deploy_reindex.rb new file mode 100644 index 00000000..945d01b4 --- /dev/null +++ b/db/migrate/20231026211607_deprecate_deploy_reindex.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Ya no es necesario reindexar por la fuerza +class DeprecateDeployReindex < ActiveRecord::Migration[6.1] + def up + Deploy.where(type: 'DeployReindex').destroy_all + end + + def down;end +end From f7628505b099189eb0cf47cfcac745d0dd55796f Mon Sep 17 00:00:00 2001 From: f Date: Fri, 27 Oct 2023 11:32:47 -0300 Subject: [PATCH 60/65] fix: no cambiar la fecha si vamos a leerla luego (cherry picked from commit ed786a7307533d8ec6184f00bf951c58a1bf09c4) --- app/models/post.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/post.rb b/app/models/post.rb index 26611a41..651c2624 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -53,7 +53,7 @@ class Post collection = site.collections[args[:locale].to_s] Jekyll::Document.new(args[:path], site: site.jekyll, collection: collection).tap do |doc| - doc.data['date'] ||= Date.today.to_time + doc.data['date'] = Date.today.to_time if args[:path].blank? end end From 3b3b79a22db9e3d82a9cdac7a100123016effd4f Mon Sep 17 00:00:00 2001 From: f Date: Fri, 27 Oct 2023 11:33:24 -0300 Subject: [PATCH 61/65] fix: usar Post.build (cherry picked from commit 3cf93b15b675bfe035faf47cfc234a9511f5a81c) --- app/models/site/index.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/site/index.rb b/app/models/site/index.rb index dc9f266f..213ef0bb 100644 --- a/app/models/site/index.rb +++ b/app/models/site/index.rb @@ -20,7 +20,7 @@ class Site jekyll.documents.each do |doc| doc.read! - Post.new(document: doc, site: self, layout: doc['layout'].to_sym).index! + Post.build(document: doc, site: self, layout: doc['layout'].to_sym).index! end update(last_indexed_commit: repository.head_commit.oid) From eda06ae26fc1f505db688f1498984b7099a752ad Mon Sep 17 00:00:00 2001 From: f Date: Thu, 26 Oct 2023 19:07:11 -0300 Subject: [PATCH 62/65] fix: has_one es como belongs_to (cherry picked from commit 74ae4ef4abc0cf18f4b0cdba65c4a3900545c092) --- app/models/metadata_has_one.rb | 28 +--------------------------- app/services/post_service.rb | 2 +- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/app/models/metadata_has_one.rb b/app/models/metadata_has_one.rb index d1705e7d..0cadb1d9 100644 --- a/app/models/metadata_has_one.rb +++ b/app/models/metadata_has_one.rb @@ -1,29 +1,3 @@ # frozen_string_literal: true -class MetadataHasOne < MetadataBelongsTo - alias has_one belongs_to - alias had_one belonged_to - - def save - # XXX: DRY - if !changed? - self[:value] = document_value - - return true - end - - self[:value] = sanitize value - - return true unless changed? - return true unless inverse? - - had_one[inverse]&.value = '' if had_one - has_one[inverse]&.value = post.uuid.value if has_one - - true - end - - def related_methods - @related_methods ||= %i[has_one had_one].freeze - end -end +class MetadataHasOne < MetadataBelongsTo; end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 91d8b8f6..23b54d11 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -222,7 +222,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do add_relation_to(add_post[inverse_attribute], post.uuid.value) end - when 'belongs_to' + when 'belongs_to', 'has_one' if value_was.present? associated_posts(value_was).each do |remove_post| remove_relation_from(remove_post[inverse_attribute], value_was) From f94b579a25aca8936a75a07dc16d9e8a06531b8b Mon Sep 17 00:00:00 2001 From: f Date: Fri, 27 Oct 2023 14:06:19 -0300 Subject: [PATCH 63/65] fixup! fix: has_one es como belongs_to (cherry picked from commit 7a0443d7cc0e5ee65b18bd504ab66434bbd231ef) --- app/views/posts/attribute_ro/_has_one.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/posts/attribute_ro/_has_one.haml b/app/views/posts/attribute_ro/_has_one.haml index 425e659e..fafccd34 100644 --- a/app/views/posts/attribute_ro/_has_one.haml +++ b/app/views/posts/attribute_ro/_has_one.haml @@ -1,6 +1,6 @@ %tr{ id: attribute } %th= post_label_t(attribute, post: post) %td{ dir: dir, lang: locale } - - p = metadata.has_one + - p = site.indexed_posts.find_by_post_id(metadata.value) - if p - = link_to p.title.value, site_post_path(site, p.id) + = link_to p.title, site_post_path(site, p.post_id) From 04415b5dd6ddefb967d0cad031de240e463bb2fe Mon Sep 17 00:00:00 2001 From: f Date: Wed, 15 Nov 2023 12:31:20 -0300 Subject: [PATCH 64/65] fix: aplicar uniq al valor #14644 --- app/services/post_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 23b54d11..ff2ac6bd 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -266,7 +266,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do case metadata.value when Array metadata.value << value - metadata.uniq! + metadata.value.uniq! when String then metadata.value = value end From 35a838afd2c12efbf1f9dc226d1e1045b630d64b Mon Sep 17 00:00:00 2001 From: f Date: Mon, 25 Mar 2024 12:14:16 -0300 Subject: [PATCH 65/65] =?UTF-8?q?fix:=20romper=20la=20relaci=C3=B3n=20has?= =?UTF-8?q?=5Fmany=20desde=20un=20belongs=5Fto=20#7537?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/post_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/post_service.rb b/app/services/post_service.rb index ff2ac6bd..6f42bb22 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -225,7 +225,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do when 'belongs_to', 'has_one' if value_was.present? associated_posts(value_was).each do |remove_post| - remove_relation_from(remove_post[inverse_attribute], value_was) + remove_relation_from(remove_post[inverse_attribute], post.uuid.value) end end