diff --git a/.gitignore b/.gitignore index 0e341b3..b1f7195 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ Gemfile.lock spec/dummy/log/*.log spec/dummy/db/*.sqlite3* spec/dummy/tmp/* +spec/dummy/public/* +spec/dummy/uploads/* .ruby-* node_modules yarn.lock diff --git a/app/extensions/alchemy/pg_search/ingredient_extension.rb b/app/extensions/alchemy/pg_search/ingredient_extension.rb index 8823fd0..7ef96c6 100644 --- a/app/extensions/alchemy/pg_search/ingredient_extension.rb +++ b/app/extensions/alchemy/pg_search/ingredient_extension.rb @@ -1,15 +1,4 @@ module Alchemy::PgSearch::IngredientExtension - def self.prepended(base) - base.include PgSearch::Model - base.multisearchable( - against: [ - :value, - ], - additional_attributes: ->(ingredient) { { page_id: ingredient.element.page.id } }, - if: :searchable?, - ) - end - def searchable? Alchemy::PgSearch.is_searchable?(type) && (definition.key?(:searchable) ? definition[:searchable] : true) && @@ -17,4 +6,18 @@ def searchable? end end -Alchemy::Ingredient.prepend(Alchemy::PgSearch::IngredientExtension) +# add the PgSearch model to all ingredients +Alchemy::Ingredient.include(PgSearch::Model) +Alchemy::Ingredient.include(Alchemy::PgSearch::IngredientExtension) + +# set up the default configuration for all supported ingredients +config = { + against: [:value], + additional_attributes: ->(ingredient) { { page_id: ingredient.element.page.id } }, + if: :searchable? +} + +# only enable the search for Text, Richtext, and Picture +Alchemy::Ingredients::Text.multisearchable(config) +Alchemy::Ingredients::Richtext.multisearchable(config) +Alchemy::Ingredients::Picture.multisearchable(config.merge({against: [:caption]})) diff --git a/spec/models/ingredient_spec.rb b/spec/models/ingredient_spec.rb index 88807f6..bb07aee 100644 --- a/spec/models/ingredient_spec.rb +++ b/spec/models/ingredient_spec.rb @@ -1,112 +1,117 @@ require "spec_helper" -describe Alchemy::Ingredient do - let(:element) do - page_version = create(:alchemy_page_version, :published) - create(:alchemy_element, :with_contents, name: "ingredient_test", public: true, page_version: page_version) - end +RSpec.shared_examples_for "it is searchable" do + describe "searchable?" do + subject { ingredient.searchable? } + + context "element and ingredient are searchable" do + it { is_expected.to be(true) } + + context "but configured as not searchable" do + before do + expect(ingredient).to receive(:definition).at_least(:once) do + { + searchable: false, + } + end + end - Alchemy::PgSearch::SEARCHABLE_INGREDIENTS.each do |ingredient_type| - describe ingredient_type do - let(:ingredient) { create(:"alchemy_ingredient_#{ingredient_type.downcase}", value: "foo", element: element) } + it { is_expected.to be(false) } + end + end - describe "searchable?" do - subject { ingredient.searchable? } + context "ingredient has no content" do + it "should be not searchable" do + ingredient.value = nil + expect(ingredient.searchable?).to be(false) + end + end - context "element and ingredient are searchable" do - it { is_expected.to be(true) } + context "element is not public" do + it "should be not searchable" do + element.public = false + expect(ingredient.searchable?).to be(false) + end + end - context "but configured as not searchable" do - before do - expect(ingredient).to receive(:definition).at_least(:once) do - { - searchable: false, - } - end - end + context "ingredient has no related content" do + let(:ingredient) { create(:alchemy_ingredient_text) } - it { is_expected.to be(false) } - end - end + it "should be not searchable" do + expect(ingredient.searchable?).to be(false) + end + end + end +end - context "ingredient has no content" do - it "should be not searchable" do - ingredient.value = nil - expect(ingredient.searchable?).to be(false) - end - end +RSpec.shared_examples_for "it is in search index" do + describe "search index" do + let(:document) { PgSearch::Document.first } - context "element is not public" do - it "should be not searchable" do - element.public = false - expect(ingredient.searchable?).to be(false) - end - end + subject do + ingredient + ::PgSearch::Multisearch.rebuild described_class + end + + it "should have one entry" do + subject + expect(PgSearch::Document.where(searchable_type: "Alchemy::Ingredient").count).to eq(1) + end - context "ingredient has no related content" do - let(:ingredient) { create(:alchemy_ingredient_text) } + it "should have the content" do + subject + expect(PgSearch::Document.first.content).to eq(content) + end - it "should be not searchable" do - expect(ingredient.searchable?).to be(false) - end + context "configured as not searchable" do + before do + expect_any_instance_of(ingredient.class).to receive(:definition).at_least(:once) do + { + searchable: false, + } end end - context "index" do - let(:document) { PgSearch::Document.first } + it "should have no index entry" do + subject + expect(PgSearch::Document.where(searchable_type: "Alchemy::Ingredient").count).to eq(0) + end + end - subject do - ingredient - ::PgSearch::Multisearch.rebuild Alchemy::Ingredient - end + it "should be the current ingredient" do + subject + expect(document.searchable).to eq(ingredient) + end + end +end - it "should have one entry" do - subject - expect(PgSearch::Document.where(searchable_type: "Alchemy::Ingredient").count).to eq(1) - end +describe Alchemy::Ingredient do + let(:element) do + page_version = create(:alchemy_page_version, :published) + create(:alchemy_element, :with_contents, name: "ingredient_test", public: true, page_version: page_version) + end - context "configured as not searchable" do - before do - expect_any_instance_of(ingredient.class).to receive(:definition).at_least(:once) do - { - searchable: false, - } - end - end + let(:content) { "foo bar"} - it "should have no index entry" do - subject - expect(PgSearch::Document.where(searchable_type: "Alchemy::Ingredient").count).to eq(0) - end - end + describe Alchemy::Ingredients::Text do + let(:ingredient) { create(:alchemy_ingredient_text, value: content, element: element) } - it "should be the current ingredient" do - subject - expect(document.searchable).to eq(ingredient) - end - end - end + it_behaves_like "it is searchable" + it_behaves_like "it is in search index" end - context "not supported ingredient type" do - let(:ingredient) { create(:"alchemy_ingredient_boolean", value: true, element: element) } + describe Alchemy::Ingredients::Richtext do + let(:ingredient) { create(:alchemy_ingredient_richtext, value: content, element: element) } + let(:ingredient_class) { Alchemy::Ingredients::Text } - context "searchable?" do - it "should be not searchable" do - expect(ingredient.searchable?).to be(false) - end - end + it_behaves_like "it is searchable" + it_behaves_like "it is in search index" + end - context "index" do - let(:document) { PgSearch::Document.first } - before do - ingredient - ::PgSearch::Multisearch.rebuild Alchemy::Ingredient - end + describe Alchemy::Ingredients::Picture do + let(:ingredient) { create(:alchemy_ingredient_picture, value: create(:alchemy_picture), caption: content, element: element) } - it "should have no entries" do - expect(PgSearch::Document.all.length).to eq(0) - end - end + it_behaves_like "it is searchable" + it_behaves_like "it is in search index" end end