Skip to content
Snippets Groups Projects
Commit d32aec06 authored by Hiroyuki Sato's avatar Hiroyuki Sato
Browse files

Add 'in' filter that modifies scope of 'search' filter to issues and merge requests API

parent 1161c99e
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -18,6 +18,7 @@
# assignee_id: integer or 'None' or 'Any'
# assignee_username: string
# search: string
# in: 'title', 'description' or a string joined them with comma
# label_name: string
# sort: string
# non_archived: boolean
Loading
Loading
@@ -56,6 +57,7 @@ class IssuableFinder
milestone_title
my_reaction_emoji
search
in
]
end
 
Loading
Loading
@@ -408,7 +410,7 @@ class IssuableFinder
items = klass.with(cte.to_arel).from(klass.table_name)
end
 
items.full_search(search)
items.full_search(search, matched_columns: params[:in])
end
# rubocop: enable CodeReuse/ActiveRecord
 
Loading
Loading
Loading
Loading
@@ -14,6 +14,7 @@
# milestone_title: string
# assignee_id: integer
# search: string
# in: 'title', 'description' or a string joined them with comma
# label_name: string
# sort: string
# my_reaction_emoji: string
Loading
Loading
Loading
Loading
@@ -15,6 +15,7 @@
# author_id: integer
# assignee_id: integer
# search: string
# in: 'title', 'description' or a string joined them with comma
# label_name: string
# sort: string
# non_archived: boolean
Loading
Loading
Loading
Loading
@@ -136,10 +136,18 @@ module Issuable
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
# query - The search query as a String
# matched_columns - Modify the scope of the query. 'title', 'description' or joining them with a comma.
#
# Returns an ActiveRecord::Relation.
def full_search(query)
fuzzy_search(query, [:title, :description])
def full_search(query, matched_columns: 'title,description')
allowed_columns = [:title, :description]
matched_columns = matched_columns.to_s.split(',').map(&:to_sym)
matched_columns &= allowed_columns
# Matching title or description if the matched_columns did not contain any allowed columns.
matched_columns = [:title, :description] if matched_columns.empty?
fuzzy_search(query, matched_columns)
end
 
def sort_by_attribute(method, excluded_labels: [])
Loading
Loading
---
title: Add 'in' filter that modifies scope of 'search' filter to issues and merge requests API
merge_request: 24350
author: Hiroyuki Sato
type: added
Loading
Loading
@@ -31,6 +31,7 @@ GET /issues?iids[]=42&iids[]=43
GET /issues?author_id=5
GET /issues?assignee_id=5
GET /issues?my_reaction_emoji=star
GET /issues?search=foo&in=title
```
 
| Attribute | Type | Required | Description |
Loading
Loading
@@ -46,6 +47,7 @@ GET /issues?my_reaction_emoji=star
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search issues against their `title` and `description` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joined them with comma. Default is `title,description` |
| `created_after` | datetime | no | Return issues created on or after the given time |
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
Loading
Loading
Loading
Loading
@@ -24,6 +24,7 @@ GET /merge_requests?labels=bug,reproduced
GET /merge_requests?author_id=5
GET /merge_requests?my_reaction_emoji=star
GET /merge_requests?scope=assigned_to_me
GET /merge_requests?search=foo&in=title
```
 
Parameters:
Loading
Loading
@@ -47,6 +48,7 @@ Parameters:
| `source_branch` | string | no | Return merge requests with the given source branch |
| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joined them with comma. Default is `title,description` |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
 
```json
Loading
Loading
Loading
Loading
@@ -43,7 +43,8 @@ module API
desc: 'Return issues sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return issues for a specific milestone'
optional :iids, type: Array[Integer], desc: 'The IID array of issues'
optional :search, type: String, desc: 'Search issues for text present in the title or description'
optional :search, type: String, desc: 'Search issues for text present in the title, description or any combination of these'
optional :in, type: String, desc: '`title`, `description` or a string joined them with comma'
optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
Loading
Loading
Loading
Loading
@@ -109,7 +109,8 @@ module API
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :source_branch, type: String, desc: 'Return merge requests with the given source branch'
optional :target_branch, type: String, desc: 'Return merge requests with the given target branch'
optional :search, type: String, desc: 'Search merge requests for text present in the title or description'
optional :search, type: String, desc: 'Search merge requests for text present in the title, description or any combination of these'
optional :in, type: String, desc: '`title`, `description` or a string joined them with comma'
optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
use :pagination
end
Loading
Loading
Loading
Loading
@@ -314,6 +314,14 @@ describe IssuesFinder do
end
end
 
context 'filtering by issue term in title' do
let(:params) { { search: 'git', in: 'title' } }
it 'returns issues with title match for search term' do
expect(issues).to contain_exactly(issue1)
end
end
context 'filtering by issues iids' do
let(:params) { { iids: issue3.iid } }
 
Loading
Loading
Loading
Loading
@@ -139,6 +139,78 @@ describe Issuable do
it 'returns issues with a matching description for a query shorter than 3 chars' do
expect(issuable_class.full_search(searchable_issue2.description.downcase)).to eq([searchable_issue2])
end
context 'when mathing columns is "title"' do
it 'returns issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title'))
.to eq([searchable_issue])
end
it 'returns no issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title'))
.to be_empty
end
end
context 'when mathing columns is "description"' do
it 'returns no issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'description'))
.to be_empty
end
it 'returns issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'description'))
.to eq([searchable_issue])
end
end
context 'when mathing columns is "title,description"' do
it 'returns issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title,description'))
.to eq([searchable_issue])
end
it 'returns issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title,description'))
.to eq([searchable_issue])
end
end
context 'when mathing columns is nil"' do
it 'returns issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: nil))
.to eq([searchable_issue])
end
it 'returns issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: nil))
.to eq([searchable_issue])
end
end
context 'when mathing columns is "invalid"' do
it 'returns issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'invalid'))
.to eq([searchable_issue])
end
it 'returns issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'invalid'))
.to eq([searchable_issue])
end
end
context 'when mathing columns is "title,invalid"' do
it 'returns issues with a matching title' do
expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title,invalid'))
.to eq([searchable_issue])
end
it 'returns no issues with a matching description' do
expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title,invalid'))
.to be_empty
end
end
end
 
describe '.to_ability_name' do
Loading
Loading
Loading
Loading
@@ -208,6 +208,18 @@ describe API::Issues do
expect_paginated_array_response(issue.id)
end
 
it 'returns issues matching given search string for title and scoped in title' do
get api("/issues", user), params: { search: issue.title, in: 'title' }
expect_paginated_array_response(issue.id)
end
it 'returns an empty array if no issue matches given search string for title and scoped in description' do
get api("/issues", user), params: { search: issue.title, in: 'description' }
expect_paginated_array_response([])
end
it 'returns issues matching given search string for description' do
get api("/issues", user), params: { search: issue.description }
 
Loading
Loading
Loading
Loading
@@ -260,6 +260,18 @@ describe API::MergeRequests do
expect_response_ordered_exactly(merge_request)
end
 
it 'returns merge requests matching given search string for title and scoped in title' do
get api("/merge_requests", user), params: { search: merge_request.title, in: 'title' }
expect_response_ordered_exactly(merge_request)
end
it 'returns an empty array if no merge reques matches given search string for description and scoped in title' do
get api("/merge_requests", user), params: { search: merge_request.description, in: 'title' }
expect_response_contain_exactly
end
it 'returns merge requests for project matching given search string for description' do
get api("/merge_requests", user), params: { project_id: project.id, search: merge_request.description }
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment