lib/groupify/adapter/mongoid/group_member.rb
module Groupify
module Mongoid
# Usage:
# class User
# include Mongoid::Document
#
# acts_as_group_member
# ...
# end
#
# user.groups << group
#
module GroupMember
extend ActiveSupport::Concern
include MemberScopedAs
included do
has_and_belongs_to_many :groups, autosave: true, dependent: :nullify, inverse_of: nil, class_name: @group_class_name do
def as(membership_type)
return self unless membership_type
group_ids = base.group_memberships.as(membership_type).first.group_ids
if group_ids.present?
self.and(:id.in => group_ids)
else
self.and(:id => nil)
end
end
def destroy(*args)
delete(*args)
end
def delete(*args)
opts = args.extract_options!
groups = args.flatten
if opts[:as]
base.group_memberships.as(opts[:as]).each do |membership|
membership.groups.delete(*groups)
end
else
super(*groups)
end
end
end
class GroupMembership
include ::Mongoid::Document
embedded_in :member, polymorphic: true
field :named_groups, type: Array, default: -> { [] }
after_initialize do
named_groups.extend NamedGroupCollection
end
field :as, as: :membership_type, type: String
end
GroupMembership.send :has_and_belongs_to_many, :groups, class_name: @group_class_name, inverse_of: nil
embeds_many :group_memberships, class_name: GroupMembership.to_s, as: :member do
def as(membership_type)
where(membership_type: membership_type.to_s)
end
end
end
def in_group?(group, opts={})
return false unless group.present?
groups.as(opts[:as]).include?(group)
end
def in_any_group?(*args)
opts = args.extract_options!
groups = args
groups.flatten.each do |group|
return true if in_group?(group, opts)
end
return false
end
def in_all_groups?(*args)
opts = args.extract_options!
groups = args
groups.flatten.to_set.subset? self.groups.as(opts[:as]).to_set
end
def in_only_groups?(*args)
opts = args.extract_options!
groups = args.flatten
groups.to_set == self.groups.as(opts[:as]).to_set
end
def shares_any_group?(other, opts={})
in_any_group?(other.groups.to_a, opts)
end
module ClassMethods
def in_group(group)
group.present? ? self.in(group_ids: group.id) : none
end
def in_any_group(*groups)
groups.present? ? self.in(group_ids: groups.flatten.map(&:id)) : none
end
def in_all_groups(*groups)
groups.present? ? where(:group_ids.all => groups.flatten.map(&:id)) : none
end
def in_only_groups(*groups)
groups.present? ? where(:group_ids => groups.flatten.map(&:id)) : none
end
def shares_any_group(other)
in_any_group(other.groups.to_a)
end
end
end
end
end