Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-02-25 21:15:08 +0400
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-02-25 21:15:08 +0400
commit645e8d470559b07a22164c55b76195a60fb8b37b (patch)
treed77b7a795c0bf503586e1e704064432e2df96c0b /app/finders
parent0f473674920dfc6759ddf131b32eb0b4b06256d0 (diff)
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.md24
-rw-r--r--app/finders/base_finder.rb137
-rw-r--r--app/finders/issues_finder.rb22
-rw-r--r--app/finders/merge_requests_finder.rb22
-rw-r--r--app/finders/notes_finder.rb17
-rw-r--r--app/finders/projects_finder.rb63
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