diff --git a/app/models/layout.rb b/app/models/layout.rb index 43892be..02f1645 100644 --- a/app/models/layout.rb +++ b/app/models/layout.rb @@ -1,4 +1,8 @@ # frozen_string_literal: true # Una plantilla agrupa metadatos que va a tener un artículo -Layout = Struct.new(:site, :name, :metadata, keyword_init: true) +Layout = Struct.new(:site, :name, :metadata, keyword_init: true) do + def value + name.to_s + end +end diff --git a/app/models/metadata_related_posts.rb b/app/models/metadata_related_posts.rb index 0ebc8a0..a0c5fba 100644 --- a/app/models/metadata_related_posts.rb +++ b/app/models/metadata_related_posts.rb @@ -5,13 +5,18 @@ class MetadataRelatedPosts < MetadataArray # Genera un Hash de { title | slug => uuid } def values - @values ||= site.posts(lang: lang).map do |p| + @values ||= posts.map do |p| { title(p) => p.uuid.value } end.inject(:merge) end private + # Obtiene todos los posts y opcionalmente los filtra + def posts + @posts ||= site.posts(lang: lang).where(**filter) + end + def title(post) post.try(:title).try(:value) || post.try(:slug).try(:value) end @@ -20,4 +25,9 @@ class MetadataRelatedPosts < MetadataArray def lang post.try(:lang).try(:value) || I18n.locale end + + # Encuentra el filtro + def filter + layout.metadata.dig(name, 'filter')&.to_h&.symbolize_keys || {} + end end diff --git a/app/models/post_relation.rb b/app/models/post_relation.rb index 336c8bd..efc970b 100644 --- a/app/models/post_relation.rb +++ b/app/models/post_relation.rb @@ -69,17 +69,34 @@ class PostRelation < Array end end - # Encuentra el primer post por el valor de un atributo - # XXX: Acepta cualquier atributo + # Encuentra el primer post por el valor de los atributos + # + # @param [Hash] + # @return [Post] def find_by(**args) - attr = args.first.first - - find_generic do |p| - p.attribute?(attr) && - p.public_send(attr).value == args.first.last + 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 + # + # @param [Hash] + # @return [PostRelation] + def where(**args) + return self if args.empty? + + PostRelation[*select do |post| + args.map do |attr, value| + post.attribute?(attr) && + post.public_send(attr).value == value + end.all? + end] + end + # Intenta guardar todos y devuelve true si pudo def save_all(validate: true) map do |post|