Commit d50ec8bd authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '258215-improve-fuzzy-search-on-full-path-in-groups' into 'master'

Fix problem with Groups API search argument

See merge request gitlab-org/gitlab!46394
parents 0c711543 cb230357
...@@ -119,7 +119,7 @@ class Namespace < ApplicationRecord ...@@ -119,7 +119,7 @@ class Namespace < ApplicationRecord
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def search(query, include_parents: false) def search(query, include_parents: false)
if include_parents if include_parents
where(id: Route.fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name]]).select(:source_id)) where(id: Route.for_routable_type(Namespace.name).fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name]]).select(:source_id))
else else
fuzzy_search(query, [:path, :name]) fuzzy_search(query, [:path, :name])
end end
......
...@@ -20,6 +20,7 @@ class Route < ApplicationRecord ...@@ -20,6 +20,7 @@ class Route < ApplicationRecord
scope :inside_path, -> (path) { where('routes.path LIKE ?', "#{sanitize_sql_like(path)}/%") } scope :inside_path, -> (path) { where('routes.path LIKE ?', "#{sanitize_sql_like(path)}/%") }
scope :for_routable, -> (routable) { where(source: routable) } scope :for_routable, -> (routable) { where(source: routable) }
scope :for_routable_type, -> (routable_type) { where(source_type: routable_type) }
scope :sort_by_path_length, -> { order('LENGTH(routes.path)', :path) } scope :sort_by_path_length, -> { order('LENGTH(routes.path)', :path) }
def rename_descendants def rename_descendants
......
---
title: Fix problems with Groups API search query parameter
merge_request: 46394
author:
type: fixed
...@@ -147,42 +147,45 @@ RSpec.describe Namespace do ...@@ -147,42 +147,45 @@ RSpec.describe Namespace do
end end
describe '.search' do describe '.search' do
let_it_be(:namespace) { create(:namespace) } let_it_be(:first_namespace) { build(:namespace, name: 'my first namespace', path: 'old-path').tap(&:save!) }
let_it_be(:parent_namespace) { build(:namespace, name: 'my parent namespace', path: 'parent-path').tap(&:save!) }
let_it_be(:second_namespace) { build(:namespace, name: 'my second namespace', path: 'new-path', parent: parent_namespace).tap(&:save!) }
let_it_be(:project_with_same_path) { create(:project, id: second_namespace.id, path: first_namespace.path) }
it 'returns namespaces with a matching name' do it 'returns namespaces with a matching name' do
expect(described_class.search(namespace.name)).to eq([namespace]) expect(described_class.search('my first namespace')).to eq([first_namespace])
end end
it 'returns namespaces with a partially matching name' do it 'returns namespaces with a partially matching name' do
expect(described_class.search(namespace.name[0..2])).to eq([namespace]) expect(described_class.search('first')).to eq([first_namespace])
end end
it 'returns namespaces with a matching name regardless of the casing' do it 'returns namespaces with a matching name regardless of the casing' do
expect(described_class.search(namespace.name.upcase)).to eq([namespace]) expect(described_class.search('MY FIRST NAMESPACE')).to eq([first_namespace])
end end
it 'returns namespaces with a matching path' do it 'returns namespaces with a matching path' do
expect(described_class.search(namespace.path)).to eq([namespace]) expect(described_class.search('old-path')).to eq([first_namespace])
end end
it 'returns namespaces with a partially matching path' do it 'returns namespaces with a partially matching path' do
expect(described_class.search(namespace.path[0..2])).to eq([namespace]) expect(described_class.search('old')).to eq([first_namespace])
end end
it 'returns namespaces with a matching path regardless of the casing' do it 'returns namespaces with a matching path regardless of the casing' do
expect(described_class.search(namespace.path.upcase)).to eq([namespace]) expect(described_class.search('OLD-PATH')).to eq([first_namespace])
end end
it 'returns namespaces with a matching route path' do it 'returns namespaces with a matching route path' do
expect(described_class.search(namespace.route.path, include_parents: true)).to eq([namespace]) expect(described_class.search('parent-path/new-path', include_parents: true)).to eq([second_namespace])
end end
it 'returns namespaces with a partially matching route path' do it 'returns namespaces with a partially matching route path' do
expect(described_class.search(namespace.route.path[0..2], include_parents: true)).to eq([namespace]) expect(described_class.search('parent-path/new', include_parents: true)).to eq([second_namespace])
end end
it 'returns namespaces with a matching route path regardless of the casing' do it 'returns namespaces with a matching route path regardless of the casing' do
expect(described_class.search(namespace.route.path.upcase, include_parents: true)).to eq([namespace]) expect(described_class.search('PARENT-PATH/NEW-PATH', include_parents: true)).to eq([second_namespace])
end end
end end
......
...@@ -62,6 +62,15 @@ RSpec.describe Route do ...@@ -62,6 +62,15 @@ RSpec.describe Route do
end end
end end
describe '.for_routable_type' do
let!(:nested_group) { create(:group, path: 'foo', name: 'foo', parent: group) }
let!(:project) { create(:project, path: 'other-project') }
it 'returns correct routes' do
expect(described_class.for_routable_type(Project.name)).to match_array([project.route])
end
end
describe '#rename_descendants' do describe '#rename_descendants' do
let!(:nested_group) { create(:group, path: 'test', name: 'test', parent: group) } let!(:nested_group) { create(:group, path: 'test', name: 'test', parent: group) }
let!(:deep_nested_group) { create(:group, path: 'foo', name: 'foo', parent: nested_group) } let!(:deep_nested_group) { create(:group, path: 'foo', name: 'foo', parent: nested_group) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment