groupify 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +2 -18
- data/Gemfile +11 -1
- data/README.md +100 -20
- data/gemfiles/activesupport3.gemfile +18 -0
- data/gemfiles/activesupport4.gemfile +23 -0
- data/groupify.gemspec +7 -2
- data/lib/groupify/adapter/active_record.rb +318 -0
- data/lib/groupify/adapter/mongoid.rb +249 -0
- data/lib/groupify/railtie.rb +20 -0
- data/lib/groupify/version.rb +1 -1
- data/lib/groupify.rb +1 -195
- data/spec/groupify/active_record_spec.rb +231 -0
- data/spec/groupify/{mongoid3.yml → mongoid.yml} +0 -0
- data/spec/groupify/mongoid_spec.rb +93 -23
- data/spec/spec_helper.rb +2 -12
- metadata +60 -47
- data/gemfiles/mongoid2.gemfile +0 -10
- data/gemfiles/mongoid3.gemfile +0 -8
- data/spec/groupify/mongoid2.yml +0 -9
data/.travis.yml
CHANGED
@@ -1,27 +1,11 @@
|
|
1
1
|
language: ruby
|
2
2
|
services: mongodb
|
3
3
|
rvm:
|
4
|
-
- ree
|
5
|
-
- 1.8.7
|
6
4
|
- 1.9.3
|
7
5
|
- 2.0.0
|
8
|
-
- jruby-18mode # JRuby in 1.8 mode
|
9
6
|
- jruby-19mode # JRuby in 1.9 mode
|
10
|
-
- rbx-18mode
|
11
7
|
- rbx-19mode
|
12
8
|
gemfile:
|
13
|
-
- gemfiles/
|
14
|
-
- gemfiles/
|
15
|
-
matrix:
|
16
|
-
exclude:
|
17
|
-
- rvm: 1.8.7
|
18
|
-
gemfile: gemfiles/mongoid3.gemfile
|
19
|
-
- rvm: ree
|
20
|
-
gemfile: gemfiles/mongoid3.gemfile
|
21
|
-
- rvm: jruby-18mode
|
22
|
-
gemfile: gemfiles/mongoid3.gemfile
|
23
|
-
- rvm: rbx-18mode
|
24
|
-
gemfile: gemfiles/mongoid3.gemfile
|
25
|
-
allow_failures:
|
26
|
-
- rvm: rbx-18mode
|
9
|
+
- gemfiles/activesupport3.gemfile
|
10
|
+
- gemfiles/activesupport4.gemfile
|
27
11
|
|
data/Gemfile
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in groupify.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
platform :jruby do
|
7
|
+
gem "jdbc-sqlite3"
|
8
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
9
|
+
|
10
|
+
if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
11
|
+
gem "json"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
# Groupify [](http://travis-ci.org/dwbutler/groupify)
|
1
|
+
# Groupify [](http://travis-ci.org/dwbutler/groupify) [](https://gemnasium.com/dwbutler/groupify)
|
2
2
|
Adds group and membership functionality to Rails models.
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
The following ORMs are supported:
|
5
|
+
Mongoid 3.1 & 4.0, ActiveRecord 3.2 & 4.0
|
6
|
+
|
7
|
+
The following Rubies are supported:
|
8
|
+
Ruby 1.9.3, 2.0.0 (MRI, REE, JRuby, and Rubinius).
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
@@ -19,28 +22,75 @@ Or install it yourself as:
|
|
19
22
|
$ gem install groupify
|
20
23
|
|
21
24
|
## Getting Started
|
25
|
+
|
26
|
+
### Active Record
|
27
|
+
Add a migration similar to the following:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class CreateGroups < ActiveRecord::Migration
|
31
|
+
def change
|
32
|
+
create_table :groups do |t|
|
33
|
+
t.string :type # Only needed if using single table inheritence
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :group_memberships do |t|
|
37
|
+
t.string :member_type # Needed to make polymorphic members work
|
38
|
+
t.integer :member_id # The member that belongs to this group
|
39
|
+
t.integer :group_id # The group to which the member belongs
|
40
|
+
t.string :group_name # Links a member to a named group (if using named groups)
|
41
|
+
end
|
42
|
+
|
43
|
+
add_index :group_memberships, [:member_id, :member_type]
|
44
|
+
add_index :group_memberships, :group_id
|
45
|
+
add_index :group_memberships, :group_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
In your group model:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Group < ActiveRecord::Base
|
54
|
+
acts_as_group :members => [:users, :assignments], :default_members => :users
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
In your member models (i.e. `User`):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class User < ActiveRecord::Base
|
62
|
+
acts_as_group_member
|
63
|
+
acts_as_named_group_member
|
64
|
+
end
|
65
|
+
|
66
|
+
class Assignment < ActiveRecord::Base
|
67
|
+
acts_as_group_member
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
### Mongoid
|
22
72
|
In your group model:
|
23
73
|
|
24
74
|
```ruby
|
25
75
|
class Group
|
26
|
-
|
76
|
+
include Mongoid::Document
|
27
77
|
|
28
|
-
|
78
|
+
acts_as_group :members => [:users], :default_members => :users
|
29
79
|
end
|
30
80
|
```
|
31
81
|
|
32
|
-
In your
|
82
|
+
In your member models (i.e. `User`):
|
33
83
|
|
34
84
|
```ruby
|
35
85
|
class User
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
86
|
+
include Mongoid::Document
|
87
|
+
|
88
|
+
acts_as_group_member
|
89
|
+
acts_as_named_group_member
|
40
90
|
end
|
41
91
|
```
|
42
92
|
|
43
|
-
## Usage
|
93
|
+
## Basic Usage
|
44
94
|
|
45
95
|
Create groups and add members:
|
46
96
|
|
@@ -49,20 +99,22 @@ group = Group.new
|
|
49
99
|
user = User.new
|
50
100
|
|
51
101
|
user.groups << group
|
52
|
-
or
|
102
|
+
# or
|
53
103
|
group.add user
|
54
104
|
|
55
|
-
user.in_group?(group)
|
105
|
+
user.in_group?(group)
|
106
|
+
# => true
|
56
107
|
```
|
57
108
|
|
58
109
|
Add to named groups:
|
59
110
|
|
60
111
|
```ruby
|
61
112
|
user.named_groups << :admin
|
62
|
-
user.in_named_group?(:admin)
|
113
|
+
user.in_named_group?(:admin)
|
114
|
+
# => true
|
63
115
|
```
|
64
116
|
|
65
|
-
Check if two
|
117
|
+
Check if two members share any of the same groups:
|
66
118
|
|
67
119
|
```ruby
|
68
120
|
user1.shares_any_group?(user2)
|
@@ -72,16 +124,44 @@ user2.shares_any_named_group?(user1)
|
|
72
124
|
Query for groups & members:
|
73
125
|
|
74
126
|
```ruby
|
75
|
-
User.in_group(group)
|
76
|
-
User.in_named_group(:admin)
|
77
|
-
Group.with_member(user)
|
127
|
+
User.in_group(group) # Find all users in this group
|
128
|
+
User.in_named_group(:admin) # Find all users in this named group
|
129
|
+
Group.with_member(user) # Find all groups with this user
|
78
130
|
|
79
|
-
User.shares_any_group(user)
|
80
|
-
User.shares_any_named_group(user)
|
131
|
+
User.shares_any_group(user) # Find all users that share any groups with this user
|
132
|
+
User.shares_any_named_group(user) # Find all users that share any named groups with this user
|
133
|
+
```
|
134
|
+
|
135
|
+
Merge one group into another:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
# Moves the members of source into destination, and destroys source
|
139
|
+
destination_group.merge!(source_group)
|
81
140
|
```
|
82
141
|
|
83
142
|
Check the specs for more details.
|
84
143
|
|
144
|
+
## Using for Authorization
|
145
|
+
Groupify was originally created to help implement user authorization, although it can be used
|
146
|
+
generically for much more than that. Here is how to do it.
|
147
|
+
|
148
|
+
### With CanCan
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class Ability
|
152
|
+
include CanCan::Ability
|
153
|
+
|
154
|
+
def initialize(user)
|
155
|
+
…
|
156
|
+
# Implements group authorization
|
157
|
+
# Users can only manage assignment which belong to the same group
|
158
|
+
can [:manage], Assignment, Assignment.shares_any_group(user) do |assignment|
|
159
|
+
assignment.shares_any_group?(user)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
85
165
|
## Contributing
|
86
166
|
|
87
167
|
1. Fork it
|
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'activerecord', "~> 3.2"
|
4
|
+
gem "mongoid", ">= 3.0", "< 4"
|
5
|
+
gem 'mongoid-rspec', '>= 1.5.1'
|
6
|
+
|
7
|
+
gem 'database_cleaner'
|
8
|
+
gem "rspec"
|
9
|
+
gem "rake"
|
10
|
+
|
11
|
+
platform :ruby do
|
12
|
+
gem 'sqlite3'
|
13
|
+
end
|
14
|
+
|
15
|
+
platform :jruby do
|
16
|
+
gem "jdbc-sqlite3"
|
17
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'activerecord', "~> 4"
|
4
|
+
|
5
|
+
# TODO: Enable once Mongoid 4 is released
|
6
|
+
#gem "mongoid", ">= 4.0"
|
7
|
+
|
8
|
+
gem "mongoid", :github => "mongoid/mongoid"
|
9
|
+
gem 'mongoid-rspec'
|
10
|
+
|
11
|
+
gem 'database_cleaner'
|
12
|
+
gem "rspec"
|
13
|
+
gem "rake"
|
14
|
+
|
15
|
+
platform :ruby do
|
16
|
+
gem 'sqlite3'
|
17
|
+
end
|
18
|
+
|
19
|
+
platform :jruby do
|
20
|
+
gem "jdbc-sqlite3"
|
21
|
+
# See https://github.com/jruby/activerecord-jdbc-adapter/issues/253
|
22
|
+
gem "activerecord-jdbcsqlite3-adapter", :github => 'jruby/activerecord-jdbc-adapter', :branch => 'v1.3.0.beta2'
|
23
|
+
end
|
data/groupify.gemspec
CHANGED
@@ -14,8 +14,13 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "groupify"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Groupify::VERSION
|
17
|
-
|
18
|
-
gem.
|
17
|
+
|
18
|
+
gem.add_development_dependency "mongoid", ">= 3.1"
|
19
|
+
gem.add_development_dependency "activerecord", ">= 3.2"
|
20
|
+
|
21
|
+
unless defined?(JRUBY_VERSION)
|
22
|
+
gem.add_development_dependency "sqlite3"
|
23
|
+
end
|
19
24
|
|
20
25
|
gem.add_development_dependency "rake"
|
21
26
|
gem.add_development_dependency "rspec"
|
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
# Groups and members
|
5
|
+
module Groupify
|
6
|
+
module ActiveRecord
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# Define a scope that returns nothing.
|
11
|
+
# This is built into ActiveRecord 4, but not 3
|
12
|
+
unless self.class.respond_to? :none
|
13
|
+
def self.none
|
14
|
+
where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def acts_as_group(opts = {})
|
21
|
+
include Groupify::ActiveRecord::Group
|
22
|
+
|
23
|
+
if (member_klass = opts.delete :default_members)
|
24
|
+
self.default_member_class = member_klass.to_s.classify.constantize
|
25
|
+
end
|
26
|
+
|
27
|
+
if (member_klasses = opts.delete :members)
|
28
|
+
member_klasses.each do |member_klass|
|
29
|
+
has_members(member_klass)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def acts_as_group_member(opts = {})
|
35
|
+
@group_class_name = opts[:class_name] || 'Group'
|
36
|
+
include Groupify::ActiveRecord::GroupMember
|
37
|
+
end
|
38
|
+
|
39
|
+
def acts_as_named_group_member(opts = {})
|
40
|
+
include Groupify::ActiveRecord::NamedGroupMember
|
41
|
+
end
|
42
|
+
|
43
|
+
def acts_as_group_membership(opts = {})
|
44
|
+
include Groupify::ActiveRecord::GroupMembership
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Usage:
|
49
|
+
# class Group < ActiveRecord::Base
|
50
|
+
# acts_as_group, :members => [:users]
|
51
|
+
# ...
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# group.add(member)
|
55
|
+
#
|
56
|
+
module Group
|
57
|
+
extend ActiveSupport::Concern
|
58
|
+
|
59
|
+
included do
|
60
|
+
@default_member_class = nil
|
61
|
+
@member_klasses ||= Set.new
|
62
|
+
has_many :group_memberships
|
63
|
+
end
|
64
|
+
|
65
|
+
def members
|
66
|
+
self.class.default_member_class.joins(:group_memberships).where(:group_memberships => {:member_type => self.class.default_member_class.to_s})
|
67
|
+
end
|
68
|
+
|
69
|
+
def member_classes
|
70
|
+
self.class.member_classes
|
71
|
+
end
|
72
|
+
|
73
|
+
def add(member)
|
74
|
+
member.groups << self
|
75
|
+
end
|
76
|
+
|
77
|
+
# Merge a source group into this group.
|
78
|
+
def merge!(source)
|
79
|
+
self.class.merge!(source, self)
|
80
|
+
end
|
81
|
+
|
82
|
+
module ClassMethods
|
83
|
+
def with_member(member)
|
84
|
+
#joins(:group_memberships).where(:group_memberships => {:member_id => member.id, :member_type => member.class.to_s})
|
85
|
+
member.groups
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_member_class
|
89
|
+
@default_member_class ||= register(User)
|
90
|
+
end
|
91
|
+
|
92
|
+
def default_member_class=(klass)
|
93
|
+
@default_member_class = klass
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the member classes defined for this class, as well as for the super classes
|
97
|
+
def member_classes
|
98
|
+
(@member_klasses ||= Set.new).merge(superclass.method_defined?(:member_classes) ? superclass.member_classes : [])
|
99
|
+
end
|
100
|
+
|
101
|
+
# Define which classes are members of this group
|
102
|
+
def has_members(name)
|
103
|
+
klass = name.to_s.classify.constantize
|
104
|
+
register(klass)
|
105
|
+
|
106
|
+
# Define specific members accessor, i.e. group.users
|
107
|
+
define_method name.to_s.pluralize.underscore do
|
108
|
+
klass.joins(:group_memberships).where(:group_memberships => {:group_id => self.id})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Merge two groups. The members of the source become members of the destination, and the source is destroyed.
|
113
|
+
def merge!(source_group, destination_group)
|
114
|
+
# Ensure that all the members of the source can be members of the destination
|
115
|
+
invalid_member_classes = (source_group.member_classes - destination_group.member_classes)
|
116
|
+
invalid_member_classes.each do |klass|
|
117
|
+
if klass.joins(:group_memberships).where(:group_memberships => {:group_id => source_group.id}).count > 0
|
118
|
+
raise ArgumentError.new("#{source_group.class} has members that cannot belong to #{destination_group.class}")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
source_group.transaction do
|
123
|
+
source_group.group_memberships.update_all(:group_id => destination_group.id)
|
124
|
+
source_group.destroy
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
protected
|
129
|
+
|
130
|
+
def register(member_klass)
|
131
|
+
(@member_klasses ||= Set.new) << member_klass
|
132
|
+
member_klass
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Join table that tracks which members belong to which groups
|
138
|
+
#
|
139
|
+
# Usage:
|
140
|
+
# class GroupMembership < ActiveRecord::Base
|
141
|
+
# acts_as_group_membership
|
142
|
+
# ...
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
module GroupMembership
|
146
|
+
extend ActiveSupport::Concern
|
147
|
+
|
148
|
+
included do
|
149
|
+
belongs_to :member, :polymorphic => true
|
150
|
+
belongs_to :group
|
151
|
+
end
|
152
|
+
|
153
|
+
module ClassMethods
|
154
|
+
def named(group_name=nil)
|
155
|
+
if group_name.present?
|
156
|
+
where(group_name: group_name)
|
157
|
+
else
|
158
|
+
where("group_name IS NOT NULL")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Usage:
|
165
|
+
# class User < ActiveRecord::Base
|
166
|
+
# acts_as_group_member
|
167
|
+
# ...
|
168
|
+
# end
|
169
|
+
#
|
170
|
+
# user.groups << group
|
171
|
+
#
|
172
|
+
module GroupMember
|
173
|
+
extend ActiveSupport::Concern
|
174
|
+
|
175
|
+
included do
|
176
|
+
has_many :group_memberships, :as => :member, :autosave => true
|
177
|
+
has_many :groups, :through => :group_memberships, :class_name => @group_class_name
|
178
|
+
end
|
179
|
+
|
180
|
+
def in_group?(group)
|
181
|
+
self.group_memberships.exists?(:group_id => group.id)
|
182
|
+
end
|
183
|
+
|
184
|
+
def in_any_group?(*groups)
|
185
|
+
groups.flatten.each do |group|
|
186
|
+
return true if in_group?(group)
|
187
|
+
end
|
188
|
+
return false
|
189
|
+
end
|
190
|
+
|
191
|
+
def in_all_groups?(*groups)
|
192
|
+
Set.new(groups.flatten) == Set.new(self.named_groups)
|
193
|
+
end
|
194
|
+
|
195
|
+
def shares_any_group?(other)
|
196
|
+
in_any_group?(other.groups)
|
197
|
+
end
|
198
|
+
|
199
|
+
module ClassMethods
|
200
|
+
def group_class_name; @group_class_name ||= 'Group'; end
|
201
|
+
def group_class_name=(klass); @group_class_name = klass; end
|
202
|
+
|
203
|
+
def in_group(group)
|
204
|
+
group.present? ? joins(:group_memberships).where(:group_memberships => {:group_id => group.id}) : none
|
205
|
+
end
|
206
|
+
|
207
|
+
def in_any_group(*groups)
|
208
|
+
groups.present? ? joins(:group_memberships).where(:group_memberships => {:group_id => groups.flatten.map(&:id)}) : none
|
209
|
+
end
|
210
|
+
|
211
|
+
def in_all_groups(*groups)
|
212
|
+
if groups.present?
|
213
|
+
groups = groups.flatten
|
214
|
+
|
215
|
+
joins(:group_memberships).
|
216
|
+
group(:"group_memberships.member_id").
|
217
|
+
where(:group_memberships => {:group_id => groups.map(&:id)}).
|
218
|
+
having("COUNT(group_memberships.group_id) = #{groups.count}")
|
219
|
+
else
|
220
|
+
none
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def shares_any_group(other)
|
225
|
+
in_any_group(other.groups)
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class NamedGroupCollection < Set
|
232
|
+
def initialize(member)
|
233
|
+
@member = member
|
234
|
+
super(member.group_memberships.named.pluck(:group_name).map(&:to_sym))
|
235
|
+
end
|
236
|
+
|
237
|
+
def <<(named_group)
|
238
|
+
named_group = named_group.to_sym
|
239
|
+
unless include?(named_group)
|
240
|
+
@member.group_memberships.build(:group_name => named_group)
|
241
|
+
super(named_group)
|
242
|
+
end
|
243
|
+
named_group
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
# Usage:
|
249
|
+
# class User < ActiveRecord::Base
|
250
|
+
# acts_as_named_group_member
|
251
|
+
# ...
|
252
|
+
# end
|
253
|
+
#
|
254
|
+
# user.named_groups << :admin
|
255
|
+
#
|
256
|
+
module NamedGroupMember
|
257
|
+
extend ActiveSupport::Concern
|
258
|
+
|
259
|
+
def named_groups
|
260
|
+
@named_groups ||= NamedGroupCollection.new(self)
|
261
|
+
end
|
262
|
+
|
263
|
+
def named_groups=(named_groups)
|
264
|
+
named_groups.each do |named_group|
|
265
|
+
self.named_groups << named_group
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def in_named_group?(group)
|
270
|
+
named_groups.include?(group)
|
271
|
+
end
|
272
|
+
|
273
|
+
def in_any_named_group?(*groups)
|
274
|
+
groups.flatten.each do |group|
|
275
|
+
return true if in_named_group?(group)
|
276
|
+
end
|
277
|
+
return false
|
278
|
+
end
|
279
|
+
|
280
|
+
def in_all_named_groups?(*groups)
|
281
|
+
Set.new(groups.flatten) == Set.new(self.named_groups)
|
282
|
+
end
|
283
|
+
|
284
|
+
def shares_any_named_group?(other)
|
285
|
+
in_any_named_group?(other.named_groups.to_a)
|
286
|
+
end
|
287
|
+
|
288
|
+
module ClassMethods
|
289
|
+
def in_named_group(named_group)
|
290
|
+
named_group.present? ? joins(:group_memberships).where(:group_memberships => {:group_name => named_group}) : none
|
291
|
+
end
|
292
|
+
|
293
|
+
def in_any_named_group(*named_groups)
|
294
|
+
named_groups.present? ? joins(:group_memberships).where(:group_memberships => {:group_name => named_groups.flatten}) : none
|
295
|
+
end
|
296
|
+
|
297
|
+
def in_all_named_groups(*named_groups)
|
298
|
+
if named_groups.present?
|
299
|
+
named_groups = named_groups.flatten.map(&:to_s)
|
300
|
+
|
301
|
+
joins(:group_memberships).
|
302
|
+
group(:"group_memberships.member_id").
|
303
|
+
where(:group_memberships => {:group_name => named_groups}).
|
304
|
+
having("COUNT(group_memberships.group_name) = #{named_groups.count}")
|
305
|
+
else
|
306
|
+
none
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def shares_any_named_group(other)
|
311
|
+
in_any_named_group(other.named_groups.to_a)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
ActiveRecord::Base.send :include, Groupify::ActiveRecord
|