diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2014-02-25 19:15:08 +0200 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2014-02-25 19:15:08 +0200 |
commit | 645e8d470559b07a22164c55b76195a60fb8b37b (patch) | |
tree | d77b7a795c0bf503586e1e704064432e2df96c0b /app/finders | |
parent | 0f473674920dfc6759ddf131b32eb0b4b06256d0 (diff) | |
download | gitlab-ce-645e8d470559b07a22164c55b76195a60fb8b37b.tar.gz |
Move services for collecting items to Finders
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Diffstat (limited to 'app/finders')
-rw-r--r-- | app/finders/README.md | 24 | ||||
-rw-r--r-- | app/finders/base_finder.rb | 137 | ||||
-rw-r--r-- | app/finders/issues_finder.rb | 22 | ||||
-rw-r--r-- | app/finders/merge_requests_finder.rb | 22 | ||||
-rw-r--r-- | app/finders/notes_finder.rb | 17 | ||||
-rw-r--r-- | app/finders/projects_finder.rb | 63 |
6 files changed, 285 insertions, 0 deletions
diff --git a/app/finders/README.md b/app/finders/README.md new file mode 100644 index 00000000000..6fbf0e2f4c1 --- /dev/null +++ b/app/finders/README.md @@ -0,0 +1,24 @@ +# 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 diff --git a/app/finders/base_finder.rb b/app/finders/base_finder.rb new file mode 100644 index 00000000000..d20716fb170 --- /dev/null +++ b/app/finders/base_finder.rb @@ -0,0 +1,137 @@ +# BaseFinder +# +# Used to filter Issues and MergeRequests collections by set of params +# +# 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: '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 BaseFinder + attr_accessor :current_user, :params + + def execute(current_user, params) + @current_user = current_user + @params = params + + items = init_collection + items = by_scope(items) + items = by_state(items) + items = by_group(items) + items = by_project(items) + items = by_search(items) + items = by_milestone(items) + items = by_assignee(items) + items = by_label(items) + items = sort(items) + end + + private + + def init_collection + table_name = klass.table_name + + if project + if project.public? || (current_user && current_user.can?(:read_project, project)) + project.send(table_name) + else + [] + end + elsif current_user && params[:authorized_only].presence + klass.of_projects(current_user.authorized_projects) + else + klass.of_projects(Project.accessible_to(current_user)) + end + end + + def by_scope(items) + case params[:scope] + when 'created-by-me', 'authored' then + items.where(author_id: current_user.id) + when 'all' then + items + when 'assigned-to-me' then + items.where(assignee_id: current_user.id) + else + raise 'You must specify default scope' + end + end + + def by_state(items) + case params[:state] + when 'closed' + items.closed + when 'all' + items + when 'opened' + items.opened + else + raise 'You must specify default state' + end + end + + def by_group(items) + if params[:group_id].present? + items = items.of_group(Group.find(params[:group_id])) + end + + items + end + + def by_project(items) + if params[:project_id].present? + items = items.of_projects(params[:project_id]) + end + + items + end + + def by_search(items) + if params[:search].present? + items = items.search(params[:search]) + end + + items + end + + def sort(items) + items.sort(params[:sort]) + end + + def by_milestone(items) + if params[:milestone_id].present? + items = items.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id])) + end + + items + end + + def by_assignee(items) + if params[:assignee_id].present? + items = items.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id])) + end + + items + end + + def by_label(items) + if params[:label_name].present? + items = items.tagged_with(params[:label_name]) + end + + items + end + + def project + Project.where(id: params[:project_id]).first if params[:project_id].present? + end +end diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb new file mode 100644 index 00000000000..8e0c606249e --- /dev/null +++ b/app/finders/issues_finder.rb @@ -0,0 +1,22 @@ +# 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 diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb new file mode 100644 index 00000000000..3727149c8fb --- /dev/null +++ b/app/finders/merge_requests_finder.rb @@ -0,0 +1,22 @@ +# 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 diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb new file mode 100644 index 00000000000..384316e14b7 --- /dev/null +++ b/app/finders/notes_finder.rb @@ -0,0 +1,17 @@ +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 diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb new file mode 100644 index 00000000000..bfaba758788 --- /dev/null +++ b/app/finders/projects_finder.rb @@ -0,0 +1,63 @@ +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 |