From c2a4965fed20aa72e81aa56fbee4867a90bc934e Mon Sep 17 00:00:00 2001 From: f Date: Fri, 25 Sep 2020 14:07:54 -0300 Subject: [PATCH] =?UTF-8?q?mejoras=20en=20filtros=20y=20relaciones=20de=20?= =?UTF-8?q?posts=20y=20categor=C3=ADas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/application_controller.rb | 4 ++++ app/controllers/posts_controller.rb | 17 ++++++++++++++--- app/models/post_relation.rb | 9 +++++++-- app/policies/post_policy.rb | 16 ++++------------ app/views/posts/attribute_ro/_belongs_to.haml | 3 ++- .../attribute_ro/_has_and_belongs_to_many.haml | 2 +- app/views/posts/index.haml | 17 ++++------------- 7 files changed, 36 insertions(+), 32 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a5df344b..1640cfd1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -26,6 +26,10 @@ class ApplicationController < ActionController::Base private + def uuid?(string) + /[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/ =~ string + end + # Encontrar un sitio por su nombre def find_site id = params[:site_id] || params[:id] diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 03b8b20a..395a85d1 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -17,17 +17,28 @@ class PostsController < ApplicationController @site = find_site @category = params.dig(:category) - @layout = params.dig(:layout).try(:to_sym) + @layout = params.dig(:layout) @locale = locale # XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es # más simple saber si hubo cambios. if @category || @layout || stale?(@site) - # TODO: Aplicar policy_scope @posts = @site.posts(lang: locale) + @posts = @posts.where(categories: @category) if @category + @posts = @posts.where(layout: @layout) if @layout + @posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve + + @category_name = if uuid?(@category) + @site.posts(lang: locale).find(@category, uuid: true)&.title&.value + else + @category + end + + # Filtrar los posts que les invitades no pueden ver + @usuarie = @site.usuarie? current_usuarie + # Orden descendiente por número y luego por fecha @posts.sort_by!(:order, :date).reverse! - @usuarie = @site.usuarie? current_usuarie end end diff --git a/app/models/post_relation.rb b/app/models/post_relation.rb index 0546cd77..40108fc0 100644 --- a/app/models/post_relation.rb +++ b/app/models/post_relation.rb @@ -84,6 +84,8 @@ class PostRelation < Array # 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] @@ -91,7 +93,7 @@ class PostRelation < Array return self if args.empty? PostRelation[*select do |post| - args.map do |attr, value| + result = args.map do |attr, value| next unless post.attribute?(attr) attribute = post.public_send(attr) @@ -106,7 +108,10 @@ class PostRelation < Array else attribute.value == value end end - end.compact.all? + end.compact + + # Un Array vacío devuelve true para all? + !result.empty? && result.all? end] end diff --git a/app/policies/post_policy.rb b/app/policies/post_policy.rb index 5a9f29ff..e249d9f4 100644 --- a/app/policies/post_policy.rb +++ b/app/policies/post_policy.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true # Política de acceso a artículos -# -# TODO: Implementar Invitadx class PostPolicy attr_reader :post, :usuarie @@ -54,18 +52,12 @@ class PostPolicy @scope = scope end - # Las usuarias pueden ver todos los posts - # - # Les invitades solo pueden ver sus propios posts - # - # TODO: Arreglar def resolve - return scope if scope.try(:first).try(:site).try(:usuarie?, usuarie) + return scope if scope&.first&.site&.usuarie? usuarie - # Asegurarse que al menos devolvemos [] - [scope.find do |post| - post.author.value == usuarie.email - end].flatten.compact + scope.select do |post| + post.usuaries.include? usuarie + 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 2f7ee462..c7e06be8 100644 --- a/app/views/posts/attribute_ro/_belongs_to.haml +++ b/app/views/posts/attribute_ro/_belongs_to.haml @@ -2,4 +2,5 @@ %th= post_label_t(attribute, post: post) %td{ dir: dir, lang: locale } - p = metadata.belongs_to - = link_to p.title.value, site_post_path(site, p.id) + - if p + = link_to p.title.value, site_post_path(site, p.id) 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..d7186718 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| + - metadata.belongs_to.each do |p| %li= link_to p.title.value, site_post_path(site, p.id) diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index a77705ac..d9327e02 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -3,7 +3,7 @@ @site.name, link_to(t('posts.index'), site_posts_path(@site)), - @category] + @category_name] %main.row %aside.menu.col-md-3 @@ -53,15 +53,6 @@ %tbody - dir = t("locales.#{@locale}.dir") - @posts.each_with_index do |post, i| - -# - saltearse el post a menos que esté en la categoría por - la que estamos filtrando - - if @category - - next unless post.attributes.include? :categories - - next unless post.categories.value.include?(@category) - - if @layout - - next unless post.layout.name == @layout - - next unless @usuarie || policy(post).show? -# TODO: Solo les usuaries cachean porque tenemos que separar les botones por permisos. @@ -88,9 +79,9 @@ - unless post.categories.value.empty? %br %small - - post.categories.value.each do |c| - = link_to site_posts_path(@site, category: c) do - %span{ lang: post.lang.value, dir: dir }= c + - (post.categories.respond_to?(:belongs_to) ? post.categories.belongs_to : post.categories.value).each do |c| + = link_to site_posts_path(@site, category: (c.respond_to?(:uuid) ? c.uuid.value : c)) do + %span{ lang: post.lang.value, dir: dir }= (c.respond_to?(:title) ? c.title.value : c) %td = post.date.value.strftime('%F')