adhocracy 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/README.rdoc +1 -1
- data/app/models/adhocracy/membership.rb +15 -0
- data/app/models/adhocracy/membership_invitation.rb +31 -0
- data/app/models/adhocracy/membership_request.rb +31 -0
- data/config/locales/en.yml +14 -0
- data/db/migrate/20140306214416_create_adhocracy_memberships.rb +19 -0
- data/db/migrate/20140306214532_create_adhocracy_membership_requests.rb +23 -0
- data/db/migrate/20140306214552_create_adhocracy_membership_invitations.rb +23 -0
- data/lib/adhocracy/acceptable.rb +18 -0
- data/lib/adhocracy/acts_as_group.rb +65 -0
- data/lib/adhocracy/acts_as_member.rb +63 -0
- data/lib/adhocracy/membership_association.rb +49 -0
- data/lib/adhocracy/version.rb +1 -1
- data/lib/adhocracy.rb +4 -0
- data/spec/dummy/app/models/adhoc.rb +3 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/config/application.rb +1 -0
- data/spec/dummy/db/migrate/20140306214611_create_users.rb +6 -0
- data/spec/dummy/db/migrate/20140306214620_create_adhocs.rb +6 -0
- data/spec/dummy/db/schema.rb +67 -0
- data/spec/factories/adhoc.rb +4 -0
- data/spec/factories/adhocracy_membership_invitations.rb +8 -0
- data/spec/factories/adhocracy_membership_requests.rb +8 -0
- data/spec/factories/adhocracy_memberships.rb +7 -0
- data/spec/factories/users.rb +4 -0
- data/spec/lib/adhocracy/acts_as_group_spec.rb +179 -0
- data/spec/lib/adhocracy/acts_as_member_spec.rb +179 -0
- data/spec/models/adhocracy/membership_invitation_spec.rb +84 -0
- data/spec/models/adhocracy/membership_request_spec.rb +84 -0
- data/spec/models/adhocracy/membership_spec.rb +21 -0
- metadata +114 -75
- data/spec/dummy/log/test.log +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Mzc4MGI0NWEzMTM5YTA5Mzg4NDcyNjlkMTRhODdlN2E3OGVlMDFjOA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MWU2NTA1NTkyYTBiNGFjMDI3OTllN2U2ZTM4MjJmMjI4Yjc2MjJkMQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
Y2U1ZDBiYjQ0NzZjNGNkMmFmOTFlOTYwMjVmN2U3NDEzNTI1MDA0ODU2ZDhl
|
10
|
+
YzFkZmJmM2JhNGJhODZiODQ2YzRkMzBlYzY3MTMxNDRmMmY4MTNkOWNjOTU1
|
11
|
+
YzQ2NWQxYTA1YjUyYWJiMjExMzg1NWE5NWMxYjU4MmVlNjg2ZGQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YTMyZTIwZjM2MjA5OWQxNzgyYWZlNTI1M2UzNmVkOTk1ZGMyZGM2ZTU3YzJm
|
14
|
+
ZDE4NWIyYmMzMWYwYjAyMDFmMGM0NGEyNDg5YmI3ZDQ3OGY2ZDMxM2E5YWE5
|
15
|
+
MjVmZDUxOTIzZWZhZmU2MWRmNGRlYzRjM2U0MTI4NmIxYmY2YWU=
|
data/README.rdoc
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
= 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://codeclimate.com/github/timothycommoner/adhocracy.png" />}[https://codeclimate.com/github/timothycommoner/adhocracy]
|
2
2
|
|
3
3
|
A group management engine for Rails.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
class Membership < ActiveRecord::Base
|
3
|
+
belongs_to :member, polymorphic: true
|
4
|
+
belongs_to :group, polymorphic: true
|
5
|
+
|
6
|
+
validate :membership_is_unique
|
7
|
+
|
8
|
+
private
|
9
|
+
def membership_is_unique
|
10
|
+
if self.member.member_of?(self.group)
|
11
|
+
errors[:base] << I18n.t("activerecord.errors.models.membership.not_unique")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
class MembershipInvitation < ActiveRecord::Base
|
3
|
+
include Acceptable
|
4
|
+
|
5
|
+
belongs_to :member, polymorphic: true
|
6
|
+
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
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
class MembershipRequest < ActiveRecord::Base
|
3
|
+
include Acceptable
|
4
|
+
|
5
|
+
belongs_to :member, polymorphic: true
|
6
|
+
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
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
activerecord:
|
3
|
+
errors:
|
4
|
+
models:
|
5
|
+
membership:
|
6
|
+
not_unique: "Membership already exists."
|
7
|
+
membership_invitation:
|
8
|
+
still_pending: "Invitation still pending."
|
9
|
+
already_declined: "Cannot invite member again."
|
10
|
+
already_a_member: "Already a member."
|
11
|
+
membership_request:
|
12
|
+
still_pending: "Request still pending."
|
13
|
+
already_declined: "Cannot request membership again."
|
14
|
+
already_a_member: "Already a member."
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateAdhocracyMemberships < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :adhocracy_memberships do |t|
|
4
|
+
t.string :member_type
|
5
|
+
t.integer :member_id
|
6
|
+
t.string :group_type
|
7
|
+
t.integer :group_id
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :adhocracy_memberships,
|
13
|
+
[:member_id, :member_type],
|
14
|
+
name: "adhocracy_memberships_on_member"
|
15
|
+
add_index :adhocracy_memberships,
|
16
|
+
[:group_id, :group_type],
|
17
|
+
name: "adhocracy_memberships_on_group"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateAdhocracyMembershipRequests < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :adhocracy_membership_requests do |t|
|
4
|
+
t.string :member_type
|
5
|
+
t.integer :member_id
|
6
|
+
t.string :group_type
|
7
|
+
t.integer :group_id
|
8
|
+
|
9
|
+
t.boolean :pending, null: false, default: true
|
10
|
+
t.boolean :accepted, null: false, default: false
|
11
|
+
t.boolean :declined, null: false, default: false
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :adhocracy_membership_requests,
|
17
|
+
[:member_id, :member_type],
|
18
|
+
name: "adhocracy_membership_requests_on_member"
|
19
|
+
add_index :adhocracy_memberships,
|
20
|
+
[:group_id, :group_type],
|
21
|
+
name: "adhocracy_membership_requests_on_group"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateAdhocracyMembershipInvitations < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :adhocracy_membership_invitations do |t|
|
4
|
+
t.string :member_type
|
5
|
+
t.integer :member_id
|
6
|
+
t.string :group_type
|
7
|
+
t.integer :group_id
|
8
|
+
|
9
|
+
t.boolean :pending, null: false, default: true
|
10
|
+
t.boolean :accepted, null: false, default: false
|
11
|
+
t.boolean :declined, null: false, default: false
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :adhocracy_membership_invitations,
|
17
|
+
[:member_id, :member_type],
|
18
|
+
name: "adhocracy_membership_invitations_on_member"
|
19
|
+
add_index :adhocracy_memberships,
|
20
|
+
[:group_id, :group_type],
|
21
|
+
name: "adhocracy_membership_invitations_on_group"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
module Acceptable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def accept
|
6
|
+
if pending?
|
7
|
+
member.join_group(group)
|
8
|
+
update_attributes(pending: false, accepted: true, declined: false)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def decline
|
13
|
+
if pending?
|
14
|
+
update_attributes(pending: false, accepted: false, declined: true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
module ActsAsGroup
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def acts_as_group(options = {})
|
7
|
+
|
8
|
+
has_many :memberships, as: :group, class_name: "Adhocracy::Membership"
|
9
|
+
has_many :membership_invitations, as: :group,
|
10
|
+
class_name: "Adhocracy::MembershipInvitation"
|
11
|
+
has_many :membership_requests, as: :group,
|
12
|
+
class_name: "Adhocracy::MembershipRequest"
|
13
|
+
|
14
|
+
send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
def members
|
20
|
+
MembershipAssociation.new(group: self).list_members_for_membership
|
21
|
+
end
|
22
|
+
|
23
|
+
def invited_members
|
24
|
+
MembershipAssociation.new(group: self).
|
25
|
+
list_members_for_membership_invitation
|
26
|
+
end
|
27
|
+
|
28
|
+
def membership_requests
|
29
|
+
MembershipAssociation.new(group: self).
|
30
|
+
list_members_for_membership_request
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_member(member)
|
34
|
+
MembershipAssociation.new(member: member, group: self).
|
35
|
+
create_membership
|
36
|
+
end
|
37
|
+
|
38
|
+
def invite_member(member)
|
39
|
+
MembershipAssociation.new(member: member, group: self).
|
40
|
+
create_membership_invitation
|
41
|
+
end
|
42
|
+
|
43
|
+
def remove_member(member)
|
44
|
+
MembershipAssociation.new(member: member, group: self).
|
45
|
+
destroy_membership
|
46
|
+
end
|
47
|
+
|
48
|
+
def has_member?(member)
|
49
|
+
MembershipAssociation.new(member: member, group: self).verify_membership
|
50
|
+
end
|
51
|
+
|
52
|
+
def invited?(member, params = {})
|
53
|
+
params.merge!({ member: member, group: self })
|
54
|
+
MembershipAssociation.new(params).verify_membership_invitation
|
55
|
+
end
|
56
|
+
|
57
|
+
def recieved_request_from?(member, params = {})
|
58
|
+
params.merge!({ member: member, group: self })
|
59
|
+
MembershipAssociation.new(params).verify_membership_request
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
ActiveRecord::Base.send :include, Adhocracy::ActsAsGroup
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
module ActsAsMember
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def acts_as_member(options = {})
|
7
|
+
|
8
|
+
has_many :memberships, as: :member, class_name: "Adhocracy::Membership"
|
9
|
+
has_many :membership_invitations, as: :member,
|
10
|
+
class_name: "Adhocracy::MembershipInvitation"
|
11
|
+
has_many :membership_requests, as: :member,
|
12
|
+
class_name: "Adhocracy::MembershipRequest"
|
13
|
+
|
14
|
+
send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
def groups
|
20
|
+
MembershipAssociation.new(member: self).list_groups_for_membership
|
21
|
+
end
|
22
|
+
|
23
|
+
def group_invitations
|
24
|
+
MembershipAssociation.new(member: self).
|
25
|
+
list_groups_for_membership_invitation
|
26
|
+
end
|
27
|
+
|
28
|
+
def membership_requests
|
29
|
+
MembershipAssociation.new(member: self).
|
30
|
+
list_groups_for_membership_request
|
31
|
+
end
|
32
|
+
|
33
|
+
def join_group(group)
|
34
|
+
MembershipAssociation.new(member: self, group: group).create_membership
|
35
|
+
end
|
36
|
+
|
37
|
+
def request_membership_in(group)
|
38
|
+
MembershipAssociation.new(member: self, group: group).
|
39
|
+
create_membership_request
|
40
|
+
end
|
41
|
+
|
42
|
+
def leave_group(group)
|
43
|
+
MembershipAssociation.new(member: self, group: group).destroy_membership
|
44
|
+
end
|
45
|
+
|
46
|
+
def member_of?(group)
|
47
|
+
MembershipAssociation.new(member: self, group: group).verify_membership
|
48
|
+
end
|
49
|
+
|
50
|
+
def invited_to?(group, params = {})
|
51
|
+
params.merge!({ member: self, group: group })
|
52
|
+
MembershipAssociation.new(params).verify_membership_invitation
|
53
|
+
end
|
54
|
+
|
55
|
+
def requested_membership_in?(group, params = {})
|
56
|
+
params.merge!({ member: self, group: group })
|
57
|
+
MembershipAssociation.new(params).verify_membership_request
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ActiveRecord::Base.send :include, Adhocracy::ActsAsMember
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Adhocracy
|
2
|
+
class MembershipAssociation
|
3
|
+
|
4
|
+
attr_accessor :params
|
5
|
+
def initialize(params)
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
# Creates Methods:
|
10
|
+
# list_membership, create_membership, destroy_membership, verify_membership
|
11
|
+
# list_membership_request, create_membership_request,
|
12
|
+
# destroy_membership_request, verify_membership_request
|
13
|
+
# list_membership_invitation, create_membership_invitation,
|
14
|
+
# destroy_membership_invitation, verify_membership_invitation
|
15
|
+
|
16
|
+
%w(membership membership_request membership_invitation).each do |type|
|
17
|
+
%w(list_members_for list_groups_for create destroy verify).each do |action|
|
18
|
+
define_method "#{action}_#{type}" do
|
19
|
+
send("#{action}", "Adhocracy::#{type.camelize}".constantize)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def list_members_for(membership_class)
|
26
|
+
membership_class.where(group: params[:group]).includes(:member).
|
27
|
+
collect { |membership| membership.member }
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_groups_for(membership_class)
|
31
|
+
membership_class.where(member: params[:member]).includes(:group).
|
32
|
+
collect { |membership| membership.group }
|
33
|
+
end
|
34
|
+
|
35
|
+
def create(membership_class)
|
36
|
+
membership_class.create(params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy(membership_class)
|
40
|
+
membership = membership_class.find_by(params)
|
41
|
+
return false if membership.nil?
|
42
|
+
membership.destroy
|
43
|
+
end
|
44
|
+
|
45
|
+
def verify(membership_class)
|
46
|
+
membership_class.where(params).exists?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/adhocracy/version.rb
CHANGED
data/lib/adhocracy.rb
CHANGED
@@ -23,6 +23,7 @@ module Dummy
|
|
23
23
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
24
24
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
25
25
|
# config.i18n.default_locale = :de
|
26
|
+
config.i18n.enforce_available_locales = true
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20140306214620) do
|
15
|
+
|
16
|
+
# These are extensions that must be enabled in order to support this database
|
17
|
+
enable_extension "plpgsql"
|
18
|
+
|
19
|
+
create_table "adhocracy_membership_invitations", force: true do |t|
|
20
|
+
t.string "member_type"
|
21
|
+
t.integer "member_id"
|
22
|
+
t.string "group_type"
|
23
|
+
t.integer "group_id"
|
24
|
+
t.boolean "pending", default: true, null: false
|
25
|
+
t.boolean "accepted", default: false, null: false
|
26
|
+
t.boolean "declined", default: false, null: false
|
27
|
+
t.datetime "created_at"
|
28
|
+
t.datetime "updated_at"
|
29
|
+
end
|
30
|
+
|
31
|
+
add_index "adhocracy_membership_invitations", ["member_id", "member_type"], name: "adhocracy_membership_invitations_on_member", using: :btree
|
32
|
+
|
33
|
+
create_table "adhocracy_membership_requests", force: true do |t|
|
34
|
+
t.string "member_type"
|
35
|
+
t.integer "member_id"
|
36
|
+
t.string "group_type"
|
37
|
+
t.integer "group_id"
|
38
|
+
t.boolean "pending", default: true, null: false
|
39
|
+
t.boolean "accepted", default: false, null: false
|
40
|
+
t.boolean "declined", default: false, null: false
|
41
|
+
t.datetime "created_at"
|
42
|
+
t.datetime "updated_at"
|
43
|
+
end
|
44
|
+
|
45
|
+
add_index "adhocracy_membership_requests", ["member_id", "member_type"], name: "adhocracy_membership_requests_on_member", using: :btree
|
46
|
+
|
47
|
+
create_table "adhocracy_memberships", force: true do |t|
|
48
|
+
t.string "member_type"
|
49
|
+
t.integer "member_id"
|
50
|
+
t.string "group_type"
|
51
|
+
t.integer "group_id"
|
52
|
+
t.datetime "created_at"
|
53
|
+
t.datetime "updated_at"
|
54
|
+
end
|
55
|
+
|
56
|
+
add_index "adhocracy_memberships", ["group_id", "group_type"], name: "adhocracy_membership_invitations_on_group", using: :btree
|
57
|
+
add_index "adhocracy_memberships", ["group_id", "group_type"], name: "adhocracy_membership_requests_on_group", using: :btree
|
58
|
+
add_index "adhocracy_memberships", ["group_id", "group_type"], name: "adhocracy_memberships_on_group", using: :btree
|
59
|
+
add_index "adhocracy_memberships", ["member_id", "member_type"], name: "adhocracy_memberships_on_member", using: :btree
|
60
|
+
|
61
|
+
create_table "adhocs", force: true do |t|
|
62
|
+
end
|
63
|
+
|
64
|
+
create_table "users", force: true do |t|
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|