diff options
author | Rémy Coutable <remy@rymai.me> | 2019-01-17 18:49:07 +0100 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2019-02-21 09:40:49 +0100 |
commit | f0a2c4116c862fdfa26015aa1a964714d41855e5 (patch) | |
tree | db14699d5e22b49dcc49792cb637cd65003b57a7 | |
parent | deca66884ac3bd77e4adbf50213dc6835285350d (diff) | |
download | gitlab-ce-f0a2c4116c862fdfa26015aa1a964714d41855e5.tar.gz |
Allow IssuableFinder to filter by closed_at
Signed-off-by: Rémy Coutable <remy@rymai.me>
-rw-r--r-- | app/finders/issuable_finder.rb | 8 | ||||
-rw-r--r-- | app/models/concerns/closed_at_filterable.rb | 14 | ||||
-rw-r--r-- | app/models/concerns/issuable.rb | 1 | ||||
-rw-r--r-- | spec/finders/issues_finder_spec.rb | 30 |
4 files changed, 53 insertions, 0 deletions
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 23af2e0521c..5870f158690 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -94,6 +94,7 @@ class IssuableFinder 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_group(items) items = by_assignee(items) @@ -353,6 +354,13 @@ class IssuableFinder items end + def by_closed_at(items) + items = items.closed_after(params[:closed_after]) if params[:closed_after].present? + items = items.closed_before(params[:closed_before]) if params[:closed_before].present? + + items + end + # rubocop: disable CodeReuse/ActiveRecord def by_state(items) case params[:state].to_s diff --git a/app/models/concerns/closed_at_filterable.rb b/app/models/concerns/closed_at_filterable.rb new file mode 100644 index 00000000000..239c2e47611 --- /dev/null +++ b/app/models/concerns/closed_at_filterable.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module ClosedAtFilterable + extend ActiveSupport::Concern + + included do + scope :closed_before, ->(date) { where(scoped_table[:closed_at].lteq(date)) } + scope :closed_after, ->(date) { where(scoped_table[:closed_at].gteq(date)) } + + def self.scoped_table + arel_table.alias(table_name) + end + end +end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 0a77fbeba08..429a63f83cc 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -23,6 +23,7 @@ module Issuable include Sortable include CreatedAtFilterable include UpdatedAtFilterable + include ClosedAtFilterable # This object is used to gather issuable meta data for displaying # upvotes, downvotes, notes and closing merge requests count for issues and merge requests diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 34cb09942be..fe8000e419b 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -416,6 +416,36 @@ describe IssuesFinder do end end + context 'filtering by closed_at' do + let!(:closed_issue1) { create(:issue, project: project1, state: :closed, closed_at: 1.week.ago) } + let!(:closed_issue2) { create(:issue, project: project2, state: :closed, closed_at: 1.week.from_now) } + let!(:closed_issue3) { create(:issue, project: project2, state: :closed, closed_at: 2.weeks.from_now) } + + context 'through closed_after' do + let(:params) { { state: :closed, closed_after: closed_issue3.closed_at } } + + it 'returns issues closed on or after the given date' do + expect(issues).to contain_exactly(closed_issue3) + end + end + + context 'through closed_before' do + let(:params) { { state: :closed, closed_before: closed_issue1.closed_at } } + + it 'returns issues closed on or before the given date' do + expect(issues).to contain_exactly(closed_issue1) + end + end + + context 'through closed_after and closed_before' do + let(:params) { { state: :closed, closed_after: closed_issue2.closed_at, closed_before: closed_issue3.closed_at } } + + it 'returns issues closed between the given dates' do + expect(issues).to contain_exactly(closed_issue2, closed_issue3) + end + end + end + context 'filtering by reaction name' do context 'user searches by no reaction' do let(:params) { { my_reaction_emoji: 'None' } } |