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
@@ -53,13 +53,13 @@ class DashboardController < ApplicationController
Loading
@@ -53,13 +53,13 @@ class DashboardController < ApplicationController
end end
   
def merge_requests 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.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project) @merge_requests = @merge_requests.preload(:author, :target_project)
end end
   
def issues 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.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project) @issues = @issues.preload(:author, :project)
   
Loading
Loading
Loading
@@ -47,13 +47,13 @@ class GroupsController < ApplicationController
Loading
@@ -47,13 +47,13 @@ class GroupsController < ApplicationController
end end
   
def merge_requests 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.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project) @merge_requests = @merge_requests.preload(:author, :target_project)
end end
   
def issues 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.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project) @issues = @issues.preload(:author, :project)
   
Loading
@@ -100,7 +100,7 @@ class GroupsController < ApplicationController
Loading
@@ -100,7 +100,7 @@ class GroupsController < ApplicationController
end end
   
def projects def projects
@projects ||= Projects::CollectService.new.execute(current_user, group: group) @projects ||= ProjectsFinder.new.execute(current_user, group: group)
end end
   
def project_ids def project_ids
Loading
Loading
Loading
@@ -121,7 +121,7 @@ class Projects::IssuesController < Projects::ApplicationController
Loading
@@ -121,7 +121,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issues_filtered def issues_filtered
params[:scope] = 'all' if params[:scope].blank? params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].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 end
   
# Since iids are implemented only in 6.1 # Since iids are implemented only in 6.1
Loading
Loading
Loading
@@ -21,7 +21,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
Loading
@@ -21,7 +21,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params[:scope] = 'all' if params[:scope].blank? params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].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) @merge_requests = @merge_requests.page(params[:page]).per(20)
   
@sort = params[:sort].humanize @sort = params[:sort].humanize
Loading
Loading
Loading
@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController
Loading
@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController
before_filter :authorize_admin_note!, only: [:update, :destroy] before_filter :authorize_admin_note!, only: [:update, :destroy]
   
def index def index
@notes = Notes::LoadService.new(project, current_user, params).execute @notes = NotesFinder.new.execute(project, current_user, params)
   
notes_json = { notes: [] } 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 # Used to filter Issues and MergeRequests collections by set of params
# #
Loading
@@ -16,11 +16,10 @@
Loading
@@ -16,11 +16,10 @@
# label_name: string # label_name: string
# sort: string # sort: string
# #
class FilteringService class BaseFinder
attr_accessor :klass, :current_user, :params attr_accessor :current_user, :params
   
def execute(klass, current_user, params) def execute(current_user, params)
@klass = klass
@current_user = current_user @current_user = current_user
@params = params @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
@@ -184,7 +184,7 @@ class Ability
Loading
@@ -184,7 +184,7 @@ class Ability
def group_abilities user, group def group_abilities user, group
rules = [] 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 rules << :read_group
end 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
@@ -12,7 +12,7 @@ module Gitlab
Loading
@@ -12,7 +12,7 @@ module Gitlab
# -- all .rb files in that directory are automatically loaded. # -- all .rb files in that directory are automatically loaded.
   
# Custom directories with classes and modules you want to be autoloadable. # 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). # 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. # :all can be used as a placeholder for all plugins not explicitly named.
Loading
@@ -64,7 +64,7 @@ module Gitlab
Loading
@@ -64,7 +64,7 @@ module Gitlab
config.assets.enabled = true config.assets.enabled = true
config.assets.paths << Emoji.images_path config.assets.paths << Emoji.images_path
config.assets.precompile << "emoji/*.png" config.assets.precompile << "emoji/*.png"
# Version of your assets, change this if you want to expire all your assets # Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0' 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