radiant-reader_group-extension 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.markdown +44 -0
- data/Rakefile +137 -0
- data/VERSION +1 -0
- data/app/controllers/admin/group_invitations_controller.rb +84 -0
- data/app/controllers/admin/groups_controller.rb +4 -0
- data/app/controllers/admin/memberships_controller.rb +42 -0
- data/app/controllers/admin/permissions_controller.rb +42 -0
- data/app/helpers/admin/groups_helper.rb +36 -0
- data/app/models/group.rb +43 -0
- data/app/models/membership.rb +13 -0
- data/app/models/permission.rb +13 -0
- data/app/views/admin/group_invitations/new.html.haml +45 -0
- data/app/views/admin/group_invitations/preview.html.haml +63 -0
- data/app/views/admin/groups/_add_readers.html.haml +0 -0
- data/app/views/admin/groups/_form.html.haml +61 -0
- data/app/views/admin/groups/_list_head.html.haml +12 -0
- data/app/views/admin/groups/_listed.html.haml +25 -0
- data/app/views/admin/groups/edit.html.haml +8 -0
- data/app/views/admin/groups/index.html.haml +19 -0
- data/app/views/admin/groups/new.html.haml +6 -0
- data/app/views/admin/groups/remove.html.haml +31 -0
- data/app/views/admin/groups/show.html.haml +41 -0
- data/app/views/admin/memberships/_reader.html.haml +9 -0
- data/app/views/admin/messages/_list_notes.html.haml +9 -0
- data/app/views/admin/messages/_message_description.html.haml +7 -0
- data/app/views/admin/messages/_message_group.html.haml +3 -0
- data/app/views/admin/pages/_listed.html.haml +16 -0
- data/app/views/admin/pages/_page_groups.html.haml +17 -0
- data/app/views/admin/permissions/_page.html.haml +24 -0
- data/app/views/admin/reader_settings/_group_welcomes.html.haml +11 -0
- data/app/views/admin/readers/_reader_groups.html.haml +7 -0
- data/app/views/messages/show.html.haml +11 -0
- data/app/views/reader_activations/_on_activation.html.haml +10 -0
- data/app/views/readers/_memberships.html.haml +11 -0
- data/app/views/site/not_allowed.html.haml +4 -0
- data/config/routes.rb +8 -0
- data/db/migrate/001_create_groups.rb +32 -0
- data/db/migrate/20090921125654_group_messages.rb +9 -0
- data/db/migrate/20091120083119_groups_public.rb +11 -0
- data/lib/admin_messages_controller_extensions.rb +15 -0
- data/lib/group_message_tags.rb +82 -0
- data/lib/group_ui.rb +37 -0
- data/lib/grouped_message.rb +38 -0
- data/lib/grouped_model.rb +100 -0
- data/lib/grouped_page.rb +59 -0
- data/lib/grouped_reader.rb +63 -0
- data/lib/reader_activations_controller_extensions.rb +21 -0
- data/lib/reader_notifier_extensions.rb +14 -0
- data/lib/reader_sessions_controller_extensions.rb +21 -0
- data/lib/readers_controller_extensions.rb +22 -0
- data/lib/site_controller_extensions.rb +37 -0
- data/lib/tasks/reader_group_extension_tasks.rake +28 -0
- data/pkg/radiant-reader_group-extension-0.9.0.gem +0 -0
- data/public/images/admin/chk_auto.png +0 -0
- data/public/images/admin/chk_off.png +0 -0
- data/public/images/admin/chk_on.png +0 -0
- data/public/images/admin/edit.png +0 -0
- data/public/images/admin/error.png +0 -0
- data/public/images/admin/message.png +0 -0
- data/public/images/admin/new-group.png +0 -0
- data/public/images/admin/populate.png +0 -0
- data/public/images/admin/rdo_off.png +0 -0
- data/public/images/admin/rdo_on.png +0 -0
- data/public/stylesheets/sass/admin/group.sass +66 -0
- data/radiant-reader_group-extension.gemspec +134 -0
- data/reader_group_extension.rb +53 -0
- data/spec/controllers/readers_controller_spec.rb +44 -0
- data/spec/controllers/site_controller_spec.rb +64 -0
- data/spec/datasets/group_messages_dataset.rb +32 -0
- data/spec/datasets/group_readers_dataset.rb +49 -0
- data/spec/datasets/group_sites_dataset.rb +11 -0
- data/spec/datasets/groups_dataset.rb +48 -0
- data/spec/models/group_spec.rb +45 -0
- data/spec/models/message_spec.rb +42 -0
- data/spec/models/page_spec.rb +53 -0
- data/spec/models/reader_spec.rb +16 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- metadata +184 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
%tr.node.level-1
|
2
|
+
- render_region :tbody do |tbody|
|
3
|
+
- tbody.name_cell do
|
4
|
+
%td.name
|
5
|
+
%p
|
6
|
+
= link_to group.name, admin_group_url(group)
|
7
|
+
%br
|
8
|
+
= truncate_words(group.description, 40)
|
9
|
+
- tbody.home_cell do
|
10
|
+
%td.home
|
11
|
+
- if group.homepage
|
12
|
+
= link_to group.homepage.title, edit_admin_page_url(group.homepage)
|
13
|
+
- else
|
14
|
+
none
|
15
|
+
- tbody.members_cell do
|
16
|
+
%td.members
|
17
|
+
= link_to group.readers.count, admin_group_url(group)
|
18
|
+
- tbody.pages_cell do
|
19
|
+
%td.pages
|
20
|
+
= link_to group.pages.count, admin_group_url(group)
|
21
|
+
- tbody.modify_cell do
|
22
|
+
%td.actions
|
23
|
+
= link_to_unless_current image('plus') + ' send invitations', new_admin_group_group_invitation_url(group), :class => 'action'
|
24
|
+
= link_to_unless_current image('minus') + ' remove group', admin_group_url(group, :method => 'delete', :confirm => "are you sure you want to completely remove the #{group.name} group?"), :class => 'action'
|
25
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
- include_stylesheet('admin/group')
|
2
|
+
|
3
|
+
= render_region :top
|
4
|
+
|
5
|
+
#groups_table.outset
|
6
|
+
%table#groups.index{:cellspacing=>"0", :border=>"0", :cellpadding=>"0"}
|
7
|
+
%thead
|
8
|
+
= render :partial => 'list_head'
|
9
|
+
%tbody
|
10
|
+
- @groups.each do |group|
|
11
|
+
= render :partial => 'listed', :locals => {:group => group}
|
12
|
+
|
13
|
+
- render_region :bottom do |bottom|
|
14
|
+
- bottom.buttons do
|
15
|
+
#actions
|
16
|
+
= pagination_for @readers
|
17
|
+
%ul
|
18
|
+
%li
|
19
|
+
= link_to image('plus') + " " + "new group", new_admin_group_url
|
@@ -0,0 +1,31 @@
|
|
1
|
+
- include_stylesheet('admin/group')
|
2
|
+
%h1 Remove Group
|
3
|
+
|
4
|
+
%p
|
5
|
+
Are you sure you want to
|
6
|
+
%strong.warning
|
7
|
+
remove permanently
|
8
|
+
the group
|
9
|
+
= h @group.name
|
10
|
+
?
|
11
|
+
|
12
|
+
%p
|
13
|
+
The group has
|
14
|
+
= @group.readers.count
|
15
|
+
= pluralize(@group.readers.count, 'member')
|
16
|
+
and
|
17
|
+
= @group.pages.count
|
18
|
+
= pluralize(@group.pages.count, 'page')
|
19
|
+
\. The pages and readers will not be deleted - just dissociated from one another - and removing the group association from those pages may make them visible to everyone.
|
20
|
+
|
21
|
+
%table#groups.index{:cellspacing=>"0", :border=>"0", :cellpadding=>"0"}
|
22
|
+
%thead
|
23
|
+
= render :partial => 'list_head'
|
24
|
+
%tbody
|
25
|
+
= render :partial => 'listed', :locals => {:group => @group}
|
26
|
+
|
27
|
+
- form_for [:admin, @group], :html => { :method => 'delete' } do
|
28
|
+
%p.buttons
|
29
|
+
%input.button{:type=>"submit", :value=>"Delete Group"}/
|
30
|
+
or
|
31
|
+
= link_to 'Cancel', admin_groups_url
|
@@ -0,0 +1,41 @@
|
|
1
|
+
- include_stylesheet 'admin/group'
|
2
|
+
- body_classes << "reversed"
|
3
|
+
|
4
|
+
%h1
|
5
|
+
Group:
|
6
|
+
= @group.name
|
7
|
+
|
8
|
+
= textilize(@group.description)
|
9
|
+
|
10
|
+
|
11
|
+
#group_pages.box.narrow
|
12
|
+
%h2
|
13
|
+
Private pages
|
14
|
+
%ul
|
15
|
+
- page = Page.respond_to?(:homepage) ? Page.homepage : Page.find_by_parent_id(nil)
|
16
|
+
%div{:id => "page_holder_#{page.id}"}
|
17
|
+
= render :partial => 'admin/permissions/page', :object => page
|
18
|
+
|
19
|
+
#group_people.box.narrow
|
20
|
+
%h2
|
21
|
+
Group members
|
22
|
+
- readers = Reader.find(:all)
|
23
|
+
- total = readers.count
|
24
|
+
- column_length = (readers.count-1) / 2
|
25
|
+
- columns = [readers[0..column_length], readers[column_length+1..readers.count]]
|
26
|
+
- columns.each do |column|
|
27
|
+
%ul.column
|
28
|
+
- column.each do |reader|
|
29
|
+
%div{:id => "reader_holder_#{reader.id}"}
|
30
|
+
= render :partial => 'admin/memberships/reader', :object => reader
|
31
|
+
|
32
|
+
#footnotes
|
33
|
+
%p
|
34
|
+
The pages selected on the left are only visible to the people selected on the right.
|
35
|
+
|
36
|
+
:javascript
|
37
|
+
var h1 = $('group_pages').getHeight();
|
38
|
+
var h2 = $('group_people').getHeight();
|
39
|
+
var h = (h1 > h2) ? h1 : h2
|
40
|
+
$('group_people').setStyle({'height': h + 'px'});
|
41
|
+
$('group_pages').setStyle({'height': h + 'px'});
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- reader ||= @reader
|
2
|
+
- group ||= @group
|
3
|
+
|
4
|
+
- if membership = group.membership_for(reader)
|
5
|
+
%li{:class => "fake_checkbox checked", :id => "reader_#{reader.id}"}
|
6
|
+
= link_to_remote reader.name, :url => admin_group_membership_url(group, membership), :method => 'delete', :loading => "$('reader_#{reader.id}').addClassName('waiting')", :update => "reader_holder_#{reader.id}"
|
7
|
+
- else
|
8
|
+
%li{:class => "fake_checkbox unchecked", :id => "reader_#{reader.id}"}
|
9
|
+
= link_to_remote reader.name, :url => admin_group_memberships_url(group, :reader_id => reader.id), :loading => "$('reader_#{reader.id}').addClassName('waiting')", :update => "reader_holder_#{reader.id}"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%tr.node{:id => "page-#{page.id}", :class =>"level-#{level}"}
|
2
|
+
- render_region :page, :locals => {:page => page, :level => level} do |node|
|
3
|
+
- node.title_column do
|
4
|
+
%td.page{:style => "padding-left: #{(level * 22) + 4}px"}
|
5
|
+
%span.w1
|
6
|
+
= image('page', :class => "icon", :alt => 'page-icon', :title => '')
|
7
|
+
%span.title
|
8
|
+
= link_to page.title, edit_admin_page_url(page)
|
9
|
+
- node.add_child_column do
|
10
|
+
%td.add-child
|
11
|
+
= link_to image('add-child', :alt => 'add child'), new_admin_page_child_url(page)
|
12
|
+
- node.remove_column do
|
13
|
+
%td.remove
|
14
|
+
= link_to image('remove', :alt => 'remove page'), remove_admin_page_url(page)
|
15
|
+
- page.children.each do |child|
|
16
|
+
= render :partial => 'admin/pages/listed', :locals => {:page => child, :level => level+1}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
- include_stylesheet('admin/group')
|
2
|
+
= hidden_field_tag "page[group_ids][]", ""
|
3
|
+
|
4
|
+
.row
|
5
|
+
%p
|
6
|
+
Allow access only to:
|
7
|
+
- Group.find(:all).each do |g|
|
8
|
+
= check_box_tag "page[group_ids][]", g.id, @page.has_inherited_group?(g), {:id => "page_group_#{g.id}", :disabled => @page.group_is_inherited?(g)}
|
9
|
+
- if @page.group_is_inherited?(g)
|
10
|
+
%label{:for => "page_group_#{g.id}", :class => 'disabled', :title => "group is attached higher in the page tree: can't be detached here"}
|
11
|
+
= g.name
|
12
|
+
- else
|
13
|
+
%label{:for => "page_group_#{g.id}"}
|
14
|
+
= g.name
|
15
|
+
%br
|
16
|
+
%span.formnote
|
17
|
+
Leave all groups unchecked for public access.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
- page ||= @page
|
2
|
+
- group ||= @group
|
3
|
+
|
4
|
+
- liclass = 'loose'
|
5
|
+
- liclass = 'attached' if page.has_group?(group)
|
6
|
+
- liclass = 'inherited' if page.group_is_inherited?(group)
|
7
|
+
|
8
|
+
- if permission = group.permission_for(page)
|
9
|
+
%li{:class => "fake_checkbox checked", :id => "page_#{page.id}"}
|
10
|
+
= link_to_remote page.title, :url => admin_group_permission_url(group, permission), :method => 'delete', :loading => "$('page_#{page.id}').addClassName('waiting')", :update => "page_holder_#{page.id}"
|
11
|
+
|
12
|
+
- elsif page.has_inherited_group?(group)
|
13
|
+
%li{:class => "fake_checkbox inherited", :id => "page_#{page.id}"}
|
14
|
+
= page.title
|
15
|
+
|
16
|
+
- else
|
17
|
+
%li{:class => "fake_checkbox unchecked", :id => "page_#{page.id}"}
|
18
|
+
= link_to_remote page.title, :url => admin_group_permissions_url(group, :page_id => page.id), :loading => "$('page_#{page.id}').addClassName('waiting')", :update => "page_holder_#{page.id}"
|
19
|
+
|
20
|
+
- if page.children.any?
|
21
|
+
%ul
|
22
|
+
- page.children.each do |child|
|
23
|
+
%div{:id => "page_holder_#{child.id}"}
|
24
|
+
= render :partial => 'admin/permissions/page', :object => child
|
@@ -0,0 +1,11 @@
|
|
1
|
+
- Group.all.each do |group|
|
2
|
+
- [:invitation, :welcome].each do |func|
|
3
|
+
- message = Message.functional(:invitation, group)
|
4
|
+
%p.ruled
|
5
|
+
%label
|
6
|
+
= group.name
|
7
|
+
= func
|
8
|
+
- if message
|
9
|
+
= link_to message.subject, edit_admin_message_url(message)
|
10
|
+
- else
|
11
|
+
= link_to image('plus') + " create message", new_admin_group_message_url(group, :function => func), :class => 'create'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
.message
|
2
|
+
%iframe.message_body{:src => preview_group_message_url(@group, @message)}
|
3
|
+
|
4
|
+
- content_for :pagetitle do
|
5
|
+
= @message.subject
|
6
|
+
|
7
|
+
- content_for :marginalia do
|
8
|
+
margin?
|
9
|
+
|
10
|
+
- content_for :breadhead do
|
11
|
+
= link_to @group.name, @group.homepage.url
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- if homepage = current_reader.find_homepage
|
2
|
+
%p
|
3
|
+
Would you like to go straight to the
|
4
|
+
= link_to homepage.title, homepage.url
|
5
|
+
page?
|
6
|
+
|
7
|
+
- elsif session[:return_to]
|
8
|
+
%p
|
9
|
+
Would you like to
|
10
|
+
= link_to ("return to the page you were looking at before you started registering", session[:return_to]) + '?'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
- if Group.subscribable.any?
|
2
|
+
%h3
|
3
|
+
Subscriptions
|
4
|
+
%p{:style => 'margin-top: 0;'}
|
5
|
+
- Group.subscribable.each do |group|
|
6
|
+
= check_box_tag "reader[group_ids][]", group.id, @reader.is_in?(group), :id => "reader_group_#{group.id}"
|
7
|
+
%label{:for => "reader_group_#{group.id}"}
|
8
|
+
= group.name
|
9
|
+
%span.formnote
|
10
|
+
= group.invitation
|
11
|
+
%br
|
data/config/routes.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.namespace :admin, :path_prefix => 'admin/readers' do |admin|
|
3
|
+
admin.resources :groups, :has_many => [:memberships, :permissions, :group_invitations, :messages]
|
4
|
+
end
|
5
|
+
map.resources :groups, :only => [] do |group|
|
6
|
+
group.resources :messages, :only => [:index, :show], :member => [:preview]
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class CreateGroups < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :groups do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
t.column :description, :text
|
6
|
+
t.column :notes, :text
|
7
|
+
t.column :created_at, :datetime
|
8
|
+
t.column :updated_at, :datetime
|
9
|
+
t.column :created_by_id, :integer
|
10
|
+
t.column :updated_by_id, :integer
|
11
|
+
t.column :homepage_id, :integer
|
12
|
+
t.column :site_id, :integer
|
13
|
+
t.column :lock_version, :integer
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :memberships do |t|
|
17
|
+
t.column :group_id, :integer
|
18
|
+
t.column :reader_id, :integer
|
19
|
+
end
|
20
|
+
|
21
|
+
create_table :permissions do |t|
|
22
|
+
t.column :group_id, :integer
|
23
|
+
t.column :page_id, :integer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.down
|
28
|
+
drop_table :groups
|
29
|
+
drop_table :memberships
|
30
|
+
drop_table :permissions
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module GroupMessageTags
|
2
|
+
include Radiant::Taggable
|
3
|
+
|
4
|
+
class TagError < StandardError; end
|
5
|
+
|
6
|
+
desc %{
|
7
|
+
The root 'group' tag is not meant to be called directly.
|
8
|
+
All it does is summon a group object so that its fields can be displayed with eg.
|
9
|
+
<pre><code><r:group:name /></code></pre>
|
10
|
+
|
11
|
+
This tag will not throw an exception if there is no group; it will just disappear.
|
12
|
+
}
|
13
|
+
tag 'group' do |tag|
|
14
|
+
tag.locals.group = @mailer_vars ? @mailer_vars[:@group] : tag.locals.page.group
|
15
|
+
tag.expand if tag.locals.group
|
16
|
+
end
|
17
|
+
|
18
|
+
[:name, :description, :url].each do |field|
|
19
|
+
desc %{
|
20
|
+
Displays the #{field} field of the currently relevant group. Works in email messages too.
|
21
|
+
|
22
|
+
<pre><code><r:group:#{field} /></code></pre>
|
23
|
+
}
|
24
|
+
tag "group:#{field}" do |tag|
|
25
|
+
tag.locals.group.send(field)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc %{
|
30
|
+
Expands if this group has messages.
|
31
|
+
|
32
|
+
<pre><code><r:group:if_messages>...</r:group:if_messages /></code></pre>
|
33
|
+
}
|
34
|
+
tag "group:if_messages" do |tag|
|
35
|
+
tag.expand if tag.locals.group.messages.ordinary.published.any?
|
36
|
+
end
|
37
|
+
|
38
|
+
desc %{
|
39
|
+
Expands if this group does not have messages.
|
40
|
+
|
41
|
+
<pre><code><r:group:unless_messages>...</r:group:unless_messages /></code></pre>
|
42
|
+
}
|
43
|
+
tag "group:unless_messages" do |tag|
|
44
|
+
tag.expand unless tag.locals.group.messages.ordinary.published.any?
|
45
|
+
end
|
46
|
+
|
47
|
+
desc %{
|
48
|
+
Loops through the non-functional messages (ie not welcomes and reminders) that belong to this group
|
49
|
+
and that have been sent, though not necessarily to the present reader (which is the point, really).
|
50
|
+
|
51
|
+
<pre><code><r:group:messages:each>...</r:group:messages:each /></code></pre>
|
52
|
+
}
|
53
|
+
tag "group:messages" do |tag|
|
54
|
+
tag.locals.messages = tag.locals.group.messages.ordinary.published
|
55
|
+
tag.expand
|
56
|
+
end
|
57
|
+
tag "group:messages:each" do |tag|
|
58
|
+
result = []
|
59
|
+
tag.locals.messages.each do |message|
|
60
|
+
tag.locals.message = message
|
61
|
+
result << tag.expand
|
62
|
+
end
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
# overridden to add group scope:
|
67
|
+
|
68
|
+
desc %{
|
69
|
+
Returns the url of the show-message page
|
70
|
+
|
71
|
+
<pre><code><r:message:url /></code></pre>
|
72
|
+
}
|
73
|
+
tag "message:url" do |tag|
|
74
|
+
if tag.locals.group
|
75
|
+
group_message_path(tag.locals.group, tag.locals.message)
|
76
|
+
else
|
77
|
+
message_path(tag.locals.message)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
end
|
data/lib/group_ui.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module GroupUI
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
|
6
|
+
attr_accessor :group
|
7
|
+
alias_method :groups, :group
|
8
|
+
|
9
|
+
def load_default_regions_with_group
|
10
|
+
load_default_regions_without_group
|
11
|
+
@group = load_default_group_regions
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method_chain :load_default_regions, :group
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def load_default_group_regions
|
19
|
+
returning OpenStruct.new do |group|
|
20
|
+
group.edit = Radiant::AdminUI::RegionSet.new do |edit|
|
21
|
+
edit.main.concat %w{edit_header edit_form}
|
22
|
+
edit.form.concat %w{edit_group edit_timestamp edit_buttons edit_membership edit_pages}
|
23
|
+
end
|
24
|
+
group.index = Radiant::AdminUI::RegionSet.new do |index|
|
25
|
+
index.thead.concat %w{name_header home_header members_header pages_header modify_header}
|
26
|
+
index.tbody.concat %w{name_cell home_cell members_cell pages_cell modify_cell}
|
27
|
+
index.bottom.concat %w{buttons}
|
28
|
+
end
|
29
|
+
group.remove = group.index
|
30
|
+
group.new = group.edit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GroupedMessage
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval {
|
5
|
+
is_grouped
|
6
|
+
|
7
|
+
include InstanceMethods
|
8
|
+
alias_method_chain :possible_readers, :group
|
9
|
+
alias_method_chain :inactive_readers, :group
|
10
|
+
|
11
|
+
extend ClassMethods
|
12
|
+
class << self
|
13
|
+
alias_method_chain :functional, :group
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
def possible_readers_with_group
|
20
|
+
group ? group.readers.active : possible_readers_without_group
|
21
|
+
end
|
22
|
+
def inactive_readers_with_group
|
23
|
+
group ? group.readers.inactive : inactive_readers_without_group
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
def functional_with_group(function, group=nil)
|
29
|
+
messages = for_function(function)
|
30
|
+
if group
|
31
|
+
messages.for_group(group).first
|
32
|
+
else
|
33
|
+
messages.ungrouped.first
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module GroupedModel
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def is_grouped?
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def is_grouped(options={})
|
12
|
+
return if is_grouped?
|
13
|
+
cattr_accessor :group_recipients, :group_donor
|
14
|
+
|
15
|
+
class_eval {
|
16
|
+
extend GroupedModel::GroupedClassMethods
|
17
|
+
include GroupedModel::GroupedInstanceMethods
|
18
|
+
|
19
|
+
def visible_to?(reader)
|
20
|
+
return true unless group
|
21
|
+
return false unless reader
|
22
|
+
return true if reader.is_user?
|
23
|
+
return true if reader.is_in?(group)
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
}
|
28
|
+
|
29
|
+
belongs_to :group
|
30
|
+
named_scope :ungrouped, {:conditions => 'group_id IS NULL'}
|
31
|
+
named_scope :for_group, lambda { |g| {:conditions => ["group_id = ?", g]} }
|
32
|
+
named_scope :visible_to, lambda { |reader|
|
33
|
+
groups = reader.nil? ? [] : reader.groups
|
34
|
+
{:conditions => ["group_id IS NULL OR group_id IN(?)", groups.map(&:id).join(',')]}
|
35
|
+
}
|
36
|
+
|
37
|
+
Group.send(:has_many, self.to_s.pluralize.underscore.intern)
|
38
|
+
|
39
|
+
before_create :get_group
|
40
|
+
after_save :give_group
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module GroupedClassMethods
|
45
|
+
def visible
|
46
|
+
ungrouped
|
47
|
+
end
|
48
|
+
|
49
|
+
def is_grouped?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def gets_group_from(association_name)
|
54
|
+
association = reflect_on_association(association_name)
|
55
|
+
raise StandardError "can't find group source '#{association_name}" unless association
|
56
|
+
raise StandardError "#{association.klass} is not grouped and cannot be a group donor" unless association.klass.is_grouped?
|
57
|
+
self.group_donor = association_name
|
58
|
+
end
|
59
|
+
|
60
|
+
def gives_group_to(associations)
|
61
|
+
associations = [associations] unless associations.is_a?(Array)
|
62
|
+
# shall we force is_grouped here?
|
63
|
+
# shall we assume that gets_group_from follows? and find the association somehow?
|
64
|
+
self.group_recipients ||= []
|
65
|
+
self.group_recipients += associations
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module GroupedInstanceMethods
|
70
|
+
|
71
|
+
def visible?
|
72
|
+
!!group
|
73
|
+
end
|
74
|
+
|
75
|
+
def permitted_groups
|
76
|
+
[group]
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def get_group
|
82
|
+
if self.class.group_donor && group_source = self.send(self.class.group_donor)
|
83
|
+
self.group = group_source.group
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def give_group
|
88
|
+
if self.class.group_recipients
|
89
|
+
self.class.group_recipients.each do |association|
|
90
|
+
send(association).each do |associate|
|
91
|
+
unless associate.group == group
|
92
|
+
associate.group = group
|
93
|
+
associate.save(false)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|