Class: IssuableFinder
- Inherits:
-
Object
- Object
- IssuableFinder
- Includes:
- CreatedAtFilter, FinderMethods, FinderWithCrossProjectAccess, Gitlab::Utils::StrongMemoize, UpdatedAtFilter
- Defined in:
- app/finders/issuable_finder.rb,
app/finders/issuable_finder/params.rb
Overview
IssuableFinder
Used to filter Issues and MergeRequests collections by set of params
Note: This class is NOT meant to be instantiated. Instead you should
look at IssuesFinder or EpicsFinder, which inherit from this.
Arguments:
klass - actual class like Issue or MergeRequest
current_user - which user use
params:
scope: 'created_by_me' or 'assigned_to_me' or 'all'
state: 'opened' or 'closed' or 'locked' or 'all'
group_id: integer
project_id: integer
milestone_title: string (cannot be simultaneously used with milestone_wildcard_id)
milestone_wildcard_id: 'none', 'any', 'upcoming', 'started' (cannot be simultaneously used with milestone_title)
release_tag: string
author_id: integer
author_username: string
assignee_id: integer or 'None' or 'Any'
assignee_username: string
search: string
in: 'title', 'description', or a string joining them with comma
label_name: string
sort: string
non_archived: boolean
iids: integer[]
my_reaction_emoji: string
created_after: datetime
created_before: datetime
updated_after: datetime
updated_before: datetime
attempt_group_search_optimizations: boolean
attempt_project_search_optimizations: boolean
crm_contact_id: integer
crm_organization_id: integer
Direct Known Subclasses
Defined Under Namespace
Classes: Params
Constant Summary collapse
- FULL_TEXT_SEARCH_TERM_PATTERN =
'[\u0000-\u02FF\u1E00-\u1EFF\u2070-\u218F]*'
- FULL_TEXT_SEARCH_TERM_REGEX =
/\A#{FULL_TEXT_SEARCH_TERM_PATTERN}\z/
- NEGATABLE_PARAMS_HELPER_KEYS =
%i[project_id scope status include_subgroups].freeze
Instance Attribute Summary collapse
-
#current_user ⇒ Object
Returns the value of attribute current_user.
-
#original_params ⇒ Object
readonly
Returns the value of attribute original_params.
-
#params ⇒ Object
Returns the value of attribute params.
-
#parent ⇒ Object
writeonly
Sets the attribute parent.
Attributes included from FinderWithCrossProjectAccess
#should_skip_cross_project_check
Class Method Summary collapse
- .array_params ⇒ Object
-
.negatable_array_params ⇒ Object
This should not be used in controller strong params!.
-
.negatable_params ⇒ Object
This should not be used in controller strong params!.
-
.negatable_scalar_params ⇒ Object
This should not be used in controller strong params!.
- .scalar_params ⇒ Object
- .valid_params ⇒ Object
Instance Method Summary collapse
-
#count_by_state ⇒ Object
We often get counts for each state by running a query per state, and counting those results.
- #execute ⇒ Object
- #filter_items(items) ⇒ Object
-
#filter_negated_items(items) ⇒ Object
Negates all params found in ‘negatable_params`.
-
#initialize(current_user, params = {}) ⇒ IssuableFinder
constructor
A new instance of IssuableFinder.
- #klass ⇒ Object
- #params_class ⇒ Object
- #parent_param ⇒ Object
- #parent_param=(obj) ⇒ Object
- #row_count ⇒ Object
-
#search ⇒ Object
rubocop: enable CodeReuse/ActiveRecord.
- #should_filter_negated_args? ⇒ Boolean
- #use_cte_for_search? ⇒ Boolean
Methods included from UpdatedAtFilter
Methods included from CreatedAtFilter
Methods included from FinderMethods
Methods included from FinderWithCrossProjectAccess
#can_read_cross_project?, #can_read_project?, #find, #find_by, #find_by!, #skip_cross_project_check
Methods included from Gitlab::Utils::Override
#extended, extensions, #included, #method_added, #override, #prepended, #queue_verification, verify!
Constructor Details
#initialize(current_user, params = {}) ⇒ IssuableFinder
Returns a new instance of IssuableFinder.
110 111 112 113 114 |
# File 'app/finders/issuable_finder.rb', line 110 def initialize(current_user, params = {}) @current_user = current_user @original_params = params @params = params_class.new(params, current_user, klass) end |
Instance Attribute Details
#current_user ⇒ Object
Returns the value of attribute current_user.
54 55 56 |
# File 'app/finders/issuable_finder.rb', line 54 def current_user @current_user end |
#original_params ⇒ Object (readonly)
Returns the value of attribute original_params.
55 56 57 |
# File 'app/finders/issuable_finder.rb', line 55 def original_params @original_params end |
#params ⇒ Object
Returns the value of attribute params.
54 55 56 |
# File 'app/finders/issuable_finder.rb', line 54 def params @params end |
#parent=(value) ⇒ Object
Sets the attribute parent
56 57 58 |
# File 'app/finders/issuable_finder.rb', line 56 def parent=(value) @parent = value end |
Class Method Details
.array_params ⇒ Object
78 79 80 |
# File 'app/finders/issuable_finder.rb', line 78 def array_params @array_params ||= { label_name: [], assignee_username: [] } end |
.negatable_array_params ⇒ Object
This should not be used in controller strong params!
88 89 90 |
# File 'app/finders/issuable_finder.rb', line 88 def negatable_array_params @negatable_array_params ||= array_params.keys.append(:iids) end |
.negatable_params ⇒ Object
This should not be used in controller strong params!
93 94 95 |
# File 'app/finders/issuable_finder.rb', line 93 def negatable_params @negatable_params ||= negatable_scalar_params + negatable_array_params end |
.negatable_scalar_params ⇒ Object
This should not be used in controller strong params!
83 84 85 |
# File 'app/finders/issuable_finder.rb', line 83 def negatable_scalar_params @negatable_scalar_params ||= scalar_params - %i[search in] end |
.scalar_params ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'app/finders/issuable_finder.rb', line 61 def scalar_params @scalar_params ||= %i[ assignee_id assignee_username author_id author_username crm_contact_id crm_organization_id label_name milestone_title release_tag my_reaction_emoji search in ] end |
.valid_params ⇒ Object
97 98 99 |
# File 'app/finders/issuable_finder.rb', line 97 def valid_params @valid_params ||= scalar_params + [array_params.merge(or: {}, not: {})] end |
Instance Method Details
#count_by_state ⇒ Object
We often get counts for each state by running a query per state, and counting those results. This is typically slower than running one query (even if that query is slower than any of the individual state queries) and grouping and counting within that query.
rubocop: disable CodeReuse/ActiveRecord
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'app/finders/issuable_finder.rb', line 178 def count_by_state count_params = params.merge(state: nil, sort: nil, force_cte: true) finder = self.class.new(current_user, count_params) state_counts = finder .execute .reorder(nil) .group(:state_id) .count counts = Hash.new(0) state_counts.each do |key, value| counts[count_key(key)] += value end counts[:all] = counts.values.sum counts.with_indifferent_access end |
#execute ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'app/finders/issuable_finder.rb', line 116 def execute items = init_collection items = filter_items(items) # Let's see if we have to negate anything items = filter_negated_items(items) if should_filter_negated_args? # This has to be last as we use a CTE as an optimization fence # for counts by passing the force_cte param and passing the # attempt_group_search_optimizations param # https://www.postgresql.org/docs/current/static/queries-with.html items = by_search(items) sort(items) end |
#filter_items(items) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'app/finders/issuable_finder.rb', line 132 def filter_items(items) # Selection by group is already covered by `by_project` and `projects` for project-based issuables # Group-based issuables have their own group filter methods items = by_project(items) items = by_scope(items) items = by_created_at(items) items = by_updated_at(items) items = by_closed_at(items) items = by_state(items) items = by_assignee(items) items = (items) items = by_non_archived(items) items = by_iids(items) items = by_milestone(items) items = by_release(items) items = by_label(items) items = by_my_reaction_emoji(items) items = by_crm_contact(items) by_crm_organization(items) end |
#filter_negated_items(items) ⇒ Object
Negates all params found in ‘negatable_params`
159 160 161 162 163 164 |
# File 'app/finders/issuable_finder.rb', line 159 def filter_negated_items(items) items = by_negated_milestone(items) items = by_negated_release(items) items = by_negated_my_reaction_emoji(items) by_negated_iids(items) end |
#klass ⇒ Object
106 107 108 |
# File 'app/finders/issuable_finder.rb', line 106 def klass raise NotImplementedError end |
#params_class ⇒ Object
102 103 104 |
# File 'app/finders/issuable_finder.rb', line 102 def params_class IssuableFinder::Params end |
#parent_param ⇒ Object
217 218 219 220 221 222 223 224 225 226 |
# File 'app/finders/issuable_finder.rb', line 217 def parent_param case parent when Project :project_id when Group :group_id else raise "Unexpected parent: #{parent.class}" end end |
#parent_param=(obj) ⇒ Object
212 213 214 215 |
# File 'app/finders/issuable_finder.rb', line 212 def parent_param=(obj) @parent = obj params[parent_param] = parent if parent end |
#row_count ⇒ Object
166 167 168 169 170 |
# File 'app/finders/issuable_finder.rb', line 166 def row_count Gitlab::IssuablesCountForState .new(self, nil, fast_fail: true) .for_state_or_opened(params[:state]) end |
#search ⇒ Object
rubocop: enable CodeReuse/ActiveRecord
199 200 201 |
# File 'app/finders/issuable_finder.rb', line 199 def search params[:search].presence end |
#should_filter_negated_args? ⇒ Boolean
153 154 155 156 |
# File 'app/finders/issuable_finder.rb', line 153 def should_filter_negated_args? # API endpoints send in `nil` values so we test if there are any non-nil not_params.present? && not_params.values.any? end |
#use_cte_for_search? ⇒ Boolean
203 204 205 206 207 208 209 210 |
# File 'app/finders/issuable_finder.rb', line 203 def use_cte_for_search? strong_memoize(:use_cte_for_search) do next false unless search next false unless default_or_simple_sort? attempt_group_search_optimizations? || attempt_project_search_optimizations? end end |