adhocracy 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.rdoc +183 -2
- data/app/models/adhocracy/membership.rb +1 -1
- data/app/models/adhocracy/membership_invitation.rb +1 -23
- data/app/models/adhocracy/membership_request.rb +1 -23
- data/config/locales/en.yml +3 -1
- data/db/migrate/20140306214416_create_adhocracy_memberships.rb +2 -0
- data/lib/adhocracy/acts_as_group.rb +26 -0
- data/lib/adhocracy/joinable.rb +71 -0
- data/lib/adhocracy/version.rb +1 -1
- data/lib/adhocracy.rb +1 -0
- data/spec/dummy/db/schema.rb +2 -0
- data/spec/lib/adhocracy/acts_as_group_spec.rb +75 -1
- data/spec/lib/adhocracy/acts_as_member_spec.rb +6 -0
- data/spec/spec_helper.rb +3 -0
- metadata +49 -34
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MGIyMWQyYTE2OGZmM2MzMDRhNmJkYzYyZDcwMGM3ZWQzMDBkZDNjMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjdhYWMwMTNlYmE2YzYzNDYyNGQ3MTE3ZWRhY2RkMmYyYjczNzNlNA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmYwZjA2ZDYxNzcwOTFmZDE3NDQzYWM2MWNkMjM2MTg1ODUxYjhkMGQyOTBm
|
10
|
+
OWUwODM3ZmE0MzNjNzllZjE5ZDQ3MWFkYTA1MmM2NzgwMTAzY2ExYzc5YmZi
|
11
|
+
ZTEzOGE0YmQ4YzU2ZDIyYWM4ZWYwMDQ5MjgyZWJmZTNhM2Q2NGU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTdkYjk0MGJmNzRiN2VjNmI1ZGUyMGI1NTVkZTE2NzE2OTliNDBjZTNiOWY4
|
14
|
+
NmNmNGE4ZDFmOTQ2MzFiNGNhMzQzZjRiODk4NzFhZmJkZjEwOTdmNjA1NDg3
|
15
|
+
NTU4YTg3MDZhYjUzODU2OTg1MTY5ZDAwOWMzOGUxNmI4OGUyZTg=
|
data/README.rdoc
CHANGED
@@ -1,3 +1,184 @@
|
|
1
|
-
= Adhocracy {<img src="https://badge.fury.io/rb/adhocracy.png" alt="Gem Version" />}[http://badge.fury.io/rb/adhocracy] {<img src="https://travis-ci.org/timothycommoner/adhocracy.png?branch=master" alt="Build Status" />}[https://travis-ci.org/timothycommoner/adhocracy] {<img src="https://codeclimate.com/github/timothycommoner/adhocracy.png" />}[https://codeclimate.com/github/timothycommoner/adhocracy]
|
1
|
+
= Adhocracy {<img src="https://badge.fury.io/rb/adhocracy.png" alt="Gem Version" />}[http://badge.fury.io/rb/adhocracy] {<img src="https://travis-ci.org/timothycommoner/adhocracy.png?branch=master" alt="Build Status" />}[https://travis-ci.org/timothycommoner/adhocracy] {<img src="https://coveralls.io/repos/timothycommoner/adhocracy/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/timothycommoner/adhocracy] {<img src="https://codeclimate.com/github/timothycommoner/adhocracy.png" />}[https://codeclimate.com/github/timothycommoner/adhocracy]
|
2
2
|
|
3
|
-
A group management engine for Rails.
|
3
|
+
A group management engine for Rails.
|
4
|
+
|
5
|
+
== Compatibility
|
6
|
+
|
7
|
+
Adhocracy is a Rails Engine, which means it plays best with Rails applications. So far, it's only been tested with Rails 4.
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
=== Installation
|
12
|
+
|
13
|
+
1. Add Adhocracy to your gemfile: `gem 'adhocracy'`
|
14
|
+
2. Run bundler: `bundle install`
|
15
|
+
3. Run this in your app folder: `rake adhocracy:install:migrations`
|
16
|
+
4. Run your migrations: `rake db:migrate`
|
17
|
+
5. Add `acts_as_group` to the models you want to have group functionality
|
18
|
+
6. Add `acts_as_member` to the models you want to have member functionality
|
19
|
+
|
20
|
+
=== Creating Groups and Members
|
21
|
+
|
22
|
+
Scenario: You want your Club model to have group functionality. Ideally, it'll accept members from both the Student and Teacher model.
|
23
|
+
|
24
|
+
First, add `acts_as_group` to your Club model:
|
25
|
+
|
26
|
+
class Club < ActiveRecord::Base
|
27
|
+
acts_as_group
|
28
|
+
end
|
29
|
+
|
30
|
+
Then, add 'acts_as_member' to your Student and Teacher models:
|
31
|
+
|
32
|
+
class Student < ActiveRecord::Base
|
33
|
+
acts_as_member
|
34
|
+
end
|
35
|
+
|
36
|
+
class Teacher < ActiveRecord::Base
|
37
|
+
acts_as_member
|
38
|
+
end
|
39
|
+
|
40
|
+
After that, you can add members to your Club by:
|
41
|
+
|
42
|
+
@club.add_member(@student)
|
43
|
+
@student.join_group(@club)
|
44
|
+
@teacher.join_group(@club)
|
45
|
+
|
46
|
+
List the current members:
|
47
|
+
|
48
|
+
@club.members # => returns an array with @student and @teacher in it
|
49
|
+
|
50
|
+
Or list the groups a member is a part of:
|
51
|
+
|
52
|
+
@student.groups # => returns an array with only @club
|
53
|
+
|
54
|
+
Check for membership:
|
55
|
+
|
56
|
+
@student.member_of?(@club) # => true
|
57
|
+
@club.has_member?(@teacher) # => true
|
58
|
+
|
59
|
+
And destroy memberships
|
60
|
+
|
61
|
+
@student.leave_group(@club)
|
62
|
+
@group.remove_member(@teacher)
|
63
|
+
|
64
|
+
=== Officers
|
65
|
+
|
66
|
+
Scenario: You want a special class of membership that has the privilege to edit the group and accept/invite new members.
|
67
|
+
|
68
|
+
Adhocracy allows for administrative members called officers. You can create a new officer with:
|
69
|
+
|
70
|
+
@club.add_officer(@student)
|
71
|
+
|
72
|
+
Alternatively, if `@student` is already a member, you can promote her with:
|
73
|
+
|
74
|
+
@club.promote_to_officer(@student)
|
75
|
+
|
76
|
+
Later, you can strip an officer of her title with:
|
77
|
+
|
78
|
+
@club.demote_officer(@student)
|
79
|
+
|
80
|
+
=== Inviting Members
|
81
|
+
|
82
|
+
Scenario: You want your users to have control over which groups they join.
|
83
|
+
|
84
|
+
Groups can send invitations to users:
|
85
|
+
|
86
|
+
@club.invite_member(@student)
|
87
|
+
@student.groups # => does not yet include @club
|
88
|
+
@student.group_invitations # => array including @club
|
89
|
+
|
90
|
+
The user can either accept or decline:
|
91
|
+
|
92
|
+
@invitation = @student.membership_invitations.first
|
93
|
+
@invitation.accept
|
94
|
+
- or -
|
95
|
+
@invitation.decline
|
96
|
+
|
97
|
+
If they accept, then they become a member of the group.
|
98
|
+
|
99
|
+
Invitations can be queried for their state of acceptance:
|
100
|
+
|
101
|
+
@invitation.pending?
|
102
|
+
@invitation.accepted?
|
103
|
+
@invitation.declined?
|
104
|
+
|
105
|
+
You can also check to see if an invitation is already sent:
|
106
|
+
|
107
|
+
@student.invited_to?(@club)
|
108
|
+
@club.invited?(@student)
|
109
|
+
|
110
|
+
These checks can include the state of the invitation:
|
111
|
+
|
112
|
+
@student.invited_to?(@club, { pending: true })
|
113
|
+
@student.invited_to?(@club, { accepted: false })
|
114
|
+
@student.invited_to?(@club, { declined: false })
|
115
|
+
|
116
|
+
=== Requesting Membership
|
117
|
+
|
118
|
+
Scenario: You want your groups to have control over which users join them.
|
119
|
+
|
120
|
+
Interested users can send membership requests to groups:
|
121
|
+
|
122
|
+
@student.request_membership_in(@club)
|
123
|
+
@club.members # => does not yet include @student
|
124
|
+
@club.membership_requests # => array including @student
|
125
|
+
|
126
|
+
The group can either accept or decline:
|
127
|
+
|
128
|
+
@request = @club.membership_requests.first
|
129
|
+
@request.accept
|
130
|
+
- or -
|
131
|
+
@request.decline
|
132
|
+
|
133
|
+
Requests can be queried for their state of acceptance:
|
134
|
+
|
135
|
+
@request.pending?
|
136
|
+
@request.accepted?
|
137
|
+
@request.declined?
|
138
|
+
|
139
|
+
You can also check to see if a request is already sent:
|
140
|
+
|
141
|
+
@student.requested_membership_in?(@club)
|
142
|
+
@club.recieved_request_from?(@student)
|
143
|
+
|
144
|
+
These checks can include the state of the request:
|
145
|
+
|
146
|
+
@student.requested_membership_in?(@club, { pending: true })
|
147
|
+
@student.requested_membership_in?(@club, { accepted: false })
|
148
|
+
@student.requested_membership_in?(@club, { declined: false })
|
149
|
+
|
150
|
+
=== Nesting Groups
|
151
|
+
|
152
|
+
Scenario: You want your Company model to have many subsidiary companies.
|
153
|
+
|
154
|
+
Create a model that both `acts_as_group` and `acts_as_member`:
|
155
|
+
|
156
|
+
class Company < ActiveRecord::Base
|
157
|
+
acts_as_group
|
158
|
+
acts_as_member
|
159
|
+
end
|
160
|
+
|
161
|
+
You can then nest companies like you would any other member:
|
162
|
+
|
163
|
+
@company.add_member(@child_company)
|
164
|
+
@child_company.add_member(@grand_child_company)
|
165
|
+
|
166
|
+
== Limitations
|
167
|
+
|
168
|
+
Unfortunately, Rails does not support `has_many through` relationships that pass through a polymorphic join table, which we do in Adhocracy. In order to work around this limitation, we've created pseudo-associations, such as `@club.members` and `@user.groups`. These pseudo-associations return a simple array, rather than the feature-packed associations Rails typically uses. This means you can't chain in scopes or use commands like `@user.groups.create`. If you know of a way we can reincorporate Rails associations without losing our ability to join groups and members polymorphically, please share your thoughts!
|
169
|
+
|
170
|
+
== Issues
|
171
|
+
|
172
|
+
Adhocracy is still very young, and both its functionality and its documentation are bound to be lacking. If you're having trouble with something, feel free to open an issue.
|
173
|
+
|
174
|
+
== Contributing
|
175
|
+
|
176
|
+
Feel free to send us a pull request. Public methods, callbacks, and validations should have Rspec tests to back them up.
|
177
|
+
|
178
|
+
=== Contributors
|
179
|
+
|
180
|
+
Timothy Baron
|
181
|
+
|
182
|
+
== License
|
183
|
+
|
184
|
+
Released under the MIT license.
|
@@ -1,31 +1,9 @@
|
|
1
1
|
module Adhocracy
|
2
2
|
class MembershipInvitation < ActiveRecord::Base
|
3
3
|
include Acceptable
|
4
|
+
include Joinable
|
4
5
|
|
5
6
|
belongs_to :member, polymorphic: true
|
6
7
|
belongs_to :group, polymorphic: true
|
7
|
-
|
8
|
-
validate :no_pending_invitations, on: :create
|
9
|
-
validate :no_declined_invitations, on: :create
|
10
|
-
validate :not_currently_a_member, on: :create
|
11
|
-
|
12
|
-
private
|
13
|
-
def no_pending_invitations
|
14
|
-
if self.member.invited_to?(self.group, { pending: true })
|
15
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_invitation.still_pending")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def no_declined_invitations
|
20
|
-
if self.member.invited_to?(self.group, { declined: true })
|
21
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_invitation.already_declined")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def not_currently_a_member
|
26
|
-
if self.member.member_of?(self.group)
|
27
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_invitation.already_a_member")
|
28
|
-
end
|
29
|
-
end
|
30
8
|
end
|
31
9
|
end
|
@@ -1,31 +1,9 @@
|
|
1
1
|
module Adhocracy
|
2
2
|
class MembershipRequest < ActiveRecord::Base
|
3
3
|
include Acceptable
|
4
|
+
include Joinable
|
4
5
|
|
5
6
|
belongs_to :member, polymorphic: true
|
6
7
|
belongs_to :group, polymorphic: true
|
7
|
-
|
8
|
-
validate :no_pending_requests, on: :create
|
9
|
-
validate :no_declined_requests, on: :create
|
10
|
-
validate :not_currently_a_member, on: :create
|
11
|
-
|
12
|
-
private
|
13
|
-
def no_pending_requests
|
14
|
-
if self.member.requested_membership_in?(self.group, { pending: true })
|
15
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_request.still_pending")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def no_declined_requests
|
20
|
-
if self.member.requested_membership_in?(self.group, { declined: true })
|
21
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_request.already_declined")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def not_currently_a_member
|
26
|
-
if self.member.member_of?(self.group)
|
27
|
-
errors[:base] << I18n.t("activerecord.errors.models.membership_request.already_a_member")
|
28
|
-
end
|
29
|
-
end
|
30
8
|
end
|
31
9
|
end
|
data/config/locales/en.yml
CHANGED
@@ -8,7 +8,9 @@ en:
|
|
8
8
|
still_pending: "Invitation still pending."
|
9
9
|
already_declined: "Cannot invite member again."
|
10
10
|
already_a_member: "Already a member."
|
11
|
+
other_party_had_pending_request: "The member already sent a request. Membership automatically accepted."
|
11
12
|
membership_request:
|
12
13
|
still_pending: "Request still pending."
|
13
14
|
already_declined: "Cannot request membership again."
|
14
|
-
already_a_member: "Already a member."
|
15
|
+
already_a_member: "Already a member."
|
16
|
+
other_party_had_pending_request: "The group already sent an invitation. Membership automatically accepted."
|
@@ -5,10 +5,12 @@ class CreateAdhocracyMemberships < ActiveRecord::Migration
|
|
5
5
|
t.integer :member_id
|
6
6
|
t.string :group_type
|
7
7
|
t.integer :group_id
|
8
|
+
t.boolean :officer, null: false, default: false
|
8
9
|
|
9
10
|
t.timestamps
|
10
11
|
end
|
11
12
|
|
13
|
+
add_index :adhocracy_memberships, :officer
|
12
14
|
add_index :adhocracy_memberships,
|
13
15
|
[:member_id, :member_type],
|
14
16
|
name: "adhocracy_memberships_on_member"
|
@@ -10,6 +10,8 @@ module Adhocracy
|
|
10
10
|
class_name: "Adhocracy::MembershipInvitation"
|
11
11
|
has_many :membership_requests, as: :group,
|
12
12
|
class_name: "Adhocracy::MembershipRequest"
|
13
|
+
has_many :officer_memberships, -> { where officer: true }, as: :group,
|
14
|
+
class_name: "Adhocracy::Membership"
|
13
15
|
|
14
16
|
send :include, InstanceMethods
|
15
17
|
end
|
@@ -20,6 +22,11 @@ module Adhocracy
|
|
20
22
|
MembershipAssociation.new(group: self).list_members_for_membership
|
21
23
|
end
|
22
24
|
|
25
|
+
def officers
|
26
|
+
Adhocracy::Membership.where(group: self, officer: true).
|
27
|
+
includes(:member).collect { |membership| membership.member }
|
28
|
+
end
|
29
|
+
|
23
30
|
def invited_members
|
24
31
|
MembershipAssociation.new(group: self).
|
25
32
|
list_members_for_membership_invitation
|
@@ -35,6 +42,25 @@ module Adhocracy
|
|
35
42
|
create_membership
|
36
43
|
end
|
37
44
|
|
45
|
+
def add_officer(member)
|
46
|
+
membership = Adhocracy::Membership.where(member: member, group: self).
|
47
|
+
first_or_create(officer: true)
|
48
|
+
promote_to_officer(member, membership) unless membership.officer?
|
49
|
+
membership
|
50
|
+
end
|
51
|
+
|
52
|
+
def promote_to_officer(member, membership = nil)
|
53
|
+
membership ||= Adhocracy::Membership.find_by(member: member, group: self)
|
54
|
+
return false if !membership.present? || membership.officer?
|
55
|
+
return membership.update_column(:officer, true)
|
56
|
+
end
|
57
|
+
|
58
|
+
def demote_officer(member)
|
59
|
+
membership = Adhocracy::Membership.find_by(member: member, group: self)
|
60
|
+
return false if !membership.present? || !membership.officer?
|
61
|
+
return membership.update_column(:officer, false)
|
62
|
+
end
|
63
|
+
|
38
64
|
def invite_member(member)
|
39
65
|
MembershipAssociation.new(member: member, group: self).
|
40
66
|
create_membership_invitation
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
module Joinable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
validate :no_pending_joins, on: :create
|
7
|
+
validate :no_declined_joins, on: :create
|
8
|
+
validate :not_currently_a_member, on: :create
|
9
|
+
validate :other_party_has_pending_request, on: :create
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def detect_preexisting_join(state, inverted = false)
|
14
|
+
self.member.send(query_symbol(inverted), self.group, { state => true })
|
15
|
+
end
|
16
|
+
|
17
|
+
def no_pending_joins
|
18
|
+
if detect_preexisting_join(:pending)
|
19
|
+
errors[:base] << I18n.t("activerecord.errors.models.membership_#{i18n_string}.still_pending")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def no_declined_joins
|
24
|
+
if detect_preexisting_join(:declined)
|
25
|
+
errors[:base] << I18n.t("activerecord.errors.models.membership_#{i18n_string}.already_declined")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def not_currently_a_member
|
30
|
+
if self.member.member_of?(self.group)
|
31
|
+
errors[:base] << I18n.t("activerecord.errors.models.membership_#{i18n_string}.already_a_member")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def other_party_has_pending_request
|
36
|
+
if detect_preexisting_join(:pending, true)
|
37
|
+
accept_preexisting_join
|
38
|
+
errors[:base] << I18n.t("activerecord.errors.models.membership_#{i18n_string}.other_party_had_pending_request")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def i18n_string
|
43
|
+
return case self.class.name
|
44
|
+
when "Adhocracy::MembershipInvitation" then "invitation"
|
45
|
+
when "Adhocracy::MembershipRequest" then "request"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def query_symbol(inverted)
|
50
|
+
test_class = inverted == false ? self.class.name : inverted_class
|
51
|
+
return case test_class
|
52
|
+
when "Adhocracy::MembershipInvitation" then :invited_to?
|
53
|
+
when "Adhocracy::MembershipRequest" then :requested_membership_in?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def inverted_class
|
58
|
+
return case self.class.name
|
59
|
+
when "Adhocracy::MembershipInvitation"
|
60
|
+
"Adhocracy::MembershipRequest"
|
61
|
+
when "Adhocracy::MembershipRequest"
|
62
|
+
"Adhocracy::MembershipInvitation"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def accept_preexisting_join
|
67
|
+
inverted_class.constantize.where(member: self.member, group: self.group).
|
68
|
+
first.accept
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/adhocracy/version.rb
CHANGED
data/lib/adhocracy.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -49,6 +49,7 @@ ActiveRecord::Schema.define(version: 20140306214620) do
|
|
49
49
|
t.integer "member_id"
|
50
50
|
t.string "group_type"
|
51
51
|
t.integer "group_id"
|
52
|
+
t.boolean "officer", default: false, null: false
|
52
53
|
t.datetime "created_at"
|
53
54
|
t.datetime "updated_at"
|
54
55
|
end
|
@@ -57,6 +58,7 @@ ActiveRecord::Schema.define(version: 20140306214620) do
|
|
57
58
|
add_index "adhocracy_memberships", ["group_id", "group_type"], name: "adhocracy_membership_requests_on_group", using: :btree
|
58
59
|
add_index "adhocracy_memberships", ["group_id", "group_type"], name: "adhocracy_memberships_on_group", using: :btree
|
59
60
|
add_index "adhocracy_memberships", ["member_id", "member_type"], name: "adhocracy_memberships_on_member", using: :btree
|
61
|
+
add_index "adhocracy_memberships", ["officer"], name: "index_adhocracy_memberships_on_officer", using: :btree
|
60
62
|
|
61
63
|
create_table "adhocs", force: true do |t|
|
62
64
|
end
|
@@ -19,6 +19,10 @@ module Adhocracy
|
|
19
19
|
it "membership invitations" do
|
20
20
|
expect(@adhoc).to have_many(:membership_invitations)
|
21
21
|
end
|
22
|
+
|
23
|
+
it "officer memberships" do
|
24
|
+
expect(@adhoc).to have_many(:officer_memberships)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
context "produces a list" do
|
@@ -30,7 +34,7 @@ module Adhocracy
|
|
30
34
|
@user4 = FactoryGirl.create(:user)
|
31
35
|
@user5 = FactoryGirl.create(:user)
|
32
36
|
@adhoc.add_member(@user1)
|
33
|
-
@adhoc.
|
37
|
+
@adhoc.add_officer(@user3)
|
34
38
|
@adhoc.invite_member(@user4)
|
35
39
|
@user5.request_membership_in(@adhoc)
|
36
40
|
end
|
@@ -43,6 +47,14 @@ module Adhocracy
|
|
43
47
|
expect(@adhoc.members).to_not include @user2, @user4, @user5
|
44
48
|
end
|
45
49
|
|
50
|
+
it "including all officers" do
|
51
|
+
expect(@adhoc.officers).to include @user3
|
52
|
+
end
|
53
|
+
|
54
|
+
it "excluding non-officers" do
|
55
|
+
expect(@adhoc.officers).to_not include @user1, @user2, @user4, @user5
|
56
|
+
end
|
57
|
+
|
46
58
|
it "including all invited members" do
|
47
59
|
expect(@adhoc.invited_members).to include @user4
|
48
60
|
end
|
@@ -136,6 +148,16 @@ module Adhocracy
|
|
136
148
|
expect(@adhoc.add_member(@user).valid?).to be false
|
137
149
|
end
|
138
150
|
|
151
|
+
it "creating officers" do
|
152
|
+
@adhoc.add_officer(@user)
|
153
|
+
expect(@adhoc.officers).to include @user
|
154
|
+
end
|
155
|
+
|
156
|
+
it "not creating duplicate officers" do
|
157
|
+
@adhoc.add_officer(@user)
|
158
|
+
expect(@adhoc.add_officer(@user).valid?).to be false
|
159
|
+
end
|
160
|
+
|
139
161
|
it "inviting members" do
|
140
162
|
@adhoc.invite_member(@user)
|
141
163
|
expect(@adhoc.invited_members).to include @user
|
@@ -156,6 +178,12 @@ module Adhocracy
|
|
156
178
|
@adhoc.add_member(@user)
|
157
179
|
expect(@adhoc.invite_member(@user).valid?).to be false
|
158
180
|
end
|
181
|
+
|
182
|
+
it "accepting invited members if they've requested membership" do
|
183
|
+
@user.request_membership_in(@adhoc)
|
184
|
+
expect(@adhoc.invite_member(@user).valid?).to be false
|
185
|
+
expect(@adhoc.members).to include @user
|
186
|
+
end
|
159
187
|
end
|
160
188
|
|
161
189
|
context "destroys memberships" do
|
@@ -175,5 +203,51 @@ module Adhocracy
|
|
175
203
|
end
|
176
204
|
end
|
177
205
|
|
206
|
+
context "promotes members to officers" do
|
207
|
+
before :each do
|
208
|
+
@adhoc = FactoryGirl.create(:adhoc)
|
209
|
+
@user = FactoryGirl.create(:user)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "if the member is a non-officer" do
|
213
|
+
@adhoc.add_member(@user)
|
214
|
+
@adhoc.promote_to_officer(@user)
|
215
|
+
expect(@adhoc.officers).to include @user
|
216
|
+
end
|
217
|
+
|
218
|
+
it "if the member is a non-officer member (and add_officer is used)" do
|
219
|
+
@adhoc.add_member(@user)
|
220
|
+
@adhoc.add_officer(@user)
|
221
|
+
expect(@adhoc.officers).to include @user
|
222
|
+
end
|
223
|
+
|
224
|
+
it "but returns false if the user is not a member" do
|
225
|
+
expect(@adhoc.promote_to_officer(@user)).to be false
|
226
|
+
end
|
227
|
+
|
228
|
+
it "but returns false if the member is already an officer" do
|
229
|
+
@adhoc.add_officer(@user)
|
230
|
+
expect(@adhoc.promote_to_officer(@user)).to be false
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "demotes officers" do
|
235
|
+
before :each do
|
236
|
+
@adhoc = FactoryGirl.create(:adhoc)
|
237
|
+
@user = FactoryGirl.create(:user)
|
238
|
+
end
|
239
|
+
|
240
|
+
it "if the member is an officer" do
|
241
|
+
@adhoc.add_officer(@user)
|
242
|
+
@adhoc.demote_officer(@user)
|
243
|
+
expect(@adhoc.officers).to_not include @user
|
244
|
+
end
|
245
|
+
|
246
|
+
it "but returns false if the member is not an officer" do
|
247
|
+
@adhoc.add_member(@user)
|
248
|
+
expect(@adhoc.demote_officer(@user)).to be false
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
178
252
|
end
|
179
253
|
end
|
@@ -118,6 +118,12 @@ module Adhocracy
|
|
118
118
|
expect(@user.requested_membership_in?(@adhoc, { pending: true })).
|
119
119
|
to be false
|
120
120
|
end
|
121
|
+
|
122
|
+
it "accepting requested groups if they've already invited membership" do
|
123
|
+
@adhoc.invite_member(@user)
|
124
|
+
expect(@user.request_membership_in(@adhoc).valid?).to be false
|
125
|
+
expect(@user.groups).to include @adhoc
|
126
|
+
end
|
121
127
|
end
|
122
128
|
|
123
129
|
context "handles prospective groups by" do
|
data/spec/spec_helper.rb
CHANGED
@@ -10,6 +10,9 @@ Spork.prefork do
|
|
10
10
|
require 'database_cleaner'
|
11
11
|
require 'shoulda'
|
12
12
|
require 'debugger'
|
13
|
+
require 'coveralls'
|
14
|
+
|
15
|
+
Coveralls.wear!('rails')
|
13
16
|
|
14
17
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
15
18
|
# in spec/support/ and its subdirectories.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adhocracy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- timothycommoner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ! '>='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: coveralls
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ! '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
description: Adhocracy is group management engine for Rails.
|
140
154
|
email:
|
141
155
|
- timothythehuman@gmail.com
|
@@ -164,6 +178,7 @@ files:
|
|
164
178
|
- lib/adhocracy/acts_as_group.rb
|
165
179
|
- lib/adhocracy/acts_as_member.rb
|
166
180
|
- lib/adhocracy/engine.rb
|
181
|
+
- lib/adhocracy/joinable.rb
|
167
182
|
- lib/adhocracy/membership_association.rb
|
168
183
|
- lib/adhocracy/version.rb
|
169
184
|
- lib/tasks/adhocracy_tasks.rake
|
@@ -240,48 +255,48 @@ summary: Adhocracy is group management engine for Rails.
|
|
240
255
|
test_files:
|
241
256
|
- spec/lib/adhocracy/acts_as_group_spec.rb
|
242
257
|
- spec/lib/adhocracy/acts_as_member_spec.rb
|
243
|
-
- spec/
|
244
|
-
- spec/factories/adhoc.rb
|
245
|
-
- spec/factories/adhocracy_membership_invitations.rb
|
246
|
-
- spec/factories/users.rb
|
247
|
-
- spec/factories/adhocracy_membership_requests.rb
|
248
|
-
- spec/spec_helper.rb
|
249
|
-
- spec/dummy/Rakefile
|
250
|
-
- spec/dummy/config/application.rb
|
251
|
-
- spec/dummy/config/boot.rb
|
252
|
-
- spec/dummy/config/initializers/backtrace_silencers.rb
|
253
|
-
- spec/dummy/config/initializers/inflections.rb
|
254
|
-
- spec/dummy/config/initializers/session_store.rb
|
255
|
-
- spec/dummy/config/initializers/mime_types.rb
|
256
|
-
- spec/dummy/config/initializers/secret_token.rb
|
257
|
-
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
258
|
-
- spec/dummy/config/initializers/wrap_parameters.rb
|
259
|
-
- spec/dummy/config/routes.rb
|
260
|
-
- spec/dummy/config/environment.rb
|
261
|
-
- spec/dummy/config/locales/en.yml
|
262
|
-
- spec/dummy/config/database.yml
|
263
|
-
- spec/dummy/config/environments/development.rb
|
264
|
-
- spec/dummy/config/environments/production.rb
|
265
|
-
- spec/dummy/config/environments/test.rb
|
266
|
-
- spec/dummy/config.ru
|
258
|
+
- spec/dummy/README.rdoc
|
267
259
|
- spec/dummy/app/helpers/application_helper.rb
|
268
260
|
- spec/dummy/app/views/layouts/application.html.erb
|
269
|
-
- spec/dummy/app/controllers/application_controller.rb
|
270
261
|
- spec/dummy/app/assets/stylesheets/application.css
|
271
262
|
- spec/dummy/app/assets/javascripts/application.js
|
272
263
|
- spec/dummy/app/models/adhoc.rb
|
273
264
|
- spec/dummy/app/models/user.rb
|
274
|
-
- spec/dummy/
|
275
|
-
- spec/dummy/
|
276
|
-
- spec/dummy/
|
265
|
+
- spec/dummy/app/controllers/application_controller.rb
|
266
|
+
- spec/dummy/db/migrate/20140306214611_create_users.rb
|
267
|
+
- spec/dummy/db/migrate/20140306214620_create_adhocs.rb
|
268
|
+
- spec/dummy/db/schema.rb
|
277
269
|
- spec/dummy/public/422.html
|
278
270
|
- spec/dummy/public/404.html
|
279
271
|
- spec/dummy/public/favicon.ico
|
280
272
|
- spec/dummy/public/500.html
|
281
|
-
- spec/dummy/
|
282
|
-
- spec/dummy/
|
283
|
-
- spec/dummy/
|
284
|
-
- spec/dummy/
|
273
|
+
- spec/dummy/Rakefile
|
274
|
+
- spec/dummy/bin/rails
|
275
|
+
- spec/dummy/bin/bundle
|
276
|
+
- spec/dummy/bin/rake
|
277
|
+
- spec/dummy/config/initializers/mime_types.rb
|
278
|
+
- spec/dummy/config/initializers/inflections.rb
|
279
|
+
- spec/dummy/config/initializers/backtrace_silencers.rb
|
280
|
+
- spec/dummy/config/initializers/wrap_parameters.rb
|
281
|
+
- spec/dummy/config/initializers/session_store.rb
|
282
|
+
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
283
|
+
- spec/dummy/config/initializers/secret_token.rb
|
284
|
+
- spec/dummy/config/application.rb
|
285
|
+
- spec/dummy/config/environments/test.rb
|
286
|
+
- spec/dummy/config/environments/development.rb
|
287
|
+
- spec/dummy/config/environments/production.rb
|
288
|
+
- spec/dummy/config/boot.rb
|
289
|
+
- spec/dummy/config/routes.rb
|
290
|
+
- spec/dummy/config/locales/en.yml
|
291
|
+
- spec/dummy/config/environment.rb
|
292
|
+
- spec/dummy/config/database.yml
|
293
|
+
- spec/dummy/config.ru
|
294
|
+
- spec/spec_helper.rb
|
295
|
+
- spec/factories/adhocracy_membership_requests.rb
|
296
|
+
- spec/factories/users.rb
|
297
|
+
- spec/factories/adhocracy_membership_invitations.rb
|
298
|
+
- spec/factories/adhocracy_memberships.rb
|
299
|
+
- spec/factories/adhoc.rb
|
285
300
|
- spec/models/adhocracy/membership_spec.rb
|
286
301
|
- spec/models/adhocracy/membership_request_spec.rb
|
287
302
|
- spec/models/adhocracy/membership_invitation_spec.rb
|