Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion app/models/workshop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ class Workshop < ApplicationRecord
scope :legacy, -> { where(legacy: true) }
scope :published, ->(published = nil) { published.to_s.present? ?
where(inactive: !published) : where(inactive: false) }
scope :title, ->(title) { where("workshops.title like ?", "%#{ title }%") }
scope :title, ->(title) {
sanitized_input = ActiveRecord::Base.sanitize_sql_like(title.to_s.gsub("-", ""))
where("REPLACE(workshops.title, '-', '') like ?", "%#{sanitized_input}%")
}
scope :windows_type_ids, ->(windows_type_ids) { where(windows_type_id: windows_type_ids) }
scope :order_by_date, ->(sort_order = "asc") {
order(Arel.sql(<<~SQL.squish))
Expand Down
34 changes: 24 additions & 10 deletions app/services/workshop_search_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,30 @@ def filter_by_title
def filter_by_query
return unless params[:query].present?

results = @workshops.search(params[:query]) # Use the SearchCop search scope directly on the relation

# If SearchCop returned an Array (e.g., because of scoring), convert back to Relation
if results.is_a?(Array)
ordered_ids = results.map(&:id)
@workshops = Workshop.where(id: ordered_ids)
.order(Arel.sql("FIELD(id, #{ordered_ids.join(',')})"))
else
@workshops = results
end
# Strip hyphens from the query to match against hyphen-stripped content
sanitized_query = ActiveRecord::Base.sanitize_sql_like(params[:query].to_s.gsub("-", "").strip)
return if sanitized_query.blank?

# Build a custom SQL query that strips hyphens from all searchable fields
searchable_fields = [
:title, :full_name,
:objective, :materials, :setup, :introduction,
:demonstration, :opening_circle, :warm_up,
:creation, :closing, :notes, :tips, :misc1, :misc2,
:objective_spanish, :materials_spanish, :setup_spanish, :introduction_spanish,
:demonstration_spanish, :opening_circle_spanish, :warm_up_spanish,
:creation_spanish, :closing_spanish, :notes_spanish, :tips_spanish, :misc1_spanish, :misc2_spanish
]

# Create WHERE conditions that strip hyphens from both field and search term
conditions = searchable_fields.map do |field|
"REPLACE(workshops.#{field}, '-', '') LIKE ?"
end.join(" OR ")

# Use the same sanitized query for all fields
query_params = Array.new(searchable_fields.length, "%#{sanitized_query}%")

@workshops = @workshops.where(conditions, *query_params)
end

# --- Search methods ---
Expand Down
61 changes: 61 additions & 0 deletions spec/services/workshop_search_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,66 @@
expect(service.sort).to eq('created')
end
end

context "hyphen-ignoring search" do
let!(:workshop_with_hyphen) do
create(:workshop, title: "Hello - Goodbye", year: 2025, month: 3)
end
let!(:workshop_without_hyphen) do
create(:workshop, title: "Hello Goodbye", year: 2025, month: 4)
end

context "title search" do
it "finds workshops with hyphens when searching without hyphens" do
service = WorkshopSearchService.new({ title: 'Hello Goodbye' }).call
workshops = service.workshops

expect(workshops).to include(workshop_with_hyphen)
expect(workshops).to include(workshop_without_hyphen)
end

it "finds workshops without hyphens when searching with hyphens" do
service = WorkshopSearchService.new({ title: 'Hello - Goodbye' }).call
workshops = service.workshops

expect(workshops).to include(workshop_with_hyphen)
expect(workshops).to include(workshop_without_hyphen)
end

it "finds workshops with multiple hyphens when searching with different hyphen patterns" do
workshop_multi_hyphen = create(:workshop, title: "Hello -- Goodbye", year: 2025, month: 5)

service = WorkshopSearchService.new({ title: 'Hello Goodbye' }).call
workshops = service.workshops

expect(workshops).to include(workshop_multi_hyphen)
end
end

context "query search" do
let!(:workshop_with_hyphen_content) do
create(:workshop, title: "Test Workshop", objective: "Learn about self-care", year: 2025, month: 6)
end
let!(:workshop_without_hyphen_content) do
create(:workshop, title: "Another Workshop", objective: "Learn about selfcare", year: 2025, month: 7)
end

it "finds workshops with hyphens in content when searching without hyphens" do
service = WorkshopSearchService.new({ query: 'selfcare' }).call
workshops = service.workshops

expect(workshops).to include(workshop_with_hyphen_content)
expect(workshops).to include(workshop_without_hyphen_content)
end

it "finds workshops without hyphens in content when searching with hyphens" do
service = WorkshopSearchService.new({ query: 'self-care' }).call
workshops = service.workshops

expect(workshops).to include(workshop_with_hyphen_content)
expect(workshops).to include(workshop_without_hyphen_content)
end
end
end
end
end