Class: UserGroupMembership
- Inherits:
-
DagLink
- Object
- ActiveRecord::Base
- DagLink
- UserGroupMembership
- Includes:
- UserGroupMembershipMixins::ValidityRange, UserGroupMembershipMixins::ValidityRangeForIndirectMemberships
- Defined in:
- app/models/user_group_membership.rb
Overview
In this application, all user group memberships, i.e. memberships of a certain user in a certain group, are stored implicitly in the dag_links table in order to minimize the number of database queries that are necessary to find out whether a user is member in a certain group through an indirect membership.
This class allows abstract access to the UserGroupMemberships themselves, and to their properties like since when the membership exists.
Direct Known Subclasses
Class Method Summary collapse
-
.create(params) ⇒ Object
Create a membership of the ‘u` in the group `g`.
-
.find_all_by(params) ⇒ Object
Find all memberships that match the given parameters.
- .find_all_by_group(group) ⇒ Object
- .find_all_by_user(user) ⇒ Object
- .find_all_by_user_and_group(user, group) ⇒ Object
-
.find_by(params) ⇒ Object
Find the first membership that matches the parameters ‘params`.
- .find_by_user_and_group(user, group) ⇒ Object
Instance Method Summary collapse
-
#corporation ⇒ Object
If this membership is a subgroup membership of a corporation, this method will return the corporation.
-
#destroy ⇒ Object
The regular destroy method won’t trigger DagLink’s callbacks properly, causing the former dag link bug.
-
#direct_groups ⇒ Object
Returns the direct groups shown in the figures above in the description of ‘direct_memberships`.
-
#direct_memberships(options = {}) ⇒ Object
Returns the direct memberships corresponding to this membership (self).
- #direct_memberships_now_and_in_the_past ⇒ Object
- #group ⇒ Object
- #group_id ⇒ Object
-
#indirect_memberships ⇒ Object
Access Methods to Associated Indirect Memberships ====================================================================================================.
- #move_to(group, options = {}) ⇒ Object
-
#move_to_group(group_to_move_in, options = {}) ⇒ Object
Destroy the current membership and move the user over to the given group.
- #promote_to(new_group, options = {}) ⇒ Object
-
#title ⇒ Object
Title, e.g.
-
#user ⇒ Object
Access Methods to Associated User and Group ====================================================================================================.
- #user=(new_user) ⇒ Object
- #user_id ⇒ Object
- #user_title ⇒ Object
- #user_title=(new_user_title) ⇒ Object
Methods inherited from DagLink
Methods inherited from ActiveRecord::Base
Class Method Details
.create(params) ⇒ Object
Create a membership of the ‘u` in the group `g`.
membership = UserGroupMembership.create( user: u, group: g )
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'app/models/user_group_membership.rb', line 50 def self.create( params ) if UserGroupMembership.find_by( params ).present? raise 'Membership already exists: id = ' + UserGroupMembership.find_by( params ).id.to_s else user = params[:user] user ||= User.find params[:user_id] if params[:user_id] user ||= User.find_by_title params[:user_title] if params[:user_title] raise "Could not create UserGroupMembership without user." unless user group = params[ :group ] group ||= Group.find params[:group_id] if params[:group_id] raise "Could not create UserGroupMembership without group." unless group new_membership = DagLink .create(ancestor_id: group.id, ancestor_type: 'Group', descendant_id: user.id, descendant_type: 'User') .becomes(UserGroupMembership) # This needs to be called manually, since DagLink won't call the proper callback. # new_membership.set_valid_from_to_now(true) new_membership.save return new_membership end end |
.find_all_by(params) ⇒ Object
Find all memberships that match the given parameters. This method returns an ActiveRecord::Relation object, which means that the result can be chained with scope methods.
memberships = UserGroupMembership.find_all_by( user: u )
memberships = UserGroupMembership.find_all_by( group: g )
memberships = UserGroupMembership.find_all_by( user: u, group: g ).now
memberships = UserGroupMembership.find_all_by( user: u, group: g ).in_the_past
memberships = UserGroupMembership.find_all_by( user: u, group: g ).now_and_in_the_past
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/models/user_group_membership.rb', line 90 def self.find_all_by( params ) user = params[ :user ] user ||= User.find params[:user_id] if params[:user_id] user ||= User.find_by_title params[:user_title] if params[:user_title] group = params[ :group ] group ||= Group.find params[:group_id] if params[:group_id] links = UserGroupMembership .where( :descendant_type => "User" ) .where( :ancestor_type => "Group" ) links = links.where( :descendant_id => user.id ) if user links = links.where( :ancestor_id => group.id ) if group links = links.order('valid_from') return links end |
.find_all_by_group(group) ⇒ Object
117 118 119 |
# File 'app/models/user_group_membership.rb', line 117 def self.find_all_by_group( group ) self.find_all_by( group: group ) end |
.find_all_by_user(user) ⇒ Object
113 114 115 |
# File 'app/models/user_group_membership.rb', line 113 def self.find_all_by_user( user ) self.find_all_by( user: user ) end |
.find_all_by_user_and_group(user, group) ⇒ Object
125 126 127 |
# File 'app/models/user_group_membership.rb', line 125 def self.find_all_by_user_and_group( user, group ) self.find_all_by( user: user, group: group ) end |
.find_by(params) ⇒ Object
Find the first membership that matches the parameters ‘params`. This is a shortcut for `find_all_by( params ).first`. Use this, if you only expect one membership to be found.
109 110 111 |
# File 'app/models/user_group_membership.rb', line 109 def self.find_by( params ) self.find_all_by( params ).limit( 1 ).first end |
.find_by_user_and_group(user, group) ⇒ Object
121 122 123 |
# File 'app/models/user_group_membership.rb', line 121 def self.find_by_user_and_group( user, group ) self.find_by( user: user, group: group ) end |
Instance Method Details
#corporation ⇒ Object
If this membership is a subgroup membership of a corporation, this method will return the corporation. Otherwise, this will return nil.
corporation
|-------- group
|---( membership )---- user
membership = UserGroupMembership.find_by_user_and_group( user, group )
membership.corporation == corporation
181 182 183 184 185 |
# File 'app/models/user_group_membership.rb', line 181 def corporation if self.group && self.user ( ( self.group.ancestor_groups + [ self.group ] ) && self.user.corporations ).first end end |
#destroy ⇒ Object
The regular destroy method won’t trigger DagLink’s callbacks properly, causing the former dag link bug. By calling the DagLink’s destroy method we’ll ensure the callbacks are called and indirect memberships are destroyed correctly.
293 294 295 |
# File 'app/models/user_group_membership.rb', line 293 def destroy DagLink.where(id: self.id).first.destroy end |
#direct_groups ⇒ Object
Returns the direct groups shown in the figures above in the description of ‘direct_memberships`.
245 246 247 |
# File 'app/models/user_group_membership.rb', line 245 def direct_groups direct_memberships.collect { |membership| membership.group } end |
#direct_memberships(options = {}) ⇒ Object
Returns the direct memberships corresponding to this membership (self). For clarification, consider the following structure:
group1
|---- group2
|---- user
user is not a direct member of group1, but an indirect member. But user is a direct member of group2. Thus, this method, called on a membership of user and group1 will return the membership between user and group2.
UserGroupMembership.find_by( user: user, group: group1 ).direct_memberships.should
include( UserGroupMembership.find_by( user: user, group: group2 ) )
An indirect membership can also have several direct memberships, as shown in this figure:
group1
|--------------- group2
| |
|---- group3 |
|------------- user
Here, group2 and grou3 are children of group1. user is member of group2 and group3. Hence, the indirect membership of user and group1 will include both direct memberships.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'app/models/user_group_membership.rb', line 216 def direct_memberships( = {}) descendant_groups_of_self_group = self.group.descendant_groups descendant_group_ids_of_self_group = descendant_groups_of_self_group.pluck(:id) group_ids = descendant_group_ids_of_self_group + [ self.group.id ] memberships = UserGroupMembership if [:with_invalid] || self.read_attribute( :valid_to ) # If the membership itself is invalidated, also consider the invalidated direct memberships. # Otherwise, one has to call `direct_memberships_now_and_in_the_past` rather than # `direct_memberships` in order to have the invalidated direct memberships included. memberships = memberships.with_invalid end memberships = memberships .find_all_by_user( self.user ) .where( :direct => true ) .where( :ancestor_id => group_ids, :ancestor_type => 'Group' ) memberships = memberships.order('valid_from') memberships end |
#direct_memberships_now_and_in_the_past ⇒ Object
238 239 240 |
# File 'app/models/user_group_membership.rb', line 238 def direct_memberships_now_and_in_the_past direct_memberships(with_invalid: true) end |
#group ⇒ Object
153 154 155 |
# File 'app/models/user_group_membership.rb', line 153 def group self.ancestor end |
#group_id ⇒ Object
157 158 159 |
# File 'app/models/user_group_membership.rb', line 157 def group_id self.ancestor_id end |
#indirect_memberships ⇒ Object
Access Methods to Associated Indirect Memberships
253 254 255 256 257 258 259 |
# File 'app/models/user_group_membership.rb', line 253 def indirect_memberships self.group.ancestor_groups.collect do |ancestor_group| UserGroupMembership.with_invalid.find_by_user_and_group(self.user, ancestor_group) end.select do |item| item != nil end end |
#move_to(group, options = {}) ⇒ Object
276 277 278 |
# File 'app/models/user_group_membership.rb', line 276 def move_to(group, = {}) move_to_group(group, ) end |
#move_to_group(group_to_move_in, options = {}) ⇒ Object
Destroy the current membership and move the user over to the given group.
group1 group2
|---- user => |---- user
269 270 271 272 273 274 275 |
# File 'app/models/user_group_membership.rb', line 269 def move_to_group( group_to_move_in, = {} ) time = ([:time] || [:date] || [:at] || Time.zone.now).to_datetime invalidate at: time new_membership = UserGroupMembership.create(user: self.user, group: group_to_move_in) new_membership.update_attribute(:valid_from, time) return new_membership end |
#promote_to(new_group, options = {}) ⇒ Object
280 281 282 |
# File 'app/models/user_group_membership.rb', line 280 def promote_to( new_group, = {} ) self.move_to_group( new_group, ) end |
#title ⇒ Object
Title, e.g. ‘Membership of John Doe in GroupXY’
39 40 41 |
# File 'app/models/user_group_membership.rb', line 39 def title I18n.translate( :membership_of_user_in_group, user_name: self.user.title, group_name: self.group.name ) end |
#user ⇒ Object
Access Methods to Associated User and Group
133 134 135 |
# File 'app/models/user_group_membership.rb', line 133 def user self.descendant end |
#user=(new_user) ⇒ Object
137 138 139 140 |
# File 'app/models/user_group_membership.rb', line 137 def user=(new_user) self.descendant_id = new_user.id self.descendant_type = 'User' end |
#user_id ⇒ Object
142 143 144 |
# File 'app/models/user_group_membership.rb', line 142 def user_id self.descendant_id end |
#user_title ⇒ Object
146 147 148 |
# File 'app/models/user_group_membership.rb', line 146 def user_title user.try(:title) end |
#user_title=(new_user_title) ⇒ Object
149 150 151 |
# File 'app/models/user_group_membership.rb', line 149 def user_title=(new_user_title) self.user = User.find_by_title(new_user_title) end |