diff --git a/app/models/post.rb b/app/models/post.rb index cab7665f..de647758 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -29,7 +29,11 @@ class Post # TODO: Reemplazar cuando leamos el contenido del Document # a demanda? def find_layout(path) - IO.foreach(path).lazy.grep(/^layout: /).take(1).first&.split(' ')&.last&.tr('\'', '')&.tr('"', '')&.to_sym + IO.foreach(path).lazy.grep(/^layout: /).take(1).first&.split(' ')&.last&.tr('\'', '')&.tr('"', '')&.to_sym || :post + rescue Errno::ENOENT => e + ExceptionNotifier.notify(e) + + :post end end @@ -113,7 +117,7 @@ class Post # Devuelve una llave para poder guardar el post en una cache def cache_key - 'posts/' + uuid.value + "posts/#{uuid.value}" end def cache_version @@ -123,7 +127,7 @@ class Post # Agregar el timestamp para saber si cambió, siguiendo el módulo # ActiveRecord::Integration def cache_key_with_version - cache_key + '-' + cache_version + "#{cache_key}-#{cache_version}" end # TODO: Convertir a UUID? diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 90d65670..9852e128 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -92,40 +92,46 @@ -# TODO: Solo les usuaries cachean porque tenemos que separar les botones por permisos. - - cache_if @usuarie, [post, I18n.locale] do - - checkbox_id = "checkbox-#{post.id}" - %tr{ id: post.id, data: { target: 'reorder.row' } } - %td - .custom-control.custom-checkbox - %input.custom-control-input{ id: checkbox_id, type: 'checkbox', autocomplete: 'off', data: { action: 'reorder#select' } } - %label.custom-control-label{ for: checkbox_id } - %span.sr-only= t('posts.reorder.select') - -# Orden más alto es mayor prioridad - = hidden_field 'post[reorder]', post.id, - value: size - i, - data: { reorder: true } - %td.w-100{ class: dir } - = link_to site_post_path(@site, post.path) do - %span{ lang: post.locale, dir: dir }= post.title - - if post.front_matter['draft'].present? - %span.badge.badge-primary= I18n.t('posts.attributes.draft.label') - %br - %small - = link_to @site.layouts[post.layout].humanized_name, site_posts_path(@site, **@filter_params.merge(layout: post.layout)) - - post.front_matter['categories']&.each do |category| - = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do - %span{ lang: post.locale, dir: dir }= category - = '/' unless post.front_matter['categories'].last == category + - begin + - cache_if @usuarie, [post, I18n.locale] do + - checkbox_id = "checkbox-#{post.id}" + %tr{ id: post.id, data: { target: 'reorder.row' } } + %td + .custom-control.custom-checkbox + %input.custom-control-input{ id: checkbox_id, type: 'checkbox', autocomplete: 'off', data: { action: 'reorder#select' } } + %label.custom-control-label{ for: checkbox_id } + %span.sr-only= t('posts.reorder.select') + -# Orden más alto es mayor prioridad + = hidden_field 'post[reorder]', post.id, + value: size - i, + data: { reorder: true } + %td.w-100{ class: dir } + = link_to site_post_path(@site, post.path) do + %span{ lang: post.locale, dir: dir }= post.title + - if post.front_matter['draft'].present? + %span.badge.badge-primary= I18n.t('posts.attributes.draft.label') + %br + %small + = link_to @site.layouts[post.layout].humanized_name, site_posts_path(@site, **@filter_params.merge(layout: post.layout)) + - post.front_matter['categories']&.each do |category| + = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do + %span{ lang: post.locale, dir: dir }= category + = '/' unless post.front_matter['categories'].last == category - %td.text-nowrap - = post.created_at.strftime('%F') - %br/ - = post.order - %td.text-nowrap - - if @usuarie || policy(post).edit? - = link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-block' - - if @usuarie || policy(post).destroy? - = link_to t('posts.destroy'), site_post_path(@site, post.path), class: 'btn btn-block', method: :delete, data: { confirm: t('posts.confirm_destroy') } + %td.text-nowrap + = post.created_at.strftime('%F') + %br/ + = post.order + %td.text-nowrap + - if @usuarie || policy(post).edit? + = link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-block' + - if @usuarie || policy(post).destroy? + = link_to t('posts.destroy'), site_post_path(@site, post.path), class: 'btn btn-block', method: :delete, data: { confirm: t('posts.confirm_destroy') } + -# + Rescatar cualquier error en un post, notificarlo e + ignorar su renderización. + - rescue ActionView::Template::Error => e + - ExceptionNotifier.notify_exception(e.cause, data: { site: @site.name, post: @post.path.absolute, usuarie: current_usuarie.id }) #footnotes{ hidden: true } - @filter_params.each do |param, value| diff --git a/config/environments/test.rb b/config/environments/test.rb index 05506587..bf72d234 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -50,6 +50,15 @@ Rails.application.configure do config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } + config.middleware.use ExceptionNotification::Rack, + error_grouping: true, + email: { + email_prefix: '', + sender_address: ENV['DEFAULT_FROM'], + exception_recipients: ENV['EXCEPTION_TO'], + normalize_subject: true + } + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr diff --git a/test/controllers/posts_controller_test.rb b/test/controllers/posts_controller_test.rb index b8c9f560..3349f09b 100644 --- a/test/controllers/posts_controller_test.rb +++ b/test/controllers/posts_controller_test.rb @@ -150,7 +150,7 @@ class PostsControllerTest < ActionDispatch::IntegrationTest end posts = @site.posts(**lang) - reorder = Hash[posts.map { |p| p.uuid.value }.shuffle.each_with_index.to_a] + reorder = posts.map { |p| p.uuid.value }.shuffle.each_with_index.to_a.to_h post site_posts_reorder_url(@site), headers: @authorization, @@ -159,10 +159,18 @@ class PostsControllerTest < ActionDispatch::IntegrationTest @site = Site.find @site.id assert_equal reorder, - Hash[@site.posts(**lang).map do |p| + @site.posts(**lang).map do |p| [p.uuid.value, p.order.value] - end] + end.to_h assert_equal I18n.t('post_service.reorder'), @site.repository.rugged.head.target.message end + + test 'si hay algún error se recupera' do + File.open(File.join(@site.path, '_es', "#{Date.today}-#{SecureRandom.hex}.markdown"), 'w') do |f| + f.write '' + end + + get site_posts_url(@site), headers: @authorization + end end