diff --git a/README.md b/README.md index d8f28c4..a178afd 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Set up your member models: ```ruby class User include Mongoid::Document - + groupify :group_member groupify :named_group_member end @@ -131,10 +131,44 @@ Example: class Organization < Group has_members :offices, :equipment end + +class InternationalOrganization < Organization + has_member :offices, class_name: 'CustomOfficeClass' + has_member :equipment, class_name: 'CustomEquipmentClass' +end ``` Mongoid works the same way by creating Mongoid relations. +##### Group Associations on Member (ActiveRecord only) + +Your member class can be configured to create associations for each expected group type. +For example, let's say that your member class will have multiple types of organizations as groups. +The following configuration adds `organizations` and `international_organizations` associations +on the member model: + +```ruby +class Group < ActiveRecord::Base + groupify :group, members: [:users, :assignments], default_members: :users +end + +class Organization < Group + has_members :offices, :equipment +end + +class InternationalOrganization < Organization +end + +class Member < ActiveRecord::Base + groupify :group_member + + has_group :organizations, class_name: 'Organization' + has_group :international_organizations, class_name: 'InternationalOrganization' +end +``` + +Mongoid does not support the `has_group` helper method. + ## Usage ### Create groups and add members diff --git a/lib/groupify/adapter/active_record/group.rb b/lib/groupify/adapter/active_record/group.rb index f14339b..ffc5ae1 100644 --- a/lib/groupify/adapter/active_record/group.rb +++ b/lib/groupify/adapter/active_record/group.rb @@ -70,9 +70,22 @@ def member_classes # Define which classes are members of this group def has_members(*names) Array.wrap(names.flatten).each do |name| + has_member name + end + end + + def has_member(name, options = {}) + klass_name = options[:class_name] + + if klass_name.nil? klass = name.to_s.classify.constantize - register(klass) + association_name = name.is_a?(Symbol) ? name : klass.model_name.plural.to_sym + else + klass = klass_name.to_s.classify.constantize + association_name = name.to_sym end + + register(klass, association_name) end # Merge two groups. The members of the source become members of the destination, and the source is destroyed. @@ -93,10 +106,10 @@ def merge!(source_group, destination_group) protected - def register(member_klass) + def register(member_klass, association_name = nil) (@member_klasses ||= Set.new) << member_klass - associate_member_class(member_klass) + associate_member_class(member_klass, association_name) member_klass end @@ -135,8 +148,8 @@ def destroy(*args) end end - def associate_member_class(member_klass) - define_member_association(member_klass) + def associate_member_class(member_klass, association_name = nil) + define_member_association(member_klass, association_name) if member_klass == default_member_class define_member_association(member_klass, :members) diff --git a/lib/groupify/adapter/active_record/group_member.rb b/lib/groupify/adapter/active_record/group_member.rb index f6f961a..f49b902 100644 --- a/lib/groupify/adapter/active_record/group_member.rb +++ b/lib/groupify/adapter/active_record/group_member.rb @@ -21,11 +21,7 @@ module GroupMember class_name: Groupify.group_membership_class_name end - has_many :groups, ->{ distinct }, - through: :group_memberships_as_member, - as: :group, - source_type: @group_class_name, - extend: GroupAssociationExtensions + has_group :groups end module GroupAssociationExtensions @@ -144,6 +140,15 @@ def in_other_groups(*groups) def shares_any_group(other) in_any_group(other.groups) end + + def has_group(name, options = {}) + has_many name.to_sym, ->{ distinct }, { + through: :group_memberships_as_member, + source: :group, + source_type: @group_class_name, + extend: GroupAssociationExtensions + }.merge(options.slice :class_name) + end end end end diff --git a/lib/groupify/adapter/mongoid/group.rb b/lib/groupify/adapter/mongoid/group.rb index 5ea992a..aa8eddf 100644 --- a/lib/groupify/adapter/mongoid/group.rb +++ b/lib/groupify/adapter/mongoid/group.rb @@ -67,9 +67,22 @@ def member_classes # Define which classes are members of this group def has_members(*names) Array.wrap(names.flatten).each do |name| + has_member name + end + end + + def has_member(name, options = {}) + klass_name = options[:class_name] + + if klass_name.nil? klass = name.to_s.classify.constantize - register(klass) + association_name = name.is_a?(Symbol) ? name : klass.model_name.plural.to_sym + else + klass = klass_name.to_s.classify.constantize + association_name = name.to_sym end + + register(klass, association_name) end # Merge two groups. The members of the source become members of the destination, and the source is destroyed. @@ -101,9 +114,11 @@ def merge!(source_group, destination_group) protected - def register(member_klass) + def register(member_klass, association_name = nil) (@member_klasses ||= Set.new) << member_klass - associate_member_class(member_klass) + + associate_member_class(member_klass, association_name) + member_klass end @@ -137,7 +152,7 @@ def delete(*args) end end - def associate_member_class(member_klass) + def associate_member_class(member_klass, association_name = nil) association_name ||= member_klass.model_name.plural.to_sym has_many association_name, class_name: member_klass.to_s, dependent: :nullify, foreign_key: 'group_ids', extend: MemberAssociationExtensions