groupify 0.6.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +90 -0
  5. data/Gemfile +1 -1
  6. data/README.md +87 -49
  7. data/gemfiles/rails_3.2.gemfile +1 -1
  8. data/gemfiles/rails_4.0.gemfile +1 -1
  9. data/gemfiles/rails_4.1.gemfile +1 -1
  10. data/gemfiles/rails_4.2.gemfile +1 -1
  11. data/groupify.gemspec +3 -1
  12. data/lib/generators/groupify/active_record/initializer/initializer_generator.rb +11 -0
  13. data/lib/generators/groupify/active_record/initializer/templates/initializer.rb +9 -0
  14. data/lib/generators/groupify/active_record/install/install_generator.rb +12 -0
  15. data/lib/generators/groupify/active_record/migration/migration_generator.rb +22 -0
  16. data/lib/generators/groupify/active_record/migration/templates/migration.rb +20 -0
  17. data/lib/generators/groupify/active_record/model/model_generator.rb +15 -0
  18. data/lib/generators/groupify/active_record/model/templates/group.rb +3 -0
  19. data/lib/generators/groupify/active_record/model/templates/group_membership.rb +3 -0
  20. data/lib/generators/groupify/active_record/next_migration_version.rb +16 -0
  21. data/lib/generators/groupify/active_record/upgrade/templates/upgrade_migration.rb +7 -0
  22. data/lib/generators/groupify/active_record/upgrade/upgrade_generator.rb +22 -0
  23. data/lib/generators/groupify/mongoid/initializer/initializer_generator.rb +11 -0
  24. data/lib/generators/groupify/mongoid/initializer/templates/initializer.rb +5 -0
  25. data/lib/generators/groupify/mongoid/install/install_generator.rb +12 -0
  26. data/lib/generators/groupify/mongoid/model/model_generator.rb +11 -0
  27. data/lib/generators/groupify/mongoid/model/templates/group.rb +5 -0
  28. data/lib/groupify.rb +13 -1
  29. data/lib/groupify/adapter/active_record/group.rb +19 -6
  30. data/lib/groupify/adapter/active_record/group_member.rb +20 -10
  31. data/lib/groupify/adapter/active_record/group_membership.rb +3 -3
  32. data/lib/groupify/adapter/active_record/model.rb +1 -1
  33. data/lib/groupify/adapter/active_record/named_group_member.rb +7 -3
  34. data/lib/groupify/adapter/mongoid/group.rb +2 -2
  35. data/lib/groupify/adapter/mongoid/group_member.rb +0 -3
  36. data/lib/groupify/adapter/mongoid/model.rb +1 -1
  37. data/lib/groupify/version.rb +1 -1
  38. data/spec/active_record_spec.rb +98 -30
  39. data/spec/db/schema.rb +28 -4
  40. data/spec/mongoid_spec.rb +4 -4
  41. metadata +33 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 330d329200d0dda6ac489a0c099fd54655e2899d
4
- data.tar.gz: 95a7c8c3d68c7e409818cd8fe816957325da8112
3
+ metadata.gz: 2d570dee72597e96ba6684917ba35f43d4d90809
4
+ data.tar.gz: eae9072357349dae48d23634ecda81e6a95d0447
5
5
  SHA512:
6
- metadata.gz: f256fc9f5d55ad7feb210c9af83ae7005f0c1921ad76af0f3f5287f8f0e71653a5a54e99f335460cada5dd11466ad96b70b862951e4eb8f52362f3175fa004f4
7
- data.tar.gz: 2be5800f07ea8e8b32f13e349557ebfb6f795fe490433a7468e4f5606c349573728ce47e59a40894705967cc4599b38000b966ca10a37c4d5bf2e8993d0d40c3
6
+ metadata.gz: 62eb907fb6744685f4d799b8d51611fdf91539e1cce0d5207d05a7f3470a485d8fe443520e11c507b40548c05e7af5a585577275660fbe13c087eb26a0d87f0f
7
+ data.tar.gz: 3f16c4a4941e7d86eeed9ab62b764be8cb236eb4dd390a0a3e6c745b29914e22ef210f016e66a8169f730150b339279e84d3ab31bdb991dbed2808d7a7b0e30c
data/.rspec CHANGED
@@ -1,4 +1,3 @@
1
1
  --color
2
2
  --format progress
3
3
  --require spec_helper
4
- --pattern "spec/**/*_spec.rb"
@@ -23,3 +23,4 @@ matrix:
23
23
  gemfile: gemfiles/rails_3.2.gemfile
24
24
  allow_failures:
25
25
  - rvm: rbx-2
26
+ sudo: false
@@ -0,0 +1,90 @@
1
+ # Change Log
2
+
3
+ ## [v0.6.3](https://github.com/dwbutler/groupify/tree/v0.6.3) (2015-08-24)
4
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.6.2...v0.6.3)
5
+
6
+ **Fixed bugs:**
7
+
8
+ - ActiveRecord Statement Invalid for Group queries [\#30](https://github.com/dwbutler/groupify/issues/30)
9
+
10
+ **Merged pull requests:**
11
+
12
+ - Test against mysql and postgresql [\#31](https://github.com/dwbutler/groupify/pull/31) ([dwbutler](https://github.com/dwbutler))
13
+
14
+ ## [v0.6.2](https://github.com/dwbutler/groupify/tree/v0.6.2) (2015-05-28)
15
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.6.1...v0.6.2)
16
+
17
+ **Closed issues:**
18
+
19
+ - can't complete migration [\#27](https://github.com/dwbutler/groupify/issues/27)
20
+ - NameError: uninitialized constant User::GroupMembership [\#25](https://github.com/dwbutler/groupify/issues/25)
21
+
22
+ **Merged pull requests:**
23
+
24
+ - fix association name in mongoid adapter [\#29](https://github.com/dwbutler/groupify/pull/29) ([samuelebistoletti](https://github.com/samuelebistoletti))
25
+
26
+ ## [v0.6.1](https://github.com/dwbutler/groupify/tree/v0.6.1) (2015-01-16)
27
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.6.0...v0.6.1)
28
+
29
+ **Closed issues:**
30
+
31
+ - Groupify support unique groups scoped to user? [\#18](https://github.com/dwbutler/groupify/issues/18)
32
+ - Double Membership [\#14](https://github.com/dwbutler/groupify/issues/14)
33
+ - Getting uninitialized constant Assignment [\#8](https://github.com/dwbutler/groupify/issues/8)
34
+
35
+ **Merged pull requests:**
36
+
37
+ - Fixed bug that occurs when using namespaced Models [\#24](https://github.com/dwbutler/groupify/pull/24) ([byronduenas](https://github.com/byronduenas))
38
+
39
+ ## [v0.6.0](https://github.com/dwbutler/groupify/tree/v0.6.0) (2014-08-27)
40
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.6.0.rc2...v0.6.0)
41
+
42
+ ## [v0.6.0.rc2](https://github.com/dwbutler/groupify/tree/v0.6.0.rc2) (2014-08-21)
43
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.6.0.rc1...v0.6.0.rc2)
44
+
45
+ **Closed issues:**
46
+
47
+ - NoMethodError: undefined method `groups' for {:as=\>"manager"}:Hash [\#12](https://github.com/dwbutler/groupify/issues/12)
48
+ - Count functions [\#10](https://github.com/dwbutler/groupify/issues/10)
49
+ - Named Groups to be a Group [\#7](https://github.com/dwbutler/groupify/issues/7)
50
+
51
+ **Merged pull requests:**
52
+
53
+ - Active Record adapter typo fix [\#13](https://github.com/dwbutler/groupify/pull/13) ([fourfour](https://github.com/fourfour))
54
+
55
+ ## [v0.6.0.rc1](https://github.com/dwbutler/groupify/tree/v0.6.0.rc1) (2014-06-18)
56
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.5.1...v0.6.0.rc1)
57
+
58
+ **Closed issues:**
59
+
60
+ - Change the name of the group\_membership [\#9](https://github.com/dwbutler/groupify/issues/9)
61
+ - Extend to deal with group managers/leaders? [\#3](https://github.com/dwbutler/groupify/issues/3)
62
+
63
+ **Merged pull requests:**
64
+
65
+ - Membership types [\#6](https://github.com/dwbutler/groupify/pull/6) ([dwbutler](https://github.com/dwbutler))
66
+
67
+ ## [v0.5.1](https://github.com/dwbutler/groupify/tree/v0.5.1) (2014-03-28)
68
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.5.0...v0.5.1)
69
+
70
+ **Merged pull requests:**
71
+
72
+ - Allow model instances to access other models with names matching Groupify modules [\#5](https://github.com/dwbutler/groupify/pull/5) ([reed](https://github.com/reed))
73
+
74
+ ## [v0.5.0](https://github.com/dwbutler/groupify/tree/v0.5.0) (2014-03-24)
75
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.4.2...v0.5.0)
76
+
77
+ **Closed issues:**
78
+
79
+ - New Group \(Unsaved\) has members somehow [\#2](https://github.com/dwbutler/groupify/issues/2)
80
+
81
+ ## [v0.4.2](https://github.com/dwbutler/groupify/tree/v0.4.2) (2013-07-02)
82
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.4.1...v0.4.2)
83
+
84
+ ## [v0.4.1](https://github.com/dwbutler/groupify/tree/v0.4.1) (2013-07-02)
85
+ [Full Changelog](https://github.com/dwbutler/groupify/compare/v0.4.0...v0.4.1)
86
+
87
+ ## [v0.4.0](https://github.com/dwbutler/groupify/tree/v0.4.0) (2013-07-01)
88
+
89
+
90
+ \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
data/Gemfile CHANGED
@@ -20,6 +20,6 @@ end
20
20
 
21
21
  platforms :ruby do
22
22
  gem "sqlite3"
23
- gem "mysql2"
23
+ gem "mysql2", "~> 0.3.11"
24
24
  gem "pg"
25
25
  end
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # Groupify
2
- [![Build Status](https://secure.travis-ci.org/dwbutler/groupify.png)](http://travis-ci.org/dwbutler/groupify) [![Coverage Status](https://coveralls.io/repos/dwbutler/groupify/badge.png?branch=master)](https://coveralls.io/r/dwbutler/groupify?branch=master) [![Code Climate](https://codeclimate.com/github/dwbutler/groupify.png)](https://codeclimate.com/github/dwbutler/groupify) [![Inline docs](http://inch-ci.org/github/dwbutler/groupify.svg?branch=master)](http://inch-ci.org/github/dwbutler/groupify)
2
+ [![Build Status](https://travis-ci.org/dwbutler/groupify.svg?branch=master)](https://travis-ci.org/dwbutler/groupify) [![Coverage Status](https://coveralls.io/repos/dwbutler/groupify/badge.svg?branch=master&service=github)](https://coveralls.io/github/dwbutler/groupify?branch=master) [![Code Climate](https://codeclimate.com/github/dwbutler/groupify/badges/gpa.svg)](https://codeclimate.com/github/dwbutler/groupify) [![Inline docs](http://inch-ci.org/github/dwbutler/groupify.svg?branch=master)](http://inch-ci.org/github/dwbutler/groupify)
3
3
 
4
4
  Adds group and membership functionality to Rails models. Defines a polymorphic
5
5
  relationship between a Group model and any member model. Don't need a Group
6
6
  model? Use named groups instead to add members to named groups such as
7
7
  `:admin` or `"Team Rocketpants"`.
8
8
 
9
+ ## Compatibility
10
+
9
11
  The following ORMs are supported:
10
12
  * ActiveRecord 3.2, 4.1.x, 4.2.x
11
13
  * Mongoid 3.1, 4.0
@@ -34,40 +36,21 @@ Or install it yourself as:
34
36
 
35
37
  $ gem install groupify
36
38
 
37
- ### Active Record
38
- Add a migration similar to the following:
39
+ ### Setup
39
40
 
40
- ```ruby
41
- class CreateGroups < ActiveRecord::Migration
42
- def change
43
- create_table :groups do |t|
44
- t.string :type # Only needed if using single table inheritance
45
- end
46
-
47
- create_table :group_memberships do |t|
48
- t.string :member_type # Necessary to make polymorphic members work
49
- t.integer :member_id # The id of the member that belongs to this group
50
- t.integer :group_id # The group to which the member belongs
51
- t.string :group_name # The named group to which a member belongs (if using)
52
- t.string :membership_type # The type of membership the member belongs with
53
- end
41
+ #### Active Record
54
42
 
55
- add_index :group_memberships, [:member_id, :member_type]
56
- add_index :group_memberships, :group_id
57
- add_index :group_memberships, :group_name
58
- end
59
- end
60
- ```
43
+ Execute:
61
44
 
62
- In your group model:
45
+ $ rails generate groupify:active_record:install
63
46
 
64
- ```ruby
65
- class Group < ActiveRecord::Base
66
- groupify :group, members: [:users, :assignments], default_members: :users
67
- end
68
- ```
47
+ This will generate an initializer, `Group` model, `GroupMembership` model, and migrations.
48
+
49
+ Modify the models and migrations as needed, then run the migration:
50
+
51
+ $ rake db:migrate
69
52
 
70
- In your member models (i.e. `User`):
53
+ Set up your member models:
71
54
 
72
55
  ```ruby
73
56
  class User < ActiveRecord::Base
@@ -80,37 +63,79 @@ class Assignment < ActiveRecord::Base
80
63
  end
81
64
  ```
82
65
 
83
- You will also need to define a `GroupMembership` model to join groups to members:
66
+ #### Mongoid
67
+
68
+ Execute:
69
+
70
+ $ rails generate groupify:mongoid:install
71
+
72
+ Set up your member models:
84
73
 
85
74
  ```ruby
86
- class GroupMembership < ActiveRecord::Base
87
- groupify :group_membership
75
+ class User
76
+ include Mongoid::Document
77
+
78
+ groupify :group_member
79
+ groupify :named_group_member
88
80
  end
89
81
  ```
90
82
 
91
- ### Mongoid
92
- In your group model:
83
+ #### Advanced Configuration
84
+
85
+ ##### Groupify Model Names
86
+
87
+ The default model names for groups and group memberships are configurable. Add the following
88
+ configuration in `config/initializers/groupify.rb` to change the model names for all classes:
93
89
 
94
90
  ```ruby
95
- class Group
96
- include Mongoid::Document
91
+ Groupify.configure do |config|
92
+ config.group_class_name = 'MyCustomGroup'
93
+ # ActiveRecord only
94
+ config.group_membership_class_name = 'MyCustomGroupMembership'
95
+ end
96
+ ```
97
97
 
98
- groupify :group, members: [:users], default_members: :users
98
+ The group name can also be set on a model-by-model basis for each group member by passing
99
+ the `group_class_name` option:
100
+
101
+ ```ruby
102
+ class Member < ActiveRecord::Base
103
+ groupify :group_member, group_class_name: 'MyOtherCustomGroup'
99
104
  end
100
105
  ```
101
106
 
102
- In your member models (i.e. `User`):
107
+ Note that each member model can only belong to a single type of group (or child classes
108
+ of that group).
109
+
110
+ ##### Member Associations on Group
111
+
112
+ Your group class can be configured to create associations for each expected member type.
113
+ For example, let's say that your group class will have users and assignments as members.
114
+ The following configuration adds `users` and `assignments` associations on the group model:
103
115
 
104
116
  ```ruby
105
- class User
106
- include Mongoid::Document
107
-
108
- groupify :group_member
109
- groupify :named_group_member
117
+ class Group < ActiveRecord::Base
118
+ groupify :group, members: [:users, :assignments], default_members: :users
119
+ end
120
+ ```
121
+
122
+ The `default_members` option sets the model type when accessing the `members` association.
123
+ In the example above, `group.members` would return the users who are members of this group.
124
+
125
+ If you are using single table inheritance, child classes inherit the member associations
126
+ of the parent. If your child class needs to add more members, use the `has_members` method.
127
+
128
+ Example:
129
+
130
+ ```ruby
131
+ class Organization < Group
132
+ has_members [:offices, :equipment]
110
133
  end
111
134
  ```
112
135
 
113
- ## Basic Usage
136
+ Mongoid works the same way by creating Mongoid relations.
137
+
138
+ ## Usage
114
139
 
115
140
  ### Create groups and add members
116
141
 
@@ -245,10 +270,6 @@ employee.in_group?(group) # => false
245
270
  employee.in_group?(group, as: 'employee') # => false
246
271
  ```
247
272
 
248
- ## But wait, there's more!
249
-
250
- Check the specs for a complete list of methods and scopes provided by Groupify.
251
-
252
273
  ## Using for Authorization
253
274
  Groupify was originally created to help implement user authorization, although it can be used
254
275
  generically for much more than that. Here are some examples of how to do it.
@@ -336,6 +357,23 @@ class PostPolicy < Struct.new(:user, :post)
336
357
  end
337
358
  ```
338
359
 
360
+ ## Upgrading
361
+
362
+ ### 0.7+ - Polymorphic Groups (ActiveRecord only)
363
+ Groupify < 0.7 required a single `Group` model used for all group memberships.
364
+ Groupify 0.7+ supports using multiple models as groups by implementing polymorphic associations.
365
+ Upgrading requires adding a new `group_type` column to the `group_memberships` table and
366
+ populating that column with the class name of the group. Create the migration by executing:
367
+
368
+ $ rails generate groupify:active_record:upgrade
369
+
370
+ And then run the migration:
371
+
372
+ $ rake db:migrate
373
+
374
+ Please note that this migration may block writes in MySQL if your `group_memberships`
375
+ table is large.
376
+
339
377
  ## Contributing
340
378
 
341
379
  1. Fork it
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  platforms :ruby do
24
24
  gem "sqlite3"
25
- gem "mysql2"
25
+ gem "mysql2", "~> 0.3.11"
26
26
  gem "pg"
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  platforms :ruby do
24
24
  gem "sqlite3"
25
- gem "mysql2"
25
+ gem "mysql2", "~> 0.3.11"
26
26
  gem "pg"
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  platforms :ruby do
24
24
  gem "sqlite3"
25
- gem "mysql2"
25
+ gem "mysql2", "~> 0.3.11"
26
26
  gem "pg"
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  platforms :ruby do
24
24
  gem "sqlite3"
25
- gem "mysql2"
25
+ gem "mysql2", "~> 0.3.11"
26
26
  gem "pg"
27
27
  end
28
28
 
@@ -24,6 +24,8 @@ Gem::Specification.new do |gem|
24
24
  gem.add_development_dependency "rspec", ">= 3"
25
25
 
26
26
  gem.add_development_dependency "database_cleaner", "~> 1.3.0"
27
- gem.add_development_dependency 'combustion'
27
+ gem.add_development_dependency "combustion"
28
28
  gem.add_development_dependency "appraisal"
29
+
30
+ gem.add_development_dependency "github_changelog_generator"
29
31
  end
@@ -0,0 +1,11 @@
1
+ module Groupify
2
+ module ActiveRecord
3
+ class InitializerGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def copy_initializer
7
+ copy_file "initializer.rb", "config/initializers/groupify.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ Groupify.configure do |config|
2
+ # Configure the default group class name.
3
+ # Defaults to 'Group'
4
+ # config.group_class_name = 'Group'
5
+
6
+ # Configure the default group membership class name.
7
+ # Defaults to 'GroupMembership'
8
+ # config.group_membership_class_name = 'GroupMembership'
9
+ end
@@ -0,0 +1,12 @@
1
+ module Groupify
2
+ module ActiveRecord
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def invoke_generators
5
+ %w{ model migration initializer }.each do |name|
6
+ generate "groupify:active_record:#{name}"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,22 @@
1
+ require "rails/generators/migration"
2
+ require "rails/generators/active_record"
3
+ require "generators/groupify/active_record/next_migration_version"
4
+
5
+ module Groupify
6
+ module ActiveRecord
7
+ class MigrationGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+ extend NextMigrationVersion
10
+
11
+ source_root File.expand_path("../templates", __FILE__)
12
+
13
+ def create_migration_file
14
+ migration_template "migration.rb", "db/migrate/groupify_migration.rb"
15
+ end
16
+
17
+ def self.next_migration_number(dirname)
18
+ ::ActiveRecord::Generators::Base.next_migration_number dirname
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ class GroupifyMigration < ActiveRecord::Migration
2
+ def change
3
+ create_table :groups do |t|
4
+ t.string :type
5
+ end
6
+
7
+ create_table :group_memberships do |t|
8
+ t.references :member, polymorphic: true, index: true
9
+ t.references :group, polymorphic: true, index: true
10
+
11
+ # The named group to which a member belongs (if using)
12
+ t.string :group_name, index: true
13
+
14
+ # The membership type the member belongs with
15
+ t.string :membership_type
16
+
17
+ t.timestamps
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ module Groupify
2
+ module ActiveRecord
3
+ class ModelGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def copy_group_model_file
7
+ copy_file "group.rb", "app/models/group.rb"
8
+ end
9
+
10
+ def copy_group_membership_model_file
11
+ copy_file "group_membership.rb", "app/models/group_membership.rb"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ class Group < ActiveRecord::Base
2
+ groupify :group
3
+ end
@@ -0,0 +1,3 @@
1
+ class GroupMembership < ActiveRecord::Base
2
+ groupify :group_membership
3
+ end
@@ -0,0 +1,16 @@
1
+ module Groupify
2
+ module ActiveRecord
3
+ module NextMigrationVersion
4
+ # while methods have moved around this has been the implementation
5
+ # since ActiveRecord 3.0
6
+ def next_migration_number(dirname)
7
+ next_migration_number = current_migration_number(dirname) + 1
8
+ if ActiveRecord::Base.timestamped_migrations
9
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), format("%.14d", next_migration_number)].max
10
+ else
11
+ format("%.3d", next_migration_number)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ class AddGroupTypeToGroupMemberships < ActiveRecord::Migration
2
+ def change
3
+ add_column :group_memberships, :group_type, :string
4
+ GroupMembership.reset_column_information
5
+ GroupMembership.update_all(group_type: 'Group')
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ require "rails/generators/migration"
2
+ require "rails/generators/active_record"
3
+ require "generators/groupify/active_record/next_migration_version"
4
+
5
+ module Groupify
6
+ module ActiveRecord
7
+ class UpgradeGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+ extend NextMigrationVersion
10
+
11
+ source_root File.expand_path("../templates", __FILE__)
12
+
13
+ def create_migration_file
14
+ migration_template "upgrade_migration.rb", "db/migrate/add_group_type_to_group_memberships.rb"
15
+ end
16
+
17
+ def self.next_migration_number(dirname)
18
+ ::ActiveRecord::Generators::Base.next_migration_number dirname
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Groupify
2
+ module Mongoid
3
+ class InitializerGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def copy_initializer
7
+ copy_file "initializer.rb", "config/initializers/groupify.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ Groupify.configure do |config|
2
+ # Configure the default group class name.
3
+ # Defaults to 'Group'
4
+ # config.group_class_name = 'Group'
5
+ end
@@ -0,0 +1,12 @@
1
+ module Groupify
2
+ module Mongoid
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def invoke_generators
5
+ %w{ initializer model }.each do |name|
6
+ generate "groupify:mongoid:#{name}"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,11 @@
1
+ module Groupify
2
+ module Mongoid
3
+ class ModelGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def copy_group_model_file
7
+ copy_file "group.rb", "app/models/group.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class Group
2
+ include Mongoid::Document
3
+
4
+ groupify :group
5
+ end
@@ -1,3 +1,15 @@
1
1
  require 'active_support'
2
2
 
3
- require 'groupify/railtie' if defined?(Rails)
3
+ module Groupify
4
+ mattr_accessor :group_membership_class_name,
5
+ :group_class_name
6
+
7
+ self.group_class_name = 'Group'
8
+ self.group_membership_class_name = 'GroupMembership'
9
+
10
+ def self.configure
11
+ yield self
12
+ end
13
+ end
14
+
15
+ require 'groupify/railtie' if defined?(Rails)
@@ -3,7 +3,7 @@ module Groupify
3
3
 
4
4
  # Usage:
5
5
  # class Group < ActiveRecord::Base
6
- # acts_as_group, :members => [:users]
6
+ # groupify :group, members: [:users]
7
7
  # ...
8
8
  # end
9
9
  #
@@ -15,7 +15,10 @@ module Groupify
15
15
  included do
16
16
  @default_member_class = nil
17
17
  @member_klasses ||= Set.new
18
- has_many :group_memberships, :dependent => :destroy
18
+ has_many :group_memberships,
19
+ dependent: :destroy,
20
+ class_name: Groupify.group_membership_class_name
21
+
19
22
  end
20
23
 
21
24
  def member_classes
@@ -31,9 +34,9 @@ module Groupify
31
34
  clear_association_cache
32
35
 
33
36
  members.each do |member|
34
- member.group_memberships.where(group_id: self.id).first_or_create!
37
+ member.groups << self unless member.groups.include?(self)
35
38
  if membership_type
36
- member.group_memberships.where(group_id: self.id, membership_type: membership_type).first_or_create!
39
+ member.group_memberships.where(group_id: id, group_type: self.class.model_name.to_s, membership_type: membership_type).first_or_create!
37
40
  end
38
41
  member.clear_association_cache
39
42
  end
@@ -142,9 +145,19 @@ module Groupify
142
145
  source_type = member_klass.base_class
143
146
 
144
147
  if ActiveSupport::VERSION::MAJOR > 3
145
- has_many association_name, ->{ uniq }, through: :group_memberships, source: :member, source_type: source_type, extend: MemberAssociationExtensions
148
+ has_many association_name,
149
+ ->{ uniq },
150
+ through: :group_memberships,
151
+ source: :member,
152
+ source_type: source_type,
153
+ extend: MemberAssociationExtensions
146
154
  else
147
- has_many association_name, uniq: true, through: :group_memberships, source: :member, source_type: source_type, extend: MemberAssociationExtensions
155
+ has_many association_name,
156
+ uniq: true,
157
+ through: :group_memberships,
158
+ source: :member,
159
+ source_type: source_type,
160
+ extend: MemberAssociationExtensions
148
161
  end
149
162
 
150
163
  define_method(association_name) do |*args|
@@ -3,7 +3,7 @@ module Groupify
3
3
 
4
4
  # Usage:
5
5
  # class User < ActiveRecord::Base
6
- # acts_as_group_member
6
+ # groupify :group_member
7
7
  # ...
8
8
  # end
9
9
  #
@@ -14,13 +14,26 @@ module Groupify
14
14
 
15
15
  included do
16
16
  unless respond_to?(:group_memberships)
17
- has_many :group_memberships, as: :member, autosave: true, dependent: :destroy
17
+ has_many :group_memberships,
18
+ as: :member,
19
+ autosave: true,
20
+ dependent: :destroy,
21
+ class_name: Groupify.group_membership_class_name
18
22
  end
19
23
 
20
24
  if ActiveSupport::VERSION::MAJOR > 3
21
- has_many :groups, ->{ uniq }, through: :group_memberships, class_name: @group_class_name, extend: GroupAssociationExtensions
25
+ has_many :groups, ->{ uniq },
26
+ through: :group_memberships,
27
+ as: :group,
28
+ source_type: @group_class_name,
29
+ extend: GroupAssociationExtensions
22
30
  else
23
- has_many :groups, uniq: true, through: :group_memberships, class_name: @group_class_name, extend: GroupAssociationExtensions
31
+ has_many :groups,
32
+ uniq: true,
33
+ through: :group_memberships,
34
+ as: :group,
35
+ source_type: @group_class_name,
36
+ extend: GroupAssociationExtensions
24
37
  end
25
38
  end
26
39
 
@@ -92,9 +105,6 @@ module Groupify
92
105
  end
93
106
 
94
107
  module ClassMethods
95
- def group_class_name; @group_class_name ||= 'Group'; end
96
- def group_class_name=(klass); @group_class_name = klass; end
97
-
98
108
  def as(membership_type)
99
109
  joins(:group_memberships).where(group_memberships: { membership_type: membership_type })
100
110
  end
@@ -118,8 +128,8 @@ module Groupify
118
128
 
119
129
  joins(:group_memberships).
120
130
  group("#{quoted_table_name}.#{connection.quote_column_name('id')}").
121
- where(:group_memberships => {:group_id => groups.map(&:id)}).
122
- having("COUNT(group_memberships.group_id) = #{groups.count}").
131
+ where(group_memberships: {group_id: groups.map(&:id)}).
132
+ having("COUNT(#{reflect_on_association(:group_memberships).klass.quoted_table_name}.#{connection.quote_column_name('group_id')}) = ?", groups.count).
123
133
  uniq
124
134
  end
125
135
 
@@ -129,7 +139,7 @@ module Groupify
129
139
 
130
140
  joins(:group_memberships).
131
141
  group("#{quoted_table_name}.#{connection.quote_column_name('id')}").
132
- having("COUNT(DISTINCT group_memberships.group_id) = #{groups.count}").
142
+ having("COUNT(DISTINCT #{reflect_on_association(:group_memberships).klass.quoted_table_name}.#{connection.quote_column_name('group_id')}) = ?", groups.count).
133
143
  uniq
134
144
  end
135
145
 
@@ -5,7 +5,7 @@ module Groupify
5
5
  #
6
6
  # Usage:
7
7
  # class GroupMembership < ActiveRecord::Base
8
- # acts_as_group_membership
8
+ # groupify :group_membership
9
9
  # ...
10
10
  # end
11
11
  #
@@ -15,8 +15,8 @@ module Groupify
15
15
  included do
16
16
  attr_accessible(:member, :group, :group_name, :membership_type, :as) if ActiveSupport::VERSION::MAJOR < 4
17
17
 
18
- belongs_to :member, :polymorphic => true
19
- belongs_to :group
18
+ belongs_to :member, polymorphic: true
19
+ belongs_to :group, polymorphic: true
20
20
  end
21
21
 
22
22
  def membership_type=(membership_type)
@@ -33,7 +33,7 @@ module Groupify
33
33
  end
34
34
 
35
35
  def acts_as_group_member(opts = {})
36
- @group_class_name = opts[:class_name] || 'Group'
36
+ @group_class_name = opts[:group_class_name] || Groupify.group_class_name
37
37
  include Groupify::ActiveRecord::GroupMember
38
38
  end
39
39
 
@@ -14,7 +14,11 @@ module Groupify
14
14
 
15
15
  included do
16
16
  unless respond_to?(:group_memberships)
17
- has_many :group_memberships, :as => :member, :autosave => true, :dependent => :destroy
17
+ has_many :group_memberships,
18
+ as: :member,
19
+ autosave: true,
20
+ dependent: :destroy,
21
+ class_name: Groupify.group_membership_class_name
18
22
  end
19
23
  end
20
24
 
@@ -82,7 +86,7 @@ module Groupify
82
86
  joins(:group_memberships).
83
87
  group("#{quoted_table_name}.#{connection.quote_column_name('id')}").
84
88
  where(:group_memberships => {:group_name => named_groups}).
85
- having("COUNT(DISTINCT group_memberships.group_name) = #{named_groups.count}").
89
+ having("COUNT(DISTINCT #{reflect_on_association(:group_memberships).klass.quoted_table_name}.#{connection.quote_column_name('group_name')}) = ?", named_groups.count).
86
90
  uniq
87
91
  end
88
92
 
@@ -92,7 +96,7 @@ module Groupify
92
96
 
93
97
  joins(:group_memberships).
94
98
  group("#{quoted_table_name}.#{connection.quote_column_name('id')}").
95
- having("COUNT(DISTINCT group_memberships.group_name) = #{named_groups.count}").
99
+ having("COUNT(DISTINCT #{reflect_on_association(:group_memberships).klass.quoted_table_name}.#{connection.quote_column_name('group_name')}) = ?", named_groups.count).
96
100
  uniq
97
101
  end
98
102
 
@@ -5,7 +5,7 @@ module Groupify
5
5
  # class Group
6
6
  # include Mongoid::Document
7
7
  #
8
- # acts_as_group, :members => [:users]
8
+ # groupify :group, members: [:users]
9
9
  # ...
10
10
  # end
11
11
  #
@@ -136,7 +136,7 @@ module Groupify
136
136
  end
137
137
 
138
138
  def associate_member_class(member_klass)
139
- association_name ||= member_klass.model_name.plural.to_sym
139
+ association_name ||= member_klass.model_name.plural.to_sym
140
140
 
141
141
  has_many association_name, class_name: member_klass.to_s, dependent: :nullify, foreign_key: 'group_ids', extend: MemberAssociationExtensions
142
142
 
@@ -103,9 +103,6 @@ module Groupify
103
103
  end
104
104
 
105
105
  module ClassMethods
106
- def group_class_name; @group_class_name ||= 'Group'; end
107
- def group_class_name=(klass); @group_class_name = klass; end
108
-
109
106
  def in_group(group)
110
107
  group.present? ? self.in(group_ids: group.id) : none
111
108
  end
@@ -27,7 +27,7 @@ module Groupify
27
27
  end
28
28
 
29
29
  def acts_as_group_member(opts = {})
30
- @group_class_name = opts[:class_name] || 'Group'
30
+ @group_class_name = opts[:group_class_name] || Groupify.group_class_name
31
31
  include Groupify::Mongoid::GroupMember
32
32
  end
33
33
 
@@ -1,3 +1,3 @@
1
1
  module Groupify
2
- VERSION = "0.6.3"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -70,6 +70,10 @@ class GroupMembership < ActiveRecord::Base
70
70
  groupify :group_membership
71
71
  end
72
72
 
73
+ class Classroom < ActiveRecord::Base
74
+ groupify :group
75
+ end
76
+
73
77
  describe Group do
74
78
  it { should respond_to :members}
75
79
  it { should respond_to :add }
@@ -88,11 +92,63 @@ if DEBUG
88
92
  end
89
93
 
90
94
  describe Groupify::ActiveRecord do
91
- let!(:user) { User.create! }
92
- let!(:group) { Group.create! }
95
+ let(:user) { User.create! }
96
+ let(:group) { Group.create! }
93
97
  let(:widget) { Widget.create! }
94
98
  let(:namespaced_member) { Namespaced::Member.create! }
95
99
 
100
+ describe "configuration" do
101
+ context "globally configured group and group membership models" do
102
+ before do
103
+ Groupify.configure do |config|
104
+ config.group_class_name = 'CustomGroup'
105
+ config.group_membership_class_name = 'CustomGroupMembership'
106
+ end
107
+
108
+ class CustomGroupMembership < ActiveRecord::Base
109
+ groupify :group_membership
110
+ end
111
+
112
+ class CustomUser < ActiveRecord::Base
113
+ groupify :group_member
114
+ end
115
+
116
+ class CustomGroup < ActiveRecord::Base
117
+ groupify :group
118
+ end
119
+ end
120
+
121
+ after do
122
+ Groupify.configure do |config|
123
+ config.group_class_name = 'Group'
124
+ config.group_membership_class_name = 'GroupMembership'
125
+ end
126
+ end
127
+
128
+ it "uses the custom models to store groups and group memberships" do
129
+ custom_user = CustomUser.create!
130
+ custom_group = CustomGroup.create!
131
+ custom_user.groups << custom_group
132
+ expect(GroupMembership.count).to eq(0)
133
+ expect(CustomGroupMembership.count).to eq(1)
134
+ end
135
+ end
136
+
137
+ context "member with custom group model" do
138
+ before do
139
+ class ProjectMember < ActiveRecord::Base
140
+ groupify :group_member, group_class_name: 'Project'
141
+ end
142
+ end
143
+
144
+ it "overrides the default group name on a per-model basis" do
145
+ member = ProjectMember.create!
146
+ member.groups.create!
147
+ expect(member.groups.first).to be_a Project
148
+ end
149
+ end
150
+ end
151
+
96
152
  context 'when using groups' do
97
153
  it "members and groups are empty when initialized" do
98
154
  expect(user.groups).to be_empty
@@ -101,37 +157,51 @@ describe Groupify::ActiveRecord do
101
157
  expect(Group.new.members).to be_empty
102
158
  expect(group.members).to be_empty
103
159
  end
104
-
105
- it "adds a group to a member" do
106
- user.groups << group
107
- expect(user.groups).to include(group)
108
- expect(group.members).to include(user)
109
- expect(group.users).to include(user)
110
- end
111
-
112
- it "adds a member to a group" do
113
- expect(user.groups).to be_empty
114
- group.add user
115
- expect(user.groups).to include(group)
116
- expect(group.members).to include(user)
117
- end
118
160
 
119
- it "adds a namespaced member to a group" do
120
- group.add(namespaced_member)
121
- expect(group.namespaced_members).to include(namespaced_member)
122
- end
161
+ context "when adding" do
162
+ it "adds a group to a member" do
163
+ user.groups << group
164
+ expect(user.groups).to include(group)
165
+ expect(group.members).to include(user)
166
+ expect(group.users).to include(user)
167
+ end
168
+
169
+ it "adds a member to a group" do
170
+ expect(user.groups).to be_empty
171
+ group.add user
172
+ expect(user.groups).to include(group)
173
+ expect(group.members).to include(user)
174
+ end
123
175
 
124
- it "adds multiple members to a group" do
125
- group.add(user, widget)
126
- expect(group.users).to include(user)
127
- expect(group.widgets).to include(widget)
176
+ it "only adds a member to a group once" do
177
+ group.add user
178
+ group.add user
179
+ expect(user.group_memberships.count).to eq(1)
180
+ end
181
+
182
+ it "adds a namespaced member to a group" do
183
+ group.add(namespaced_member)
184
+ expect(group.namespaced_members).to include(namespaced_member)
185
+ end
128
186
 
129
- users = [User.create!, User.create!]
130
- group.add(users)
131
- expect(group.users).to include(*users)
187
+ it "adds multiple members to a group" do
188
+ group.add(user, widget)
189
+ expect(group.users).to include(user)
190
+ expect(group.widgets).to include(widget)
191
+
192
+ users = [User.create!, User.create!]
193
+ group.add(users)
194
+ expect(group.users).to include(*users)
195
+ end
196
+
197
+ it "only allows members to be added to their configured group type" do
198
+ classroom = Classroom.create!
199
+ expect { classroom.add(user) }.to raise_error(ActiveRecord::AssociationTypeMismatch)
200
+ expect { user.groups << classroom }.to raise_error(ActiveRecord::AssociationTypeMismatch)
201
+ end
132
202
  end
133
203
 
134
- it 'lists which member classes can belong to this group' do
204
+ it "lists which member classes can belong to this group" do
135
205
  expect(group.class.member_classes).to include(User, Widget)
136
206
  expect(group.member_classes).to include(User, Widget)
137
207
 
@@ -590,6 +660,4 @@ describe Groupify::ActiveRecord do
590
660
  end
591
661
  end
592
662
  end
593
-
594
-
595
663
  end
@@ -5,10 +5,9 @@ ActiveRecord::Schema.define(version: 0) do
5
5
  end
6
6
 
7
7
  create_table :group_memberships do |t|
8
- t.string :member_type
9
- t.integer :member_id
10
- t.integer :group_id
11
- t.string :group_name
8
+ t.references :member, polymorphic: true, index: true
9
+ t.references :group, polymorphic: true, index: true
10
+ t.string :group_name, index: true
12
11
  t.string :membership_type
13
12
  end
14
13
 
@@ -32,4 +31,29 @@ ActiveRecord::Schema.define(version: 0) do
32
31
  create_table :members do |t|
33
32
  t.string :name
34
33
  end
34
+
35
+ create_table :classrooms do |t|
36
+ t.string :name
37
+ end
38
+
39
+ create_table :custom_group_memberships do |t|
40
+ t.references :member, polymorphic: true, index: true
41
+ t.references :group, polymorphic: true, index: true
42
+ t.string :group_name, index: true
43
+ t.string :membership_type
44
+ end
45
+
46
+ create_table :custom_groups do |t|
47
+ t.string :name
48
+ t.string :type
49
+ end
50
+
51
+ create_table :custom_users do |t|
52
+ t.string :name
53
+ t.string :type
54
+ end
55
+
56
+ create_table :project_members do |t|
57
+ t.string :name
58
+ end
35
59
  end
@@ -35,7 +35,7 @@ require 'groupify/adapter/mongoid'
35
35
  class MongoidUser
36
36
  include Mongoid::Document
37
37
 
38
- groupify :group_member, class_name: 'MongoidGroup'
38
+ groupify :group_member, group_class_name: 'MongoidGroup'
39
39
  groupify :named_group_member
40
40
  end
41
41
 
@@ -44,19 +44,19 @@ end
44
44
 
45
45
  class MongoidWidget
46
46
  include Mongoid::Document
47
- groupify :group_member, class_name: 'MongoidGroup'
47
+ groupify :group_member, group_class_name: 'MongoidGroup'
48
48
  end
49
49
 
50
50
  class MongoidTask
51
51
  include Mongoid::Document
52
52
 
53
- groupify :group_member, class_name: 'MongoidGroup'
53
+ groupify :group_member, group_class_name: 'MongoidGroup'
54
54
  end
55
55
 
56
56
  class MongoidIssue
57
57
  include Mongoid::Document
58
58
 
59
- groupify :group_member, class_name: 'MongoidProject'
59
+ groupify :group_member, group_class_name: 'MongoidProject'
60
60
  end
61
61
 
62
62
  class MongoidGroup
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groupify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dwbutler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-24 00:00:00.000000000 Z
11
+ date: 2015-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -100,6 +100,20 @@ dependencies:
100
100
  - - ">="
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: github_changelog_generator
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
103
117
  description: Adds group and membership functionality to Rails models
104
118
  email:
105
119
  - dwbutler@ucla.edu
@@ -112,6 +126,7 @@ files:
112
126
  - ".rspec"
113
127
  - ".travis.yml"
114
128
  - Appraisals
129
+ - CHANGELOG.md
115
130
  - Gemfile
116
131
  - LICENSE
117
132
  - README.md
@@ -121,6 +136,22 @@ files:
121
136
  - gemfiles/rails_4.1.gemfile
122
137
  - gemfiles/rails_4.2.gemfile
123
138
  - groupify.gemspec
139
+ - lib/generators/groupify/active_record/initializer/initializer_generator.rb
140
+ - lib/generators/groupify/active_record/initializer/templates/initializer.rb
141
+ - lib/generators/groupify/active_record/install/install_generator.rb
142
+ - lib/generators/groupify/active_record/migration/migration_generator.rb
143
+ - lib/generators/groupify/active_record/migration/templates/migration.rb
144
+ - lib/generators/groupify/active_record/model/model_generator.rb
145
+ - lib/generators/groupify/active_record/model/templates/group.rb
146
+ - lib/generators/groupify/active_record/model/templates/group_membership.rb
147
+ - lib/generators/groupify/active_record/next_migration_version.rb
148
+ - lib/generators/groupify/active_record/upgrade/templates/upgrade_migration.rb
149
+ - lib/generators/groupify/active_record/upgrade/upgrade_generator.rb
150
+ - lib/generators/groupify/mongoid/initializer/initializer_generator.rb
151
+ - lib/generators/groupify/mongoid/initializer/templates/initializer.rb
152
+ - lib/generators/groupify/mongoid/install/install_generator.rb
153
+ - lib/generators/groupify/mongoid/model/model_generator.rb
154
+ - lib/generators/groupify/mongoid/model/templates/group.rb
124
155
  - lib/groupify.rb
125
156
  - lib/groupify/adapter/active_record.rb
126
157
  - lib/groupify/adapter/active_record/group.rb