Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SD-1446 use pg_search for full text search of porduct names when pg_search is available. #11416

Merged
merged 3 commits into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions common_spree_dependencies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
gem 'webmock', '~> 3.7'
gem 'timecop'
gem 'rails-controller-testing'
gem 'pg_search'
damianlegawiec marked this conversation as resolved.
Show resolved Hide resolved
end

group :test, :development do
Expand Down
20 changes: 20 additions & 0 deletions core/app/models/concerns/spree/product_scopes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ def self.for_user(user = nil)
group('spree_products.id').joins(:taxons).where(Taxon.arel_table[:name].eq(name))
end

# .search_by_name
if defined?(PgSearch) && ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
damianlegawiec marked this conversation as resolved.
Show resolved Hide resolved
include PgSearch::Model

if defined?(SpreeGlobalize)
pg_search_scope :search_by_name, associated_against: { translations: :name }, using: :tsearch
else
pg_search_scope :search_by_name, against: :name, using: :tsearch
end
else
def self.search_by_name(query)
if defined?(SpreeGlobalize)
joins(:translations).order(:name).where("LOWER(#{Product::Translation.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%").distinct
else
where("LOWER(#{Product.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%")
end
end
end
search_scopes << :search_by_name

def self.price_table_name
Price.quoted_table_name
end
Expand Down
8 changes: 0 additions & 8 deletions core/app/models/spree/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,6 @@ def self.like_any(fields, values)
where conditions.inject(:or)
end

def self.search_by_name(query)
if defined?(SpreeGlobalize)
joins(:translations).order(:name).where("LOWER(#{Product::Translation.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%").distinct
else
where("LOWER(#{Product.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%")
end
end

# Suitable for displaying only variants that has at least one option value.
# There may be scenarios where an option type is removed and along with it
# all option values. At that point all variants associated with only those
Expand Down
36 changes: 24 additions & 12 deletions core/spec/models/spree/product/scopes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -237,22 +237,34 @@
let!(:second_product) { create(:product, name: 'Second product',stores: [store]) }
let!(:third_product) { create(:product, name: 'Other second product',stores: [store]) }

it 'shows product whose name contains phrase' do
result = Spree::Product.search_by_name('First').to_a
expect(result).to include(first_product)
expect(result.count).to eq(1)
shared_examples 'valid products returned' do
it 'shows product whose name contains phrase' do
result = Spree::Product.search_by_name('First').to_a
expect(result).to include(first_product)
expect(result.count).to eq(1)
end

it 'shows multiple products whose names contain phrase' do
result = Spree::Product.search_by_name('product').to_a
expect(result).to include(product, first_product, second_product, third_product)
expect(result.count).to eq(4)
end

it 'is case insensitive for search phrases' do
result = Spree::Product.search_by_name('Second').to_a
expect(result).to include(second_product, third_product)
expect(result.count).to eq(2)
end
end

it 'shows multiple products whose names contain phrase' do
result = Spree::Product.search_by_name('product').to_a
expect(result).to include(product, first_product, second_product, third_product)
expect(result.count).to eq(4)
context 'when pg_search gem is installed' do
it_behaves_like 'valid products returned'
end

it 'is case insensitive for search phrases' do
result = Spree::Product.search_by_name('Second').to_a
expect(result).to include(second_product, third_product)
expect(result.count).to eq(2)
context 'when pg_search gem is not installed' do
before { }

it_behaves_like 'valid products returned'
damianlegawiec marked this conversation as resolved.
Show resolved Hide resolved
end
end

Expand Down