diff --git a/app/models/indexed_post.rb b/app/models/indexed_post.rb index 16858a6..7f6865f 100644 --- a/app/models/indexed_post.rb +++ b/app/models/indexed_post.rb @@ -13,26 +13,26 @@ class IndexedPost < ApplicationRecord # 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: dictionary, - tsvector_column: 'indexed_content' - }, - trigram: { - word_similarity: true - } - } - } - } + lambda { |locale, query| + { + against: :content, + query: query, + using: { + tsearch: { + dictionary: IndexedPost.to_dictionary(locale: locale), + tsvector_column: 'indexed_content' + }, + trigram: { + word_similarity: true + } + } + } + } # Trae los IndexedPost en el orden en que van a terminar en el sitio. - default_scope lambda { order(order: :desc, created_at: :desc) } - scope :in_category, lambda { |category| where("front_matter->'categories' ? :category", category: category.to_s) } - scope :by_usuarie, lambda { |usuarie| where("front_matter->'usuaries' @> :usuarie::jsonb", usuarie: usuarie.to_s) } + default_scope -> { order(order: :desc, created_at: :desc) } + scope :in_category, ->(category) { where("front_matter->'categories' ? :category", category: category.to_s) } + scope :by_usuarie, ->(usuarie) { where("front_matter->'usuaries' @> :usuarie::jsonb", usuarie: usuarie.to_s) } belongs_to :site diff --git a/app/models/post/indexable.rb b/app/models/post/indexable.rb index b1d6250..7757e7f 100644 --- a/app/models/post/indexable.rb +++ b/app/models/post/indexable.rb @@ -47,15 +47,10 @@ class Post # # @return [Hash] def indexable_front_matter - {}.tap do |indexable_front_matter| - indexable_front_matter = { - usuaries: usuaries.map(&:id), - draft: attribute?(:draft) ? draft.value : false - } - - if attribute? :categories - indexable_front_matter[:categories] = categories.indexable_values - end + {}.tap do |ifm| + ifm[:usuaries] = usuaries.map(&:id) + ifm[:draft] = attribute?(:draft) ? draft.value : false + ifm[:categories] = categories.indexable_values if attribute? :categories end end @@ -73,8 +68,8 @@ class Post def indexable_attributes @indexable_attributes ||= attributes.select do |attr| - self[attr].indexable? - end + self[attr].indexable? + end end end end diff --git a/app/models/site.rb b/app/models/site.rb index 4bfbed4..b3cae93 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -7,7 +7,6 @@ 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 @@ -38,7 +37,6 @@ 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 @@ -70,6 +68,9 @@ class Site < ApplicationRecord # El sitio en Jekyll attr_reader :jekyll + # XXX: Es importante incluir luego de los callbacks de :load_jekyll + include Site::Index + # No permitir HTML en estos atributos def title=(title) super(title.strip_tags) diff --git a/test/models/indexed_post_test.rb b/test/models/indexed_post_test.rb new file mode 100644 index 0000000..27d4e29 --- /dev/null +++ b/test/models/indexed_post_test.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'test_helper' + +class IndexedPostTest < ActiveSupport::TestCase + def site + @site ||= create :site + end + + teardown do + @site&.destroy + end + + test 'se pueden convertir los diccionarios' do + IndexedPost::DICTIONARIES.each do |locale, dict| + assert_equal dict, IndexedPost.to_dictionary(locale: locale) + end + end + + test 'se pueden buscar por categoría' do + assert(post = site.posts.create(title: SecureRandom.hex, description: SecureRandom.hex, + categories: [SecureRandom.hex, SecureRandom.hex])) + assert_not_empty site.indexed_posts.in_category(post.categories.value.sample) + end + + test 'se pueden encontrar por usuarie' do + usuarie = create :usuarie + assert(post = site.posts.create(title: SecureRandom.hex, description: SecureRandom.hex)) + + post.usuaries << usuarie + post.save + + assert_not_empty site.indexed_posts.by_usuarie(usuarie.id) + end +end diff --git a/test/models/post/indexable_test.rb b/test/models/post/indexable_test.rb new file mode 100644 index 0000000..6110bcf --- /dev/null +++ b/test/models/post/indexable_test.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'test_helper' + +class Post::IndexableTest < ActiveSupport::TestCase + setup do + @site = create :site + end + + teardown do + @site&.destroy + end + + test 'los posts se indexan apenas se crean' do + post = @site.posts.create(title: SecureRandom.hex, description: SecureRandom.hex) + indexed_post = @site.indexed_posts.find_by_title post.title.value + + assert indexed_post + assert_equal post.locale.value.to_s, indexed_post.locale + assert_equal post.order.value, indexed_post.order + assert_equal post.path.basename, indexed_post.path + assert_equal post.layout.name.to_s, indexed_post.layout + end + + test 'se pueden encontrar posts' do + post = @site.posts.sample + + assert @site.indexed_posts.where(locale: post.lang.value).search(post.lang.value, post.title.value) + assert @site.indexed_posts.where(locale: post.lang.value).search(post.lang.value, post.description.value) + end + + test 'se pueden actualizar posts' do + post = @site.posts.sample + post.description.value = SecureRandom.hex + + assert post.save + assert @site.indexed_posts.where(locale: post.lang.value).search(post.lang.value, post.description.value) + end + + test 'al borrar el post se borra el indice' do + post = @site.posts.sample + assert post.destroy + assert_not @site.indexed_posts.find_by_id(post.uuid.value) + end +end