5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-07-01 22:36:08 +00:00

los posts pueden ser indexados

`IndexedPost` es una representación indexada por PG de `Post`.  ambos
están relacionados por el UUID de `Post`, de forma que se puede traer el
artículo completo (por ejemplo al previsualizar o editar).

cada artículo está indexado según su idioma.  para eso convertimos el
locale en el equivalente en el diccionario de PG.

`Site#index_posts` es un método para indexar todos los artículos en
masa.

`Post#to_index` genera el `IndexedPost` correspondiente

`IndexedPost.search(:es, 'hola')` busca "hola" en todos los artículos
utilizando el diccionario de castellano.  esto no quiere decir que
busque en todos los artículos en castellano.  por ahora para eso hay que
hacer algo como:

```ruby
site = Site.find 1
site.indexed_posts.where(locale: :english).search(:en, 'hello')
```

para encontrar todos los artículos en inglés del sitio con id 1
This commit is contained in:
f 2021-05-06 12:52:30 -03:00
parent ceaadeb7bf
commit 86ae7fb8f8
4 changed files with 100 additions and 0 deletions

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
# La representación indexable de un artículo
class IndexedPost < ApplicationRecord
include PgSearch::Model
# La traducción del locale según Sutty al locale según PostgreSQL
DICTIONARIES = {
es: 'spanish',
en: 'english'
}.freeze
# TODO: Los indexed posts tienen que estar scopeados al idioma actual,
# no buscar sobre todos
pg_search_scope :search,
lambda { |locale, query|
{
against: :content,
query: query,
using: {
tsearch: {
dictionary: IndexedPost.to_dictionary(locale: locale),
tsvector_column: 'indexed_content'
}
}
}
}
belongs_to :site
# Convertir locale a direccionario de PG
#
# @param [String,Symbol]
# @return [String]
def self.to_dictionary(locale:)
DICTIONARIES[locale.to_sym] || 'simple'
end
end

View file

@ -17,6 +17,8 @@ class Post
attr_reader :attributes, :errors, :layout, :site, :document
include Post::Indexable
class << self
# Obtiene el layout sin leer el Document
#
@ -191,6 +193,8 @@ class Post
post: self, required: true)
end
alias locale lang
# TODO: Mover a method_missing
def uuid
@metadata[:uuid] ||= MetadataUuid.new(document: document, site: site, layout: layout, name: :uuid, type: :uuid,

View file

@ -0,0 +1,56 @@
# frozen_string_literal: true
class Post
# Vuelve indexables a los Posts
module Indexable
extend ActiveSupport::Concern
included do
# Devuelve una versión indexable del Post
#
# @return [IndexedPosts]
def to_index
@to_index ||= IndexedPost.find_or_create_by(id: uuid.value).tap do |indexed_post|
indexed_post.layout = layout.name
indexed_post.site_id = site.id
indexed_post.path = path.basename
indexed_post.locale = IndexedPost.to_dictionary(locale: locale.value)
indexed_post.title = title.value
indexed_post.front_matter = indexable_front_matter
indexed_post.content = indexable_content
end
end
private
# Los metadatos que se almacenan como objetos JSON. Empezamos con
# las categorías porque se usan para filtrar en el listado de
# artículos.
#
# @return [Hash]
def indexable_front_matter
return {} unless attribute? :categories
{ categories: categories.indexable_values }
end
# Devuelve un documento indexable en texto plano
#
# XXX: No memoizamos para permitir actualizaciones, aunque
# probablemente se indexe una sola vez.
#
# @return [String]
def indexable_content
indexable_attributes.map do |attr|
self[attr].to_s
end.join("\n")
end
def indexable_attributes
@indexable_attributes ||= attributes.select do |attr|
self[attr].indexable?
end
end
end
end
end

View file

@ -7,6 +7,7 @@ class Site < ApplicationRecord
include Site::Forms
include Site::FindAndReplace
include Site::Api
include Site::Index
include Tienda
# Cifrar la llave privada que cifra y decifra campos ocultos. Sutty
@ -37,6 +38,7 @@ class Site < ApplicationRecord
belongs_to :design
belongs_to :licencia
has_many :indexed_posts, dependent: :destroy
has_many :log_entries, dependent: :destroy
has_many :deploys, dependent: :destroy
has_many :build_stats, through: :deploys