mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-16 10:41:41 +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:
parent
ceaadeb7bf
commit
86ae7fb8f8
4 changed files with 100 additions and 0 deletions
38
app/models/indexed_post.rb
Normal file
38
app/models/indexed_post.rb
Normal 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
|
|
@ -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,
|
||||
|
|
56
app/models/post/indexable.rb
Normal file
56
app/models/post/indexable.rb
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue