Skip to content
Snippets Groups Projects
Verified Commit 645e8d47 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets
Browse files

Move services for collecting items to Finders

parent 0f473674
No related branches found
No related tags found
No related merge requests found
Showing
with 163 additions and 105 deletions
Loading
Loading
@@ -53,13 +53,13 @@ class DashboardController < ApplicationController
end
 
def merge_requests
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = MergeRequestsFinder.new.execute(current_user, params)
@merge_requests = @merge_requests.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project)
end
 
def issues
@issues = FilteringService.new.execute(Issue, current_user, params)
@issues = IssuesFinder.new.execute(current_user, params)
@issues = @issues.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project)
 
Loading
Loading
Loading
Loading
@@ -47,13 +47,13 @@ class GroupsController < ApplicationController
end
 
def merge_requests
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = MergeRequestsFinder.new.execute(current_user, params)
@merge_requests = @merge_requests.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project)
end
 
def issues
@issues = FilteringService.new.execute(Issue, current_user, params)
@issues = IssuesFinder.new.execute(current_user, params)
@issues = @issues.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project)
 
Loading
Loading
@@ -100,7 +100,7 @@ class GroupsController < ApplicationController
end
 
def projects
@projects ||= Projects::CollectService.new.execute(current_user, group: group)
@projects ||= ProjectsFinder.new.execute(current_user, group: group)
end
 
def project_ids
Loading
Loading
Loading
Loading
@@ -121,7 +121,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issues_filtered
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@issues = FilteringService.new.execute(Issue, current_user, params.merge(project_id: @project.id))
@issues = IssuesFinder.new.execute(current_user, params.merge(project_id: @project.id))
end
 
# Since iids are implemented only in 6.1
Loading
Loading
Loading
Loading
@@ -21,7 +21,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
 
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params.merge(project_id: @project.id))
@merge_requests = MergeRequestsFinder.new.execute(current_user, params.merge(project_id: @project.id))
@merge_requests = @merge_requests.page(params[:page]).per(20)
 
@sort = params[:sort].humanize
Loading
Loading
Loading
Loading
@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController
before_filter :authorize_admin_note!, only: [:update, :destroy]
 
def index
@notes = Notes::LoadService.new(project, current_user, params).execute
@notes = NotesFinder.new.execute(project, current_user, params)
 
notes_json = { notes: [] }
 
Loading
Loading
# Finders
This type of classes responsible for collectiong items based on different conditions.
To prevent lookup methods in models like this:
```
class Project
def issues_for_user_filtered_by(user, filter)
# A lot of logic not related to project model itself
end
end
issues = project.issues_for_user_filtered_by(user, params)
```
Better use this:
```
selector = Finders::Issues.new
issues = selector.execute(project, user, filter)
```
It will help keep models thiner
# FilteringService class
# BaseFinder
#
# Used to filter Issues and MergeRequests collections by set of params
#
Loading
Loading
@@ -16,11 +16,10 @@
# label_name: string
# sort: string
#
class FilteringService
attr_accessor :klass, :current_user, :params
class BaseFinder
attr_accessor :current_user, :params
 
def execute(klass, current_user, params)
@klass = klass
def execute(current_user, params)
@current_user = current_user
@params = params
 
Loading
Loading
# Finders::Issues class
#
# Used to filter Issues collections by set of params
#
# Arguments:
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# state: 'open' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_id: integer
# assignee_id: integer
# search: string
# label_name: string
# sort: string
#
class IssuesFinder < BaseFinder
def klass
Issue
end
end
# Finders::MergeRequest class
#
# Used to filter MergeRequests collections by set of params
#
# Arguments:
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# state: 'open' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_id: integer
# assignee_id: integer
# search: string
# label_name: string
# sort: string
#
class MergeRequestsFinder < BaseFinder
def klass
MergeRequest
end
end
class NotesFinder
def execute(project, current_user, params)
target_type = params[:target_type]
target_id = params[:target_id]
case target_type
when "commit"
project.notes.for_commit_id(target_id).not_inline.fresh
when "issue"
project.issues.find(target_id).notes.inc_author.fresh
when "merge_request"
project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh
when "snippet"
project.snippets.find(target_id).notes.fresh
end
end
end
class ProjectsFinder
def execute(current_user, options)
group = options[:group]
if group
group_projects(current_user, group)
else
all_projects(current_user)
end
end
private
def group_projects(current_user, group)
if current_user
if group.users.include?(current_user)
# User is group member
#
# Return ALL group projects
group.projects
else
projects_members = UsersProject.where(
project_id: group.projects,
user_id: current_user
)
if projects_members.any?
# User is a project member
#
# Return only:
# public projects
# internal projects
# joined projects
#
group.projects.where(
"projects.id IN (?) OR projects.visibility_level IN (?)",
projects_members.pluck(:project_id),
Project.public_and_internal_levels
)
else
# User has no access to group or group projects
#
# Return only:
# public projects
# internal projects
#
group.projects.public_and_internal_only
end
end
else
# Not authenticated
#
# Return only:
# public projects
group.projects.public_only
end
end
def all_projects
# TODO: implement
raise 'Not implemented yet'
end
end
Loading
Loading
@@ -184,7 +184,7 @@ class Ability
def group_abilities user, group
rules = []
 
if user.admin? || group.users.include?(user) || Projects::CollectService.new.execute(user, group: group).any?
if user.admin? || group.users.include?(user) || ProjectsFinder.new.execute(user, group: group).any?
rules << :read_group
end
 
Loading
Loading
module Notes
class LoadService < BaseService
def execute
target_type = params[:target_type]
target_id = params[:target_id]
@notes = case target_type
when "commit"
project.notes.for_commit_id(target_id).not_inline.fresh
when "issue"
project.issues.find(target_id).notes.inc_author.fresh
when "merge_request"
project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh
when "snippet"
project.snippets.find(target_id).notes.fresh
end
end
end
end
# Projects::CollectService class
#
# Used to collect projects user has access to
#
module Projects
class CollectService
def execute(current_user, options)
group = options[:group]
if group
group_projects(current_user, group)
else
all_projects(current_user)
end
end
private
def group_projects(current_user, group)
if current_user
if group.users.include?(current_user)
# User is group member
#
# Return ALL group projects
group.projects
else
projects_members = UsersProject.where(
project_id: group.projects,
user_id: current_user
)
if projects_members.any?
# User is a project member
#
# Return only:
# public projects
# internal projects
# joined projects
#
group.projects.where(
"projects.id IN (?) OR projects.visibility_level IN (?)",
projects_members.pluck(:project_id),
Project.public_and_internal_levels
)
else
# User has no access to group or group projects
#
# Return only:
# public projects
# internal projects
#
group.projects.public_and_internal_only
end
end
else
# Not authenticated
#
# Return only:
# public projects
group.projects.public_only
end
end
end
def all_projects
# TODO: implement
raise 'Not implemented yet'
end
end
Loading
Loading
@@ -12,7 +12,7 @@ module Gitlab
# -- all .rb files in that directory are automatically loaded.
 
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib #{config.root}/app/models/concerns #{config.root}/app/models/project_services)
config.autoload_paths += %W(#{config.root}/lib #{config.root}/app/finders #{config.root}/app/models/concerns #{config.root}/app/models/project_services)
 
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
Loading
Loading
@@ -64,7 +64,7 @@ module Gitlab
config.assets.enabled = true
config.assets.paths << Emoji.images_path
config.assets.precompile << "emoji/*.png"
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
 
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