Skip to content

Commit c138ad2

Browse files
authored
Merge pull request #74 from Exelord/fix-aau-nquery
Fix potential n-query
2 parents a899afc + 5ade373 commit c138ad2

File tree

1 file changed

+39
-9
lines changed

1 file changed

+39
-9
lines changed

lib/monarchy/acts_as_user.rb

+39-9
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def revoke_role!(role_name, resource)
6363
private
6464

6565
def accessible_roles_for(resource, inheritnce)
66-
return Monarchy.role_class.none unless resource.hierarchy
66+
return Monarchy.role_class.none unless resource.persisted?
67+
6768
accessible_roles = if inheritnce
6869
resource_and_inheritance_roles(resource)
6970
else
@@ -75,29 +76,32 @@ def accessible_roles_for(resource, inheritnce)
7576
end
7677

7778
def resource_and_inheritance_roles(resource)
78-
hierarchy_ids = resource.hierarchy.ancestors.select(:id)
79-
8079
Monarchy.role_class.where(id:
8180
Monarchy.role_class
8281
.joins('INNER JOIN monarchy_members_roles ON monarchy_roles.id = monarchy_members_roles.role_id')
8382
.joins("INNER JOIN (SELECT id, hierarchy_id FROM monarchy_members WHERE user_id = #{id}) as " \
8483
'monarchy_members ON monarchy_members.id = monarchy_members_roles.member_id')
8584
.where('monarchy_roles.inherited': 't')
86-
.where('monarchy_members.hierarchy_id': hierarchy_ids)
85+
.where('monarchy_members.hierarchy_id': ancestors_for(resource).select(:id))
8786
.select('monarchy_roles.inherited_role_id'))
8887
.union(resource_roles(resource))
8988
end
9089

9190
def resource_roles(resource)
91+
resource_hierarchy = hierarchies_for(resource).select(:id)
92+
93+
user_memberships = Monarchy.member_class
94+
.where(hierarchy_id: resource_hierarchy, user_id: id)
95+
.select(:id, :hierarchy_id).to_sql
96+
9297
Monarchy.role_class
9398
.joins('INNER JOIN monarchy_members_roles ON monarchy_roles.id = monarchy_members_roles.role_id')
94-
.joins('INNER JOIN (SELECT id, hierarchy_id FROM monarchy_members WHERE ' \
95-
"hierarchy_id = #{resource.hierarchy.id} AND user_id = #{id}) as monarchy_members ON " \
99+
.joins("INNER JOIN (#{user_memberships}) as monarchy_members ON " \
96100
'monarchy_members.id = monarchy_members_roles.member_id')
97101
end
98102

99103
def descendant_role(resource)
100-
descendants = resource.hierarchy.descendants
104+
descendants = descendants_for(resource)
101105
children_access = members_for(descendants).present?
102106

103107
if children_access
@@ -148,12 +152,38 @@ def grant_or_create_member(role_names, resource)
148152
member
149153
end
150154

155+
def inherited_default_role
156+
@inherited_default_role ||= Monarchy.role_class.find_by(name: Monarchy.configuration.inherited_default_role)
157+
end
158+
159+
# TODO: Make these methods public in related interfaces
160+
151161
def members_for(hierarchies)
152162
Monarchy.member_class.where(hierarchy: hierarchies, user_id: id)
153163
end
154164

155-
def inherited_default_role
156-
@inherited_default_role ||= Monarchy.role_class.find_by(name: Monarchy.configuration.inherited_default_role)
165+
def hierarchies_for(resources)
166+
Monarchy.hierarchy_class.where(resource: resources)
167+
end
168+
169+
def descendants_for(resources)
170+
resources_hierarchies = hierarchies_for(resources).select(:id)
171+
172+
Monarchy.hierarchy_class
173+
.joins('INNER JOIN monarchy_hierarchy_hierarchies ON ' \
174+
'monarchy_hierarchies.id = monarchy_hierarchy_hierarchies.descendant_id')
175+
.where(monarchy_hierarchy_hierarchies: { ancestor_id: resources_hierarchies })
176+
.where.not(monarchy_hierarchies: { id: resources_hierarchies })
177+
end
178+
179+
def ancestors_for(resources)
180+
resources_hierarchies = hierarchies_for(resources).select(:id)
181+
182+
Monarchy.hierarchy_class
183+
.joins('INNER JOIN monarchy_hierarchy_hierarchies ON ' \
184+
'monarchy_hierarchies.id = monarchy_hierarchy_hierarchies.ancestor_id')
185+
.where(monarchy_hierarchy_hierarchies: { descendant_id: resources_hierarchies })
186+
.where.not(monarchy_hierarchies: { id: resources_hierarchies })
157187
end
158188
end
159189
end

0 commit comments

Comments
 (0)