Merge branch 'rails' into search-engine
This commit is contained in:
commit
7b15a32de0
23 changed files with 368 additions and 59 deletions
7
Makefile
7
Makefile
|
@ -29,10 +29,13 @@ serve: /etc/hosts
|
||||||
|
|
||||||
# make rails args="db:migrate"
|
# make rails args="db:migrate"
|
||||||
rails:
|
rails:
|
||||||
$(hain) 'cd /Sutty/sutty; bundle exec rails $(args)'
|
$(MAKE) bundle args="exec rails $(args)"
|
||||||
|
|
||||||
rake:
|
rake:
|
||||||
$(hain) 'cd /Sutty/sutty; bundle exec rake $(args)'
|
$(MAKE) bundle args="exec rake $(args)"
|
||||||
|
|
||||||
|
bundle:
|
||||||
|
$(hain) 'cd /Sutty/sutty; bundle $(args)'
|
||||||
|
|
||||||
# Servir JS con el dev server.
|
# Servir JS con el dev server.
|
||||||
# Esto acelera la compilación del javascript, tiene que correrse por separado
|
# Esto acelera la compilación del javascript, tiene que correrse por separado
|
||||||
|
|
|
@ -72,7 +72,8 @@ class SitesController < ApplicationController
|
||||||
authorize site
|
authorize site
|
||||||
|
|
||||||
# XXX: Convertir en una máquina de estados?
|
# XXX: Convertir en una máquina de estados?
|
||||||
DeployJob.perform_async site.id if site.enqueue!
|
site.enqueue!
|
||||||
|
DeployJob.perform_async site.id
|
||||||
|
|
||||||
redirect_to site_posts_path(site, locale: site.default_locale)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,13 +8,20 @@ class DeployJob < ApplicationJob
|
||||||
def perform(site, notify = true)
|
def perform(site, notify = true)
|
||||||
ActiveRecord::Base.connection_pool.with_connection do
|
ActiveRecord::Base.connection_pool.with_connection do
|
||||||
@site = Site.find(site)
|
@site = Site.find(site)
|
||||||
@site.update_attribute :status, 'building'
|
|
||||||
|
# Si ya hay una tarea corriendo, aplazar esta
|
||||||
|
if @site.building?
|
||||||
|
DeployJob.perform_in(60, site, notify)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
@site.update status: 'building'
|
||||||
# Asegurarse que DeployLocal sea el primero!
|
# Asegurarse que DeployLocal sea el primero!
|
||||||
@deployed = { deploy_local: deploy_locally }
|
@deployed = { deploy_local: deploy_locally }
|
||||||
|
|
||||||
# No es opcional
|
# No es opcional
|
||||||
unless @deployed[:deploy_local]
|
unless @deployed[:deploy_local]
|
||||||
@site.update_attribute :status, 'waiting'
|
@site.update status: 'waiting'
|
||||||
notify_usuaries if notify
|
notify_usuaries if notify
|
||||||
|
|
||||||
# Hacer fallar la tarea
|
# Hacer fallar la tarea
|
||||||
|
@ -23,7 +30,7 @@ class DeployJob < ApplicationJob
|
||||||
|
|
||||||
deploy_others
|
deploy_others
|
||||||
notify_usuaries if notify
|
notify_usuaries if notify
|
||||||
@site.update_attribute :status, 'waiting'
|
@site.update status: 'waiting'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/MethodLength
|
# rubocop:enable Metrics/MethodLength
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
# Almacena el UUID de otro Post y actualiza el valor en el Post
|
# Almacena el UUID de otro Post y actualiza el valor en el Post
|
||||||
# relacionado.
|
# relacionado.
|
||||||
class MetadataBelongsTo < MetadataRelatedPosts
|
class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
def value_was=(new_value)
|
|
||||||
@belongs_to = nil
|
|
||||||
@belonged_to = nil
|
|
||||||
|
|
||||||
super(new_value)
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: Convertir algunos tipos de valores en módulos para poder
|
# TODO: Convertir algunos tipos de valores en módulos para poder
|
||||||
# implementar varios tipos de campo sin repetir código
|
# implementar varios tipos de campo sin repetir código
|
||||||
#
|
#
|
||||||
|
@ -39,10 +32,14 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
|
|
||||||
# Si estamos cambiando la relación, tenemos que eliminar la relación
|
# Si estamos cambiando la relación, tenemos que eliminar la relación
|
||||||
# anterior
|
# anterior
|
||||||
belonged_to[inverse].value.delete post.uuid.value if changed? && belonged_to.present?
|
if belonged_to.present?
|
||||||
|
belonged_to[inverse].value = belonged_to[inverse].value.reject do |rej|
|
||||||
|
rej == post.uuid.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# No duplicar las relaciones
|
# No duplicar las relaciones
|
||||||
belongs_to[inverse].value << post.uuid.value unless belongs_to.blank? || included?
|
belongs_to[inverse].value = (belongs_to[inverse].value.dup << post.uuid.value) unless belongs_to.blank? || included?
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -63,20 +60,13 @@ class MetadataBelongsTo < MetadataRelatedPosts
|
||||||
end
|
end
|
||||||
|
|
||||||
# El Post relacionado con este artículo
|
# El Post relacionado con este artículo
|
||||||
#
|
|
||||||
# XXX: Memoizamos usando el valor para tener el valor siempre
|
|
||||||
# actualizado.
|
|
||||||
def belongs_to
|
def belongs_to
|
||||||
return if value.blank?
|
posts.find(value, uuid: true) if value.present?
|
||||||
|
|
||||||
@belongs_to ||= posts.find(value, uuid: true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# El artículo relacionado anterior
|
# El artículo relacionado anterior
|
||||||
def belonged_to
|
def belonged_to
|
||||||
return if value_was.blank?
|
posts.find(value_was, uuid: true) if value_was.present?
|
||||||
|
|
||||||
@belonged_to ||= posts.find(value_was, uuid: true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def related_posts?
|
def related_posts?
|
||||||
|
|
|
@ -8,6 +8,8 @@ class MetadataDocumentDate < MetadataTemplate
|
||||||
end
|
end
|
||||||
|
|
||||||
def value_from_document
|
def value_from_document
|
||||||
|
return nil if post.new?
|
||||||
|
|
||||||
document.date
|
document.date
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,13 +17,47 @@ class MetadataDocumentDate < MetadataTemplate
|
||||||
true && !private?
|
true && !private?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Siempre es obligatorio
|
||||||
|
def required
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
super
|
||||||
|
|
||||||
|
errors << I18n.t('metadata.date.invalid_format') unless valid_format?
|
||||||
|
|
||||||
|
errors.empty?
|
||||||
|
end
|
||||||
|
|
||||||
# El valor puede ser un Date, Time o una String en el formato
|
# El valor puede ser un Date, Time o una String en el formato
|
||||||
# "yyyy-mm-dd"
|
# "yyyy-mm-dd"
|
||||||
|
#
|
||||||
|
# XXX: Date.iso8601 acepta fechas en el futuro lejano, como 20000,
|
||||||
|
# pero Jekyll las limita a cuatro cifras, así que vamos a mantener
|
||||||
|
# eso.
|
||||||
|
#
|
||||||
|
# @see {https://github.com/jekyll/jekyll/blob/master/lib/jekyll/document.rb#L15}
|
||||||
def value
|
def value
|
||||||
return (self[:value] = value_from_document || default_value) if self[:value].nil?
|
self[:value] =
|
||||||
|
case self[:value]
|
||||||
self[:value] = Date.iso8601(self[:value]).to_time if self[:value].is_a? String
|
when String
|
||||||
|
begin
|
||||||
self[:value]
|
Date.iso8601(self[:value]).to_time
|
||||||
|
rescue Date::Error
|
||||||
|
value_from_document || default_value
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self[:value] || value_from_document || default_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def valid_format?
|
||||||
|
return true if self[:value].is_a?(Time)
|
||||||
|
|
||||||
|
@valid_format_re ||= /\A\d{2,4}-\d{1,2}-\d{1,2}\z/
|
||||||
|
@valid_format_re =~ self[:value].to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ class MetadataHasAndBelongsToMany < MetadataHasMany
|
||||||
#
|
#
|
||||||
# Buscamos en belongs_to la relación local, si se eliminó hay que
|
# Buscamos en belongs_to la relación local, si se eliminó hay que
|
||||||
# quitarla de la relación remota, sino hay que agregarla.
|
# quitarla de la relación remota, sino hay que agregarla.
|
||||||
|
#
|
||||||
def save
|
def save
|
||||||
# XXX: No usamos super
|
# XXX: No usamos super
|
||||||
self[:value] = sanitize value
|
self[:value] = sanitize value
|
||||||
|
@ -25,27 +26,21 @@ class MetadataHasAndBelongsToMany < MetadataHasMany
|
||||||
return true unless changed?
|
return true unless changed?
|
||||||
return true unless inverse?
|
return true unless inverse?
|
||||||
|
|
||||||
|
# XXX: Usamos asignación para aprovechar value= que setea el valor
|
||||||
|
# anterior en @value_was
|
||||||
(had_many - has_many).each do |remove|
|
(had_many - has_many).each do |remove|
|
||||||
remove[inverse]&.value&.delete post.uuid.value
|
remove[inverse].value = remove[inverse].value.reject do |rej|
|
||||||
|
rej == post.uuid.value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
(has_many - had_many).each do |add|
|
(has_many - had_many).each do |add|
|
||||||
next unless add[inverse]
|
next unless add[inverse]
|
||||||
next if add[inverse].value.include? post.uuid.value
|
next if add[inverse].value.include? post.uuid.value
|
||||||
|
|
||||||
add[inverse].value << post.uuid.value
|
add[inverse].value = (add[inverse].value.dup << post.uuid.value)
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Igual que en MetadataRelatedPosts
|
|
||||||
# TODO: Mover a un módulo
|
|
||||||
def sanitize(uuid)
|
|
||||||
super(uuid.map do |u|
|
|
||||||
u.to_s.gsub(/[^a-f0-9\-]/i, '')
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,14 +6,6 @@
|
||||||
# Localmente tenemos un Array de UUIDs. Remotamente tenemos una String
|
# Localmente tenemos un Array de UUIDs. Remotamente tenemos una String
|
||||||
# apuntando a un Post, que se mantiene actualizado como el actual.
|
# apuntando a un Post, que se mantiene actualizado como el actual.
|
||||||
class MetadataHasMany < MetadataRelatedPosts
|
class MetadataHasMany < MetadataRelatedPosts
|
||||||
# Invalidar la relación anterior
|
|
||||||
def value_was=(new_value)
|
|
||||||
@had_many = nil
|
|
||||||
@has_many = nil
|
|
||||||
|
|
||||||
super(new_value)
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -24,14 +16,16 @@ class MetadataHasMany < MetadataRelatedPosts
|
||||||
|
|
||||||
# Todos los Post relacionados
|
# Todos los Post relacionados
|
||||||
def has_many
|
def has_many
|
||||||
@has_many ||= posts.where(uuid: value)
|
return default_value if value.blank?
|
||||||
|
|
||||||
|
posts.where(uuid: value)
|
||||||
end
|
end
|
||||||
|
|
||||||
# La relación anterior
|
# La relación anterior
|
||||||
def had_many
|
def had_many
|
||||||
return [] if value_was.blank?
|
return default_value if value_was.blank?
|
||||||
|
|
||||||
@had_many ||= posts.where(uuid: value_was)
|
posts.where(uuid: value_was)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inverse?
|
def inverse?
|
||||||
|
|
|
@ -30,7 +30,7 @@ class MetadataRelatedPosts < MetadataArray
|
||||||
|
|
||||||
# Obtiene todos los posts y opcionalmente los filtra
|
# Obtiene todos los posts y opcionalmente los filtra
|
||||||
def posts
|
def posts
|
||||||
@posts ||= site.posts(lang: lang).where(**filter)
|
site.posts(lang: lang).where(**filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
def title(post)
|
def title(post)
|
||||||
|
|
|
@ -55,9 +55,7 @@ class Post
|
||||||
public_send(attr)&.value = args[attr] if args.key?(attr)
|
public_send(attr)&.value = args[attr] if args.key?(attr)
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX: No usamos Post#read porque a esta altura todavía no sabemos
|
document.read! unless new?
|
||||||
# nada del Document
|
|
||||||
document.read! if File.exist? document.path
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
|
@ -238,12 +236,14 @@ class Post
|
||||||
template = public_send attr
|
template = public_send attr
|
||||||
|
|
||||||
unless template.front_matter?
|
unless template.front_matter?
|
||||||
body += "\n\n"
|
body += "\n\n" if body.present?
|
||||||
body += template.value
|
body += template.value
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
next if template.empty?
|
# Queremos mantener los Array en el resultado final para que
|
||||||
|
# siempre respondan a {% for %} en Liquid.
|
||||||
|
next if template.empty? && !template.value.is_a?(Array)
|
||||||
|
|
||||||
[attr.to_s, template.value]
|
[attr.to_s, template.value]
|
||||||
end.compact.to_h
|
end.compact.to_h
|
||||||
|
@ -301,6 +301,7 @@ class Post
|
||||||
end
|
end
|
||||||
|
|
||||||
# Vuelve a leer el post para tomar los cambios
|
# Vuelve a leer el post para tomar los cambios
|
||||||
|
document.reset
|
||||||
read
|
read
|
||||||
|
|
||||||
written?
|
written?
|
||||||
|
|
|
@ -93,8 +93,7 @@ class PostRelation < Array
|
||||||
def where(**args)
|
def where(**args)
|
||||||
return self if args.empty?
|
return self if args.empty?
|
||||||
|
|
||||||
@where ||= {}
|
begin
|
||||||
@where[args.hash.to_s] ||= begin
|
|
||||||
PostRelation.new(site: site, lang: lang).concat(select do |post|
|
PostRelation.new(site: site, lang: lang).concat(select do |post|
|
||||||
result = args.map do |attr, value|
|
result = args.map do |attr, value|
|
||||||
next unless post.attribute?(attr)
|
next unless post.attribute?(attr)
|
||||||
|
|
|
@ -306,14 +306,25 @@ class Site < ApplicationRecord
|
||||||
|
|
||||||
# Poner en la cola de compilación
|
# Poner en la cola de compilación
|
||||||
def enqueue!
|
def enqueue!
|
||||||
!enqueued? && update_attribute(:status, 'enqueued')
|
update(status: 'enqueued') if waiting?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Está en la cola de compilación?
|
# Está en la cola de compilación?
|
||||||
|
#
|
||||||
|
# TODO: definir todos estos métodos dinámicamente, aunque todavía no
|
||||||
|
# tenemos una máquina de estados propiamente dicha.
|
||||||
def enqueued?
|
def enqueued?
|
||||||
status == 'enqueued'
|
status == 'enqueued'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def waiting?
|
||||||
|
status == 'waiting'
|
||||||
|
end
|
||||||
|
|
||||||
|
def building?
|
||||||
|
status == 'building'
|
||||||
|
end
|
||||||
|
|
||||||
# Cargar el sitio Jekyll
|
# Cargar el sitio Jekyll
|
||||||
#
|
#
|
||||||
# TODO: En lugar de leer todo junto de una vez, extraer la carga de
|
# TODO: En lugar de leer todo junto de una vez, extraer la carga de
|
||||||
|
|
|
@ -73,6 +73,15 @@ module Jekyll
|
||||||
Document.class_eval do
|
Document.class_eval do
|
||||||
alias_method :read!, :read
|
alias_method :read!, :read
|
||||||
def read; end
|
def read; end
|
||||||
|
|
||||||
|
# Permitir restablecer el documento sin crear uno nuevo
|
||||||
|
def reset
|
||||||
|
@path = @extname = @has_yaml_header = @relative_path = nil
|
||||||
|
@basename_without_ext = @data = @basename = nil
|
||||||
|
@renderer = @url_placeholders = @url = nil
|
||||||
|
@to_liquid = @write_p = @excerpt_separator = @id = nil
|
||||||
|
@related_posts = @cleaned_relative_path = self.content = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Prevenir la instanciación de Time
|
# Prevenir la instanciación de Time
|
||||||
|
|
|
@ -102,6 +102,13 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
|
||||||
'index.html'))
|
'index.html'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'no se pueden encolar varias veces seguidas' do
|
||||||
|
assert_enqueued_jobs 2 do
|
||||||
|
post site_enqueue_url(@site), headers: @authorization
|
||||||
|
post site_enqueue_url(@site), headers: @authorization
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test 'se pueden actualizar' do
|
test 'se pueden actualizar' do
|
||||||
name = SecureRandom.hex
|
name = SecureRandom.hex
|
||||||
design = Design.all.where.not(id: @site.design_id).sample
|
design = Design.all.where.not(id: @site.design_id).sample
|
||||||
|
|
2
test/fixtures/site_with_relationships/README.md
vendored
Normal file
2
test/fixtures/site_with_relationships/README.md
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
This is site where posts can have many authors and viceversa and posts
|
||||||
|
can be replies to others.
|
2
test/fixtures/site_with_relationships/_config.yml
vendored
Normal file
2
test/fixtures/site_with_relationships/_config.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
locales:
|
||||||
|
- en
|
9
test/fixtures/site_with_relationships/_data/layouts/author.yml
vendored
Normal file
9
test/fixtures/site_with_relationships/_data/layouts/author.yml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title:
|
||||||
|
type: 'string'
|
||||||
|
required: true
|
||||||
|
posts:
|
||||||
|
type: 'has_and_belongs_to_many'
|
||||||
|
inverse: 'authors'
|
||||||
|
filter:
|
||||||
|
layout: 'post'
|
23
test/fixtures/site_with_relationships/_data/layouts/post.yml
vendored
Normal file
23
test/fixtures/site_with_relationships/_data/layouts/post.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
title:
|
||||||
|
type: 'string'
|
||||||
|
required: true
|
||||||
|
authors:
|
||||||
|
type: 'has_and_belongs_to_many'
|
||||||
|
inverse: 'posts'
|
||||||
|
filter:
|
||||||
|
layout: 'author'
|
||||||
|
posts:
|
||||||
|
type: 'has_many'
|
||||||
|
inverse: 'in_reply_to'
|
||||||
|
filter:
|
||||||
|
layout: 'post'
|
||||||
|
in_reply_to:
|
||||||
|
type: 'belongs_to'
|
||||||
|
inverse: 'posts'
|
||||||
|
filter:
|
||||||
|
layout: 'post'
|
||||||
|
recommended_posts:
|
||||||
|
type: 'related_posts'
|
||||||
|
filter:
|
||||||
|
layout: 'post'
|
0
test/fixtures/site_with_relationships/_en/.keep
vendored
Normal file
0
test/fixtures/site_with_relationships/_en/.keep
vendored
Normal file
1
test/fixtures/site_with_relationships/_posts
vendored
Symbolic link
1
test/fixtures/site_with_relationships/_posts
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
_en
|
62
test/models/metadata_belongs_to_test.rb
Normal file
62
test/models/metadata_belongs_to_test.rb
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'test_helper'
|
||||||
|
require_relative 'metadata_test'
|
||||||
|
|
||||||
|
class MetadataBelongsToTest < ActiveSupport::TestCase
|
||||||
|
include MetadataTest
|
||||||
|
|
||||||
|
test 'se pueden relacionar artículos' do
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex, in_reply_to: post.uuid.value)
|
||||||
|
|
||||||
|
assert_equal post, reply.in_reply_to.belongs_to
|
||||||
|
assert_includes post.posts.has_many, reply
|
||||||
|
|
||||||
|
assert post.save
|
||||||
|
|
||||||
|
assert_equal reply.document.data['in_reply_to'], post.document.data['uuid']
|
||||||
|
assert_includes post.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede eliminar la relación' do
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex, in_reply_to: post.uuid.value)
|
||||||
|
|
||||||
|
reply.in_reply_to.value = ''
|
||||||
|
assert reply.save
|
||||||
|
|
||||||
|
assert_not_equal post, reply.in_reply_to.belongs_to
|
||||||
|
assert_equal post, reply.in_reply_to.belonged_to
|
||||||
|
assert_nil reply.in_reply_to.belongs_to
|
||||||
|
assert_not_includes post.posts.has_many, reply
|
||||||
|
|
||||||
|
assert post.save
|
||||||
|
|
||||||
|
assert_nil reply.document.data['in_reply_to']
|
||||||
|
assert_not_includes post.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede cambiar la relación' do
|
||||||
|
post1 = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
post2 = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex, in_reply_to: post1.uuid.value)
|
||||||
|
|
||||||
|
reply.in_reply_to.value = post2.uuid.value
|
||||||
|
assert reply.save
|
||||||
|
|
||||||
|
assert_not_equal post1, reply.in_reply_to.belongs_to
|
||||||
|
assert_equal post1, reply.in_reply_to.belonged_to
|
||||||
|
assert_not_includes post1.posts.has_many, reply
|
||||||
|
|
||||||
|
assert_equal post2, reply.in_reply_to.belongs_to
|
||||||
|
assert_includes post2.posts.has_many, reply
|
||||||
|
|
||||||
|
assert post1.save
|
||||||
|
assert post2.save
|
||||||
|
|
||||||
|
assert_equal post2.document.data['uuid'], reply.document.data['in_reply_to']
|
||||||
|
assert_includes post2.document.data['posts'], reply.document.data['uuid']
|
||||||
|
assert_not_includes post1.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
end
|
76
test/models/metadata_has_and_belongs_to_many_test.rb
Normal file
76
test/models/metadata_has_and_belongs_to_many_test.rb
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'test_helper'
|
||||||
|
require_relative 'metadata_test'
|
||||||
|
|
||||||
|
class MetadataHasAndBelongsManyTest < ActiveSupport::TestCase
|
||||||
|
include MetadataTest
|
||||||
|
|
||||||
|
test 'se pueden relacionar artículos' do
|
||||||
|
author = @site.posts.create(layout: :author, title: SecureRandom.hex)
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
|
||||||
|
post.authors.value = [author.uuid.value]
|
||||||
|
assert post.save
|
||||||
|
|
||||||
|
assert_includes author.posts.has_many, post
|
||||||
|
assert_includes post.authors.has_many, author
|
||||||
|
|
||||||
|
assert author.save
|
||||||
|
|
||||||
|
assert_includes author.document.data['posts'], post.document.data['uuid']
|
||||||
|
assert_includes post.document.data['authors'], author.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede eliminar la relación' do
|
||||||
|
author = @site.posts.create(layout: :author, title: SecureRandom.hex)
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex, authors: [author.uuid.value])
|
||||||
|
|
||||||
|
assert_includes post.authors.value, author.uuid.value
|
||||||
|
assert_includes author.posts.value, post.uuid.value
|
||||||
|
|
||||||
|
post.authors.value = []
|
||||||
|
assert post.save
|
||||||
|
|
||||||
|
assert_not_includes author.posts.has_many, post
|
||||||
|
assert_not_includes post.authors.has_many, author
|
||||||
|
|
||||||
|
assert_includes author.posts.had_many, post
|
||||||
|
assert_includes post.authors.had_many, author
|
||||||
|
|
||||||
|
assert author.save
|
||||||
|
|
||||||
|
assert_not_includes author.document.data['posts'], post.document.data['uuid']
|
||||||
|
assert_not_includes post.document.data['authors'], author.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede cambiar la relación' do
|
||||||
|
author = @site.posts.create(layout: :author, title: SecureRandom.hex)
|
||||||
|
post1 = @site.posts.create(layout: :post, title: SecureRandom.hex, authors: [author.uuid.value])
|
||||||
|
post2 = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
|
||||||
|
author.posts.value = [post2.uuid.value]
|
||||||
|
assert author.save
|
||||||
|
|
||||||
|
assert_not_includes author.posts.has_many, post1
|
||||||
|
assert_not_includes post1.authors.has_many, author
|
||||||
|
|
||||||
|
assert_includes author.posts.had_many, post1
|
||||||
|
assert_includes post1.authors.had_many, author
|
||||||
|
|
||||||
|
assert_not_includes author.posts.had_many, post2
|
||||||
|
assert_not_includes post2.authors.had_many, author
|
||||||
|
|
||||||
|
assert_includes author.posts.has_many, post2
|
||||||
|
assert_includes post2.authors.has_many, author
|
||||||
|
|
||||||
|
assert post1.save
|
||||||
|
assert post2.save
|
||||||
|
|
||||||
|
assert_not_includes author.document.data['posts'], post1.document.data['uuid']
|
||||||
|
assert_not_includes post1.document.data['authors'], author.document.data['uuid']
|
||||||
|
|
||||||
|
assert_includes author.document.data['posts'], post2.document.data['uuid']
|
||||||
|
assert_includes post2.document.data['authors'], author.document.data['uuid']
|
||||||
|
end
|
||||||
|
end
|
62
test/models/metadata_has_many_test.rb
Normal file
62
test/models/metadata_has_many_test.rb
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'test_helper'
|
||||||
|
require_relative 'metadata_test'
|
||||||
|
|
||||||
|
class MetadataHasManyTest < ActiveSupport::TestCase
|
||||||
|
include MetadataTest
|
||||||
|
|
||||||
|
test 'se pueden relacionar artículos' do
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex, posts: [reply.uuid.value])
|
||||||
|
|
||||||
|
assert_equal post, reply.in_reply_to.belongs_to
|
||||||
|
assert_includes post.posts.has_many, reply
|
||||||
|
|
||||||
|
assert reply.save
|
||||||
|
|
||||||
|
assert_equal reply.document.data['in_reply_to'], post.document.data['uuid']
|
||||||
|
assert_includes post.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede eliminar la relación' do
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
post = @site.posts.create(layout: :post, title: SecureRandom.hex, posts: [reply.uuid.value])
|
||||||
|
|
||||||
|
post.posts.value = []
|
||||||
|
assert post.save
|
||||||
|
|
||||||
|
assert_not_equal post, reply.in_reply_to.belongs_to
|
||||||
|
assert_equal post, reply.in_reply_to.belonged_to
|
||||||
|
assert_nil reply.in_reply_to.belongs_to
|
||||||
|
assert_not_includes post.posts.has_many, reply
|
||||||
|
|
||||||
|
assert reply.save
|
||||||
|
|
||||||
|
assert_nil reply.document.data['in_reply_to']
|
||||||
|
assert_not_includes post.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'se puede cambiar la relación' do
|
||||||
|
reply = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
post1 = @site.posts.create(layout: :post, title: SecureRandom.hex, posts: [reply.uuid.value])
|
||||||
|
post2 = @site.posts.create(layout: :post, title: SecureRandom.hex)
|
||||||
|
|
||||||
|
reply.in_reply_to.value = post2.uuid.value
|
||||||
|
assert reply.save
|
||||||
|
|
||||||
|
assert_not_equal post1, reply.in_reply_to.belongs_to
|
||||||
|
assert_equal post1, reply.in_reply_to.belonged_to
|
||||||
|
assert_not_includes post1.posts.has_many, reply
|
||||||
|
|
||||||
|
assert_equal post2, reply.in_reply_to.belongs_to
|
||||||
|
assert_includes post2.posts.has_many, reply
|
||||||
|
|
||||||
|
assert post1.save
|
||||||
|
assert post2.save
|
||||||
|
|
||||||
|
assert_equal post2.document.data['uuid'], reply.document.data['in_reply_to']
|
||||||
|
assert_includes post2.document.data['posts'], reply.document.data['uuid']
|
||||||
|
assert_not_includes post1.document.data['posts'], reply.document.data['uuid']
|
||||||
|
end
|
||||||
|
end
|
19
test/models/metadata_test.rb
Normal file
19
test/models/metadata_test.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module MetadataTest
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
setup do
|
||||||
|
name = SecureRandom.hex
|
||||||
|
# TODO: Poder cambiar el nombre
|
||||||
|
FileUtils.cp_r(Rails.root.join('test', 'fixtures', 'site_with_relationships'), Rails.root.join('_sites', name))
|
||||||
|
|
||||||
|
@site = create :site, name: name
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
@site&.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue