Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
5ea4e34f
Commit
5ea4e34f
authored
Mar 09, 2017
by
Alexis Reigel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add method to get a full routable hierarchy
parent
b7ca7330
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
160 additions
and
1 deletion
+160
-1
app/models/concerns/routable.rb
app/models/concerns/routable.rb
+68
-0
spec/models/concerns/routable_spec.rb
spec/models/concerns/routable_spec.rb
+92
-1
No files found.
app/models/concerns/routable.rb
View file @
5ea4e34f
...
...
@@ -83,6 +83,74 @@ module Routable
AND members.source_type = r2.source_type"
).
where
(
'members.user_id = ?'
,
user_id
)
end
# Builds a relation to find multiple objects that are nested under user
# membership. Includes the parent, as opposed to `#member_descendants`
# which only includes the descendants.
#
# Usage:
#
# Klass.member_self_and_descendants(1)
#
# Returns an ActiveRecord::Relation.
def
member_self_and_descendants
(
user_id
)
joins
(
:route
).
joins
(
"INNER JOIN routes r2 ON routes.path LIKE CONCAT(r2.path, '/%')
OR routes.path = r2.path
INNER JOIN members ON members.source_id = r2.source_id
AND members.source_type = r2.source_type"
).
where
(
'members.user_id = ?'
,
user_id
)
end
# Returns all objects in a hierarchy, where any node in the hierarchy is
# under the user membership.
#
# Usage:
#
# Klass.member_hierarchy(1)
#
# Examples:
#
# Given the following group tree...
#
# _______group_1_______
# | |
# | |
# nested_group_1 nested_group_2
# | |
# | |
# nested_group_1_1 nested_group_2_1
#
#
# ... the following results are returned:
#
# * the user is a member of group 1
# => 'group_1',
# 'nested_group_1', nested_group_1_1',
# 'nested_group_2', 'nested_group_2_1'
#
# * the user is a member of nested_group_2
# => 'group1',
# 'nested_group_2', 'nested_group_2_1'
#
# * the user is a member of nested_group_2_1
# => 'group1',
# 'nested_group_2', 'nested_group_2_1'
#
# Returns an ActiveRecord::Relation.
def
member_hierarchy
(
user_id
)
paths
=
member_self_and_descendants
(
user_id
).
pluck
(
'routes.path'
)
return
none
if
paths
.
empty?
leaf_paths
=
paths
.
group_by
(
&
:length
).
flat_map
(
&
:last
)
wheres
=
leaf_paths
.
map
do
|
leaf_path
|
"
#{
connection
.
quote
(
leaf_path
)
}
LIKE CONCAT(routes.path, '%')"
end
joins
(
:route
).
where
(
wheres
.
join
(
' OR '
))
end
end
def
full_name
...
...
spec/models/concerns/routable_spec.rb
View file @
5ea4e34f
require
'spec_helper'
describe
Group
,
'Routable'
do
let!
(
:group
)
{
create
(
:group
)
}
let!
(
:group
)
{
create
(
:group
,
name:
'group 1'
)
}
describe
'Validations'
do
it
{
is_expected
.
to
validate_presence_of
(
:route
)
}
...
...
@@ -81,6 +81,97 @@ describe Group, 'Routable' do
it
{
is_expected
.
to
eq
([
nested_group
])
}
end
describe
'.member_self_and_descendants'
do
let!
(
:user
)
{
create
(
:user
)
}
let!
(
:nested_group
)
{
create
(
:group
,
parent:
group
)
}
before
{
group
.
add_owner
(
user
)
}
subject
{
described_class
.
member_self_and_descendants
(
user
.
id
)
}
it
{
is_expected
.
to
match_array
[
group
,
nested_group
]
}
end
describe
'.member_hierarchy'
do
let!
(
:user
)
{
create
(
:user
)
}
# _______ group _______
# | |
# | |
# nested_group_1 nested_group_2
# | |
# | |
# nested_group_1_1 nested_group_2_1
#
let!
(
:nested_group_1
)
{
create
:group
,
parent:
group
,
name:
'group 1-1'
}
let!
(
:nested_group_1_1
)
{
create
:group
,
parent:
nested_group_1
,
name:
'group 1-1-1'
}
let!
(
:nested_group_2
)
{
create
:group
,
parent:
group
,
name:
'group 1-2'
}
let!
(
:nested_group_2_1
)
{
create
:group
,
parent:
nested_group_2
,
name:
'group 1-2-1'
}
context
'user is not a member of any group'
do
subject
{
described_class
.
member_hierarchy
(
user
.
id
)
}
it
'returns an empty array'
do
is_expected
.
to
eq
[]
end
end
context
'user is member of all groups'
do
before
do
group
.
add_owner
(
user
)
nested_group_1
.
add_owner
(
user
)
nested_group_1_1
.
add_owner
(
user
)
nested_group_2
.
add_owner
(
user
)
nested_group_2_1
.
add_owner
(
user
)
end
subject
{
described_class
.
member_hierarchy
(
user
.
id
)
}
it
'returns all groups'
do
is_expected
.
to
match_array
[
group
,
nested_group_1
,
nested_group_1_1
,
nested_group_2
,
nested_group_2_1
]
end
end
context
'user is member of the top group'
do
before
{
group
.
add_owner
(
user
)
}
subject
{
described_class
.
member_hierarchy
(
user
.
id
)
}
it
'returns all groups'
do
is_expected
.
to
match_array
[
group
,
nested_group_1
,
nested_group_1_1
,
nested_group_2
,
nested_group_2_1
]
end
end
context
'user is member of the first child (internal node)'
do
before
{
nested_group_1
.
add_owner
(
user
)
}
subject
{
described_class
.
member_hierarchy
(
user
.
id
)
}
it
'returns the groups in the hierarchy'
do
is_expected
.
to
match_array
[
group
,
nested_group_1
,
nested_group_1_1
]
end
end
context
'user is member of the last child (leaf node)'
do
before
{
nested_group_1_1
.
add_owner
(
user
)
}
subject
{
described_class
.
member_hierarchy
(
user
.
id
)
}
it
'returns the groups in the hierarchy'
do
is_expected
.
to
match_array
[
group
,
nested_group_1
,
nested_group_1_1
]
end
end
end
describe
'#full_path'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:nested_group
)
{
create
(
:group
,
parent:
group
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment