Skip to content

Commit

Permalink
Improve ingredient extension
Browse files Browse the repository at this point in the history
- Use the multisearch configuration on the supported ingredients
- Fix the search for image caption (previously only the object string was stored)
- improve readability of the ingredient extension spec
- add public and upload path to gitignore - the specs are creating small images to test the picture ingredient
  • Loading branch information
kulturbande committed Jul 13, 2023
1 parent ec6ae1e commit b963885
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 98 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 15 additions & 12 deletions app/extensions/alchemy/pg_search/ingredient_extension.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
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) &&
value.present? && !!element&.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]}))
177 changes: 91 additions & 86 deletions spec/models/ingredient_spec.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b963885

Please sign in to comment.