Modificar Site con un servicio

This commit is contained in:
f 2019-08-09 16:49:25 -03:00
parent 603d0cfea7
commit f65a7f5fe2
No known key found for this signature in database
GPG key ID: 2AE5A13E321F953D
10 changed files with 133 additions and 29 deletions

View file

@ -42,6 +42,7 @@ Metrics/BlockLength:
- 'config/initializers/devise.rb'
- 'db/schema.rb'
- 'config/routes.rb'
- 'test/controllers/sites_controller_test.rb'
Metrics/ClassLength:
Exclude:
@ -49,6 +50,7 @@ Metrics/ClassLength:
- 'app/controllers/posts_controller.rb'
- 'app/controllers/sites_controller.rb'
- 'test/models/post_test.rb'
- 'test/controllers/sites_controller_test.rb'
Lint/HandleExceptions:
Exclude:

View file

@ -29,15 +29,10 @@ class SitesController < ApplicationController
end
def create
@site = Site.new(site_params)
@site.roles << Rol.new(site: @site,
usuarie: current_usuarie,
temporal: false,
rol: 'usuarie')
service = SiteService.new(usuarie: current_usuarie,
params: site_params)
# XXX: Necesitamos escribir la configuración después porque queremos
# registrar quién hizo los cambios en el repositorio
if @site.save && @site.config.write(current_usuarie)
if (@site = service.create).persisted?
redirect_to site_path(@site)
else
render 'new'
@ -53,9 +48,10 @@ class SitesController < ApplicationController
@site = find_site
authorize @site
# XXX: Necesitamos escribir la configuración después porque queremos
# registrar quién hizo los cambios en el repositorio
if @site.update(site_params) && @site.config.write(current_usuarie)
service = SiteService.new(site: @site, params: site_params,
usuarie: current_usuarie)
if service.update
redirect_to sites_path
else
render 'edit'
@ -64,8 +60,9 @@ class SitesController < ApplicationController
# Envía un archivo del directorio público de Jekyll
def send_public_file
authorize Site
@site = find_site
authorize @site
file = [params[:basename], params[:format]].join('.')
path = File.join(@site.path, 'public', params[:type], file)
path = Pathname.new path

View file

@ -316,9 +316,9 @@ class Site < ApplicationRecord
# TODO: Guardar la configuración también, quizás aprovechando algún
# método de ActiveRecord para que lance un salvado recursivo.
def sync_attributes_with_config!
config.theme = design.gem unless design_id_changed?
config.description = description unless description_changed?
config.title = title unless title_changed?
config.theme = design.gem
config.description = description
config.title = title
end
# Valida si el sitio tiene al menos una forma de alojamiento asociada

View file

@ -8,6 +8,8 @@ class Site
# Iniciar el OpenStruct con el sitio
super(site: site)
self.saved = File.exist? path
read
end
@ -28,21 +30,19 @@ class Site
end
# Escribe los cambios en el repositorio
def write(usuarie = nil)
def write
return if persisted?
I18n.with_locale(usuarie.try(:lang) || I18n.default_locale) do
Site::Writer.new(site: site, file: path,
content: content.to_yaml, usuarie: usuarie,
message: I18n.t('sites.repository.config')).save
end
self.saved = Site::Writer.new(site: site, file: path,
content: content.to_yaml).save
# Actualizar el hash para no escribir dos veces
@hash = content.hash
end
alias save write
# Detecta si la configuración cambió comparando con el valor inicial
def persisted?
@hash == content.hash
(@hash == content.hash) && saved
end
# Obtener el contenido de la configuración como un hash, sin el

View file

@ -6,9 +6,10 @@ class Site
# que un sitio tiene un solo origen, que siempre se trabaja con la
# rama master, etc.
class Repository
attr_reader :rugged, :changes
attr_reader :rugged, :changes, :path
def initialize(path)
@path = path
@rugged = Rugged::Repository.new(path)
@changes = 0
end
@ -87,7 +88,7 @@ class Site
# Guarda los cambios en git, de a un archivo por vez
# rubocop:disable Metrics/AbcSize
def commit(file:, usuarie:, message:)
rugged.index.add(file)
rugged.index.add(relativize(file))
rugged.index.write
Rugged::Commit.create(rugged,
@ -107,5 +108,11 @@ class Site
def committer
{ name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now }
end
private
def relativize(file)
Pathname.new(file).relative_path_from(Pathname.new(path)).to_s
end
end
end

View file

@ -0,0 +1,50 @@
# frozen_string_literal: true
# Se encargar de guardar cambios en sitios
# TODO: Implementar rollback en la configuración
# rubocop:disable Metrics/BlockLength
SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
# Crea un sitio, agrega un rol nuevo y guarda los cambios a la
# configuración en el repositorio git
def create
self.site = Site.new params
add_role temporal: false, rol: 'usuarie'
I18n.with_locale(usuarie.try(:lang) || I18n.default_locale) do
site.save &&
site.config.write &&
commit_config(action: :create)
end
site
end
# Actualiza el sitio y guarda los cambios en la configuración
def update
I18n.with_locale(usuarie.try(:lang) || I18n.default_locale) do
site.update_attributes(params) &&
site.config.write &&
commit_config(action: :update)
end
site
end
private
# Guarda los cambios de la configuración en el repositorio git
def commit_config(action:)
site.repository
.commit(usuarie: usuarie,
file: site.config.path,
message: I18n.t("site_service.#{action}",
name: site.name))
end
def add_role(temporal: true, rol: 'invitade')
site.roles << Rol.new(site: site, usuarie: usuarie,
temporal: temporal, rol: rol)
end
end
# rubocop:enable Metrics/BlockLength

View file

@ -1,4 +1,7 @@
en:
site_service:
create: 'Created %{name}'
update: 'Updated %{name}'
post_service:
created: 'Created "%{title}"'
metadata:

View file

@ -1,4 +1,7 @@
es:
site_service:
create: 'Creado %{name}'
update: 'Actualizado %{name}'
post_service:
created: 'Creado "%{title}"'
metadata:

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true
require 'test_helper'
class SitesControllerTest < ActionDispatch::IntegrationTest
setup do
@rol = create :rol
@ -30,13 +32,14 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
test 'se pueden crear' do
name = SecureRandom.hex
design = create :design
post sites_url, headers: @authorization, params: {
site: {
name: name,
title: name,
description: name * 2,
design_id: create(:design).id,
design_id: design.id,
licencia_id: create(:licencia).id,
deploys_attributes: {
'0' => {
@ -52,6 +55,16 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
assert_equal @usuarie.email, site.roles.first.usuarie.email
assert_equal 'usuarie', site.roles.first.rol
assert_equal name, site.name
assert_equal name, site.title
assert_equal name * 2, site.description
assert_equal design, site.design
assert_equal design.gem, site.config.theme
assert_equal name, site.config.title
assert_equal name * 2, site.config.description
assert_equal I18n.t('site_service.create', name: name),
site.repository.rugged.head.target.message
site.destroy
end
@ -84,4 +97,36 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
Sidekiq::Testing.inline!
end
test 'se pueden actualizar' do
name = SecureRandom.hex
design = create :design
put site_url(@site), headers: @authorization, params: {
site: {
name: name,
title: name,
description: name * 2,
design_id: design.id,
licencia_id: create(:licencia).id,
deploys_attributes: {
'0' => {
type: 'DeployLocal'
}
}
}
}
@site = Site.find(@site.id)
assert_equal name, @site.name
assert_equal name, @site.title
assert_equal name * 2, @site.description
assert_equal design, @site.design
assert_equal design.gem, @site.config.theme
assert_equal name, @site.config.title
assert_equal name * 2, @site.config.description
assert_equal I18n.t('site_service.update', name: name),
@site.repository.rugged.head.target.message
end
end

View file

@ -23,15 +23,12 @@ class ConfigText < ActiveSupport::TestCase
@site.config.lang = 'es'
end
assert @site.config.write(@usuarie)
assert @site.config.write
config = Site::Config.new(@site)
assert_equal 'Test', config.name
assert_equal 'es', config.lang
assert_equal I18n.t('sites.repository.config'),
@site.repository.rugged.head.target.message
end
test 'se puede obtener información' do