actualizar y eliminar artículos

This commit is contained in:
f 2019-08-16 20:12:22 -03:00
parent 1c96e0b0ff
commit da77ecf43f
No known key found for this signature in database
GPG key ID: 2AE5A13E321F953D
11 changed files with 107 additions and 69 deletions

View file

@ -58,29 +58,17 @@ class PostsController < ApplicationController
def update def update
@site = find_site @site = find_site
@lang = find_lang(@site) @post = @site.posts.find params[:id]
@post = find_post(@site)
authorize @post authorize @post
@post.update_attributes(repair_nested_params(post_params)) service = PostService.new(site: @site,
post: @post,
usuarie: current_usuarie,
params: params)
# Solo las usuarias pueden modificar la autoría if service.update.persisted?
if @site.usuarie? current_usuarie redirect_to site_posts_path(@site)
if params[:post][:author].present?
@post.update_attributes(author: params[:post][:author])
end
@post.update_attributes(draft: false)
else
# Todo lo que crean les invitades es borrador
@post.update_attributes(draft: true)
end
if @post.save
flash[:success] = @site.config.dig('thanks')
redirect_to site_posts_path(@site,
category: session[:category],
lang: @lang)
else else
render 'posts/edit' render 'posts/edit'
end end
@ -89,14 +77,17 @@ class PostsController < ApplicationController
# Eliminar artículos # Eliminar artículos
def destroy def destroy
@site = find_site @site = find_site
@lang = find_lang(@site) @post = @site.posts.find params[:id]
@post = find_post(@site)
authorize @post authorize @post
@post.destroy service = PostService.new(site: @site,
post: @post,
usuarie: current_usuarie,
params: params)
redirect_to site_posts_path(@site, category: session[:category], # TODO: Notificar si se pudo o no
lang: @lang) service.destroy
redirect_to site_posts_path(@site)
end end
end end

View file

@ -136,16 +136,13 @@ class Post < OpenStruct
# Eliminar el artículo del repositorio y de la lista de artículos del # Eliminar el artículo del repositorio y de la lista de artículos del
# sitio # sitio
#
# XXX Commit
def destroy def destroy
FileUtils.rm_f path.absolute FileUtils.rm_f path.absolute
site.posts(lang: lang).delete_if do |post| # TODO: Devolver self en lugar de todo el array
site.posts(lang: lang).reject! do |post|
post.path.absolute == path.absolute post.path.absolute == path.absolute
end end
!File.exist?(path.absolute) && !site.posts(lang: lang).include?(self)
end end
alias destroy! destroy alias destroy! destroy
@ -212,6 +209,10 @@ class Post < OpenStruct
File.exist?(path.absolute) && full_content == File.read(path.absolute) File.exist?(path.absolute) && full_content == File.read(path.absolute)
end end
def destroyed?
!File.exist?(path.absolute)
end
def update_attributes(hashable) def update_attributes(hashable)
hashable.to_hash.each do |name, value| hashable.to_hash.each do |name, value|
self[name].value = value self[name].value = value

View file

@ -143,7 +143,7 @@ class Site < ApplicationRecord
@posts ||= {} @posts ||= {}
lang ||= I18n.locale lang ||= I18n.locale
return @posts[lang] if @posts[lang].present? return @posts[lang] if @posts.key? lang
@posts[lang] = PostRelation.new site: self @posts[lang] = PostRelation.new site: self

View file

@ -33,12 +33,8 @@ class Site
# Incorpora los cambios en el repositorio actual # Incorpora los cambios en el repositorio actual
# #
# rubocop:disable Metrics/AbcSize def merge(usuarie)
# rubocop:disable Metrics/MethodLength merge = rugged.merge_commits(master, origin_master)
def merge(author)
master = rugged.branches['master'].target
origin = rugged.branches['origin/master'].target
merge = rugged.merge_commits(master, origin)
# No hacemos nada si hay conflictos # No hacemos nada si hay conflictos
# #
@ -47,23 +43,26 @@ class Site
# quién sabe. # quién sabe.
return if merge.conflicts? return if merge.conflicts?
author = { name: author.name, email: author.email }
commit = Rugged::Commit commit = Rugged::Commit
.create(rugged, .create(rugged, update_ref: 'HEAD',
parents: [master, origin], parents: [master, origin_master],
tree: merge.write_tree(rugged), tree: merge.write_tree(rugged),
message: I18n.t('sites.fetch.merge.message'), message: I18n.t('sites.fetch.merge.message'),
author: author, author: author(usuarie), committer: committer)
committer: author,
update_ref: 'HEAD')
# Forzamos el checkout para mover el HEAD al último commit y # Forzamos el checkout para mover el HEAD al último commit y
# escribir los cambios # escribir los cambios
rugged.checkout 'HEAD', strategy: :force rugged.checkout 'HEAD', strategy: :force
commit commit
end end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength def master
rugged.branches['master'].target
end
def origin_master
rugged.branches['origin/master'].target
end
# Compara los commits entre el repositorio remoto y el actual para # Compara los commits entre el repositorio remoto y el actual para
# que luego los podamos mostrar. # que luego los podamos mostrar.
@ -86,20 +85,18 @@ class Site
end end
# Guarda los cambios en git, de a un archivo por vez # Guarda los cambios en git, de a un archivo por vez
# rubocop:disable Metrics/AbcSize def commit(file:, usuarie:, message:, remove: false)
def commit(file:, usuarie:, message:) remove ? rm(file) : add(file)
rugged.index.add(relativize(file))
# Escribir los cambios para que el repositorio se vea tal cual
rugged.index.write rugged.index.write
Rugged::Commit.create(rugged, Rugged::Commit.create(rugged, message: message, update_ref: 'HEAD',
update_ref: 'HEAD', parents: [rugged.head.target],
parents: [rugged.head.target], tree: rugged.index.write_tree,
tree: rugged.index.write_tree, author: author(usuarie),
message: message, committer: committer)
author: author(usuarie),
committer: committer)
end end
# rubocop:enable Metrics/AbcSize
def author(author) def author(author)
{ name: author.name, email: author.email, time: Time.now } { name: author.name, email: author.email, time: Time.now }
@ -109,6 +106,14 @@ class Site
{ name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now } { name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now }
end end
def add(file)
rugged.index.add(relativize(file))
end
def rm(file)
rugged.index.remove(relativize(file))
end
private private
def relativize(file) def relativize(file)

View file

@ -30,11 +30,18 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
post post
end end
def destroy
post.destroy! && commit(action: :destroyed)
post
end
private private
def commit(action:) def commit(action:)
site.repository.commit(file: post.path.absolute, site.repository.commit(file: post.path.absolute,
usuarie: usuarie, usuarie: usuarie,
remove: action == :destroyed,
message: I18n.t("post_service.#{action}", message: I18n.t("post_service.#{action}",
title: post.title.value)) title: post.title.value))
end end

View file

@ -13,7 +13,7 @@
url = site_posts_path(site) url = site_posts_path(site)
method = :post method = :post
else else
url = site_post_path(site, post) url = site_post_path(site, post.id)
method = :patch method = :patch
end end
@ -29,7 +29,7 @@
- type = metadata.type - type = metadata.type
= render "posts/attributes/#{type}", = render "posts/attributes/#{type}",
post: post, attribute: attribute, post: post, attribute: attribute,
metadata: metadata metadata: metadata, site: site
-# Botones de guardado -# Botones de guardado
= render 'posts/submit', site: site = render 'posts/submit', site: site

View file

@ -1,13 +1,12 @@
.row .row
.col .col
= render 'layouts/breadcrumb', = render 'layouts/breadcrumb',
crumbs: [ link_to(t('sites.index'), sites_path), crumbs: [link_to(t('sites.index'), sites_path),
@site.name, link_to(@site.name, site_posts_path(@site)),
link_to(t('posts.index'), link_to(t('posts.index'), site_posts_path(@site)),
site_posts_path(@site)), link_to(@post.title.value, site_post_path(@site, @post.id)),
link_to(@post.title, site_post_path(@site, @post)), t('posts.edit')]
t('posts.edit')]
.row.justify-content-center .row.justify-content-center
.col-md-8 .col-md-8
= render 'posts/form' = render 'posts/form', site: @site, post: @post

View file

@ -6,6 +6,7 @@ en:
post_service: post_service:
created: 'Created "%{title}"' created: 'Created "%{title}"'
updated: 'Updated "%{title}"' updated: 'Updated "%{title}"'
destroyed: 'Removed "%{title}"'
metadata: metadata:
array: array:
cant_be_empty: 'This field cannot be empty' cant_be_empty: 'This field cannot be empty'

View file

@ -6,6 +6,7 @@ es:
post_service: post_service:
created: 'Creado "%{title}"' created: 'Creado "%{title}"'
updated: 'Modificado "%{title}"' updated: 'Modificado "%{title}"'
destroyed: 'Eliminado "%{title}"'
metadata: metadata:
array: array:
cant_be_empty: 'El campo no puede estar vacío' cant_be_empty: 'El campo no puede estar vacío'

View file

@ -93,13 +93,12 @@ Al instanciar un `Post`, se pasan el sitio y la plantilla por defecto.
## TODO ## TODO
* Reimplementar draft e incomplete (por qué eran distintos?)
* Reimplementar subida de imagenes/archivos
* Leer artículos a medida que se los necesita en lugar de todos juntos. * Leer artículos a medida que se los necesita en lugar de todos juntos.
* Reimplementar glosario (se crea un artículo por cada categoría * Reimplementar glosario (se crea un artículo por cada categoría
utilizada) utilizada)
* Reimplementar orden de artículos (ver doc) * Reimplementar orden de artículos (ver doc)
* Reimplementar subida de imagenes/archivos
* Reimplementar campo 'pre' y 'post' en los layouts.yml * Reimplementar campo 'pre' y 'post' en los layouts.yml
* Implementar autoría como un array
* Reimplementar draft e incomplete (por qué eran distintos?)
* Convertir idiomas disponibles a pestañas? * Convertir idiomas disponibles a pestañas?
* Implementar traducciones sin adivinar. Vincular artículos entre sí * Implementar traducciones sin adivinar. Vincular artículos entre sí

View file

@ -58,4 +58,38 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
assert_equal 200, response.status assert_equal 200, response.status
assert_match @post.title.value, response.body assert_match @post.title.value, response.body
end end
test 'se pueden actualizar' do
title = SecureRandom.hex
patch site_post_url(@site, @post.id), headers: @authorization,
params: { post: { title: title } }
assert_equal 302, response.status
get site_posts_url(@site), headers: @authorization
assert_match title, response.body
site = Site.find @site.id
assert site.posts.map { |p| p.title.value }.include?(title)
end
test 'se pueden eliminar' do
params = ActionController::Parameters.new(post: { author: ['hola'] })
assert PostService.new(site: @site,
usuarie: @usuarie,
post: @post,
params: params).update
delete site_post_url(@site, @post.id), headers: @authorization
get site_posts_url(@site), headers: @authorization
site = Site.find @site.id
assert_not site.posts.include?(@post)
assert @post.destroyed?
assert_equal I18n.t('post_service.destroyed', title: @post.title.value),
@site.repository.rugged.head.target.message
end
end end