user_notification 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1 -0
- data/Rakefile +18 -0
- data/lib/generators/user_notification/migration/migration_generator.rb +17 -0
- data/lib/generators/user_notification/migration/templates/migration.rb +24 -0
- data/lib/generators/user_notification/notification/notification_generator.rb +17 -0
- data/lib/generators/user_notification/notification/templates/notification.rb +3 -0
- data/lib/generators/user_notification.rb +14 -0
- data/lib/user_notification/actions/creation.rb +15 -0
- data/lib/user_notification/actions/destruction.rb +15 -0
- data/lib/user_notification/actions/update.rb +15 -0
- data/lib/user_notification/activity.rb +6 -0
- data/lib/user_notification/common.rb +342 -0
- data/lib/user_notification/config.rb +63 -0
- data/lib/user_notification/models/activist.rb +9 -0
- data/lib/user_notification/models/adapter.rb +5 -0
- data/lib/user_notification/models/notification.rb +13 -0
- data/lib/user_notification/models/trackable.rb +9 -0
- data/lib/user_notification/orm/active_record/activist.rb +48 -0
- data/lib/user_notification/orm/active_record/adapter.rb +16 -0
- data/lib/user_notification/orm/active_record/notification.rb +24 -0
- data/lib/user_notification/orm/active_record/trackable.rb +15 -0
- data/lib/user_notification/orm/active_record.rb +5 -0
- data/lib/user_notification/orm/mongo_mapper/activist.rb +46 -0
- data/lib/user_notification/orm/mongo_mapper/adapter.rb +12 -0
- data/lib/user_notification/orm/mongo_mapper/notification.rb +33 -0
- data/lib/user_notification/orm/mongo_mapper/trackable.rb +11 -0
- data/lib/user_notification/orm/mongo_mapper.rb +4 -0
- data/lib/user_notification/orm/mongoid/activist.rb +45 -0
- data/lib/user_notification/orm/mongoid/adapter.rb +12 -0
- data/lib/user_notification/orm/mongoid/notification.rb +26 -0
- data/lib/user_notification/orm/mongoid/trackable.rb +11 -0
- data/lib/user_notification/orm/mongoid.rb +4 -0
- data/lib/user_notification/renderable.rb +118 -0
- data/lib/user_notification/roles/deactivatable.rb +42 -0
- data/lib/user_notification/roles/tracked.rb +183 -0
- data/lib/user_notification/utility/store_controller.rb +37 -0
- data/lib/user_notification/utility/view_helpers.rb +26 -0
- data/lib/user_notification/version.rb +4 -0
- data/lib/user_notification.rb +68 -0
- data/test/migrations/001_create_notifications.rb +24 -0
- data/test/migrations/002_create_articles.rb +11 -0
- data/test/migrations/003_create_users.rb +8 -0
- data/test/migrations/004_add_nonstandard_to_notifications.rb +7 -0
- data/test/mongo_mapper.yml +4 -0
- data/test/mongoid.yml +6 -0
- data/test/test_activist.rb +56 -0
- data/test/test_common.rb +168 -0
- data/test/test_controller_integration.rb +41 -0
- data/test/test_generators.rb +30 -0
- data/test/test_helper.rb +124 -0
- data/test/test_notification.rb +67 -0
- data/test/test_tracking.rb +378 -0
- data/test/test_view_helpers.rb +36 -0
- data/test/views/layouts/_notification.erb +1 -0
- data/test/views/user_notification/_test.erb +8 -0
- metadata +260 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module ActiveRecord
|
4
|
+
# Module extending classes that serve as owners
|
5
|
+
module Activist
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# Loads the {ClassMethods#activist} method for declaring the class
|
9
|
+
# as an activist.
|
10
|
+
def self.extended(base)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
# Module extending classes that serve as owners
|
16
|
+
module ClassMethods
|
17
|
+
# Adds ActiveRecord associations to model to simplify fetching
|
18
|
+
# so you can list notifications performed by the owner.
|
19
|
+
# It is completely optional. Any model can be an owner to an notification
|
20
|
+
# even without being an explicit activist.
|
21
|
+
#
|
22
|
+
# == Usage:
|
23
|
+
# In model:
|
24
|
+
#
|
25
|
+
# class User < ActiveRecord::Base
|
26
|
+
# include UserNotification::Model
|
27
|
+
# activist
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# In controller:
|
31
|
+
# User.first.notifications
|
32
|
+
#
|
33
|
+
def activist
|
34
|
+
# Association of notifications as their owner.
|
35
|
+
# @!method notifications_as_owner
|
36
|
+
# @return [Array<Notification>] Activities which self is the owner of.
|
37
|
+
has_many :notifications_as_owner, :class_name => "::UserNotification::Notification", :as => :owner
|
38
|
+
|
39
|
+
# Association of notifications as their recipient.
|
40
|
+
# @!method notifications_as_recipient
|
41
|
+
# @return [Array<Notification>] Activities which self is the recipient of.
|
42
|
+
has_many :notifications_as_recipient, :class_name => "::UserNotification::Notification", :as => :recipient
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
# Support for ActiveRecord for UserNotification. Used by default and supported
|
4
|
+
# officialy.
|
5
|
+
module ActiveRecord
|
6
|
+
# Provides ActiveRecord specific, database-related routines for use by
|
7
|
+
# UserNotification.
|
8
|
+
class Adapter
|
9
|
+
# Creates the notification on `trackable` with `options`
|
10
|
+
def self.create_notification(trackable, options)
|
11
|
+
trackable.notifications.create options
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module ActiveRecord
|
4
|
+
# The ActiveRecord model containing
|
5
|
+
# details about recorded notification.
|
6
|
+
class Notification < ::ActiveRecord::Base
|
7
|
+
include Renderable
|
8
|
+
|
9
|
+
# Define polymorphic association to the parent
|
10
|
+
belongs_to :trackable, :polymorphic => true
|
11
|
+
# Define ownership to a resource responsible for this notification
|
12
|
+
belongs_to :owner, :polymorphic => true
|
13
|
+
# Define ownership to a resource targeted by this notification
|
14
|
+
belongs_to :recipient, :polymorphic => true
|
15
|
+
# Serialize parameters Hash
|
16
|
+
serialize :parameters, Hash
|
17
|
+
|
18
|
+
if ::ActiveRecord::VERSION::MAJOR < 4
|
19
|
+
attr_accessible :key, :owner, :parameters, :recipient, :trackable
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module ActiveRecord
|
4
|
+
# Implements {UserNotification::Trackable} for ActiveRecord
|
5
|
+
# @see UserNotification::Trackable
|
6
|
+
module Trackable
|
7
|
+
# Creates an association for notifications where self is the *trackable*
|
8
|
+
# object.
|
9
|
+
def self.extended(base)
|
10
|
+
base.has_many :notifications, :class_name => "::UserNotification::Notification", :as => :trackable
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module MongoMapper
|
4
|
+
# Module extending classes that serve as owners
|
5
|
+
module Activist
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
# Association of notifications as their owner.
|
12
|
+
# @!method notifications
|
13
|
+
# @return [Array<Notification>] Activities which self is the owner of.
|
14
|
+
|
15
|
+
# Association of notifications as their recipient.
|
16
|
+
# @!method private_notifications
|
17
|
+
# @return [Array<Notification>] Activities which self is the recipient of.
|
18
|
+
|
19
|
+
# Module extending classes that serve as owners
|
20
|
+
module ClassMethods
|
21
|
+
# Adds MongoMapper associations to model to simplify fetching
|
22
|
+
# so you can list notifications performed by the owner.
|
23
|
+
# It is completely optional. Any model can be an owner to an notification
|
24
|
+
# even without being an explicit activist.
|
25
|
+
#
|
26
|
+
# == Usage:
|
27
|
+
# In model:
|
28
|
+
#
|
29
|
+
# class User
|
30
|
+
# include MongoMapper::Document
|
31
|
+
# include UserNotification::Model
|
32
|
+
# activist
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# In controller:
|
36
|
+
# User.first.notifications
|
37
|
+
#
|
38
|
+
def activist
|
39
|
+
many :notifications_as_owner, :class_name => "::UserNotification::Notification", :as => :owner
|
40
|
+
many :notifications_as_recipient, :class_name => "::UserNotification::Notification", :as => :recipient
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module MongoMapper
|
4
|
+
class Adapter
|
5
|
+
# Creates the notification on `trackable` with `options`
|
6
|
+
def self.create_notification(trackable, options)
|
7
|
+
trackable.notifications.create options
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'mongo_mapper'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
|
4
|
+
module UserNotification
|
5
|
+
module ORM
|
6
|
+
module MongoMapper
|
7
|
+
# The MongoMapper document containing
|
8
|
+
# details about recorded notification.
|
9
|
+
class Notification
|
10
|
+
include ::MongoMapper::Document
|
11
|
+
include Renderable
|
12
|
+
|
13
|
+
class SymbolHash < Hash
|
14
|
+
def self.from_mongo(value)
|
15
|
+
value.symbolize_keys unless value.nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Define polymorphic association to the parent
|
20
|
+
belongs_to :trackable, polymorphic: true
|
21
|
+
# Define ownership to a resource responsible for this notification
|
22
|
+
belongs_to :owner, polymorphic: true
|
23
|
+
# Define ownership to a resource targeted by this notification
|
24
|
+
belongs_to :recipient, polymorphic: true
|
25
|
+
|
26
|
+
key :key, String
|
27
|
+
key :parameters, SymbolHash
|
28
|
+
|
29
|
+
timestamps!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module UserNotification
|
2
|
+
module ORM
|
3
|
+
module Mongoid
|
4
|
+
# Module extending classes that serve as owners
|
5
|
+
module Activist
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
# Association of notifications as their owner.
|
12
|
+
# @!method notifications
|
13
|
+
# @return [Array<Notification>] Activities which self is the owner of.
|
14
|
+
|
15
|
+
# Association of notifications as their recipient.
|
16
|
+
# @!method private_notifications
|
17
|
+
# @return [Array<Notification>] Activities which self is the recipient of.
|
18
|
+
|
19
|
+
# Module extending classes that serve as owners
|
20
|
+
module ClassMethods
|
21
|
+
# Adds ActiveRecord associations to model to simplify fetching
|
22
|
+
# so you can list notifications performed by the owner.
|
23
|
+
# It is completely optional. Any model can be an owner to an notification
|
24
|
+
# even without being an explicit activist.
|
25
|
+
#
|
26
|
+
# == Usage:
|
27
|
+
# In model:
|
28
|
+
#
|
29
|
+
# class User < ActiveRecord::Base
|
30
|
+
# include UserNotification::Model
|
31
|
+
# activist
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# In controller:
|
35
|
+
# User.first.notifications
|
36
|
+
#
|
37
|
+
def activist
|
38
|
+
has_many :notifications_as_owner, :class_name => "::UserNotification::Notification", :inverse_of => :owner
|
39
|
+
has_many :notifications_as_recipient, :class_name => "::UserNotification::Notification", :inverse_of => :recipient
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
|
3
|
+
module UserNotification
|
4
|
+
module ORM
|
5
|
+
module Mongoid
|
6
|
+
# The ActiveRecord model containing
|
7
|
+
# details about recorded notification.
|
8
|
+
class Notification
|
9
|
+
include ::Mongoid::Document
|
10
|
+
include ::Mongoid::Timestamps
|
11
|
+
include ::Mongoid::Attributes::Dynamic if (::Mongoid::VERSION =~ /^4/) == 0
|
12
|
+
include Renderable
|
13
|
+
|
14
|
+
# Define polymorphic association to the parent
|
15
|
+
belongs_to :trackable, polymorphic: true
|
16
|
+
# Define ownership to a resource responsible for this notification
|
17
|
+
belongs_to :owner, polymorphic: true
|
18
|
+
# Define ownership to a resource targeted by this notification
|
19
|
+
belongs_to :recipient, polymorphic: true
|
20
|
+
|
21
|
+
field :key, type: String
|
22
|
+
field :parameters, type: Hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module UserNotification
|
2
|
+
# Provides logic for rendering notifications. Handles both i18n strings
|
3
|
+
# support and smart partials rendering (different templates per notification key).
|
4
|
+
module Renderable
|
5
|
+
# Virtual attribute returning text description of the notification
|
6
|
+
# using the notification's key to translate using i18n.
|
7
|
+
def text(params = {})
|
8
|
+
# TODO: some helper for key transformation for two supported formats
|
9
|
+
k = key.split('.')
|
10
|
+
k.unshift('notification') if k.first != 'notification'
|
11
|
+
k = k.join('.')
|
12
|
+
|
13
|
+
I18n.t(k, parameters.merge(params) || {})
|
14
|
+
end
|
15
|
+
|
16
|
+
# Renders notification from views.
|
17
|
+
#
|
18
|
+
# @param [ActionView::Base] context
|
19
|
+
# @return [nil] nil
|
20
|
+
#
|
21
|
+
# Renders notification to the given ActionView context with included
|
22
|
+
# AV::Helpers::RenderingHelper (most commonly just ActionView::Base)
|
23
|
+
#
|
24
|
+
# The *preferred* *way* of rendering notifications is
|
25
|
+
# to provide a template specifying how the rendering should be happening.
|
26
|
+
# However, one may choose using _I18n_ based approach when developing
|
27
|
+
# an application that supports plenty of languages.
|
28
|
+
#
|
29
|
+
# If partial view exists that matches the *key* attribute
|
30
|
+
# renders that partial with local variables set to contain both
|
31
|
+
# Notification and notification_parameters (hash with indifferent access)
|
32
|
+
#
|
33
|
+
# Otherwise, it outputs the I18n translation to the context
|
34
|
+
# @example Render a list of all notifications from a view (erb)
|
35
|
+
# <ul>
|
36
|
+
# <% for notification in UserNotification::Notification.all %>
|
37
|
+
# <li><%= render_notification(notification) %></li>
|
38
|
+
# <% end %>
|
39
|
+
# </ul>
|
40
|
+
#
|
41
|
+
# = Layouts
|
42
|
+
# You can supply a layout that will be used for notification partials
|
43
|
+
# with :layout param.
|
44
|
+
# Keep in mind that layouts for partials are also partials.
|
45
|
+
# @example Supply a layout
|
46
|
+
# # in views:
|
47
|
+
# # All examples look for a layout in app/views/layouts/_notification.erb
|
48
|
+
# render_notification @notification, :layout => "notification"
|
49
|
+
# render_notification @notification, :layout => "layouts/notification"
|
50
|
+
# render_notification @notification, :layout => :notification
|
51
|
+
#
|
52
|
+
# # app/views/layouts/_notification.erb
|
53
|
+
# <p><%= a.created_at %></p>
|
54
|
+
# <%= yield %>
|
55
|
+
#
|
56
|
+
# = Creating a template
|
57
|
+
# To use templates for formatting how the notification should render,
|
58
|
+
# create a template based on notification key, for example:
|
59
|
+
#
|
60
|
+
# Given a key _notification.article.create_, create directory tree
|
61
|
+
# _app/views/user_notification/article/_ and create the _create_ partial there
|
62
|
+
#
|
63
|
+
# Note that if a key consists of more than three parts splitted by commas, your
|
64
|
+
# directory structure will have to be deeper, for example:
|
65
|
+
# notification.article.comments.destroy => app/views/user_notification/articles/comments/_destroy.html.erb
|
66
|
+
#
|
67
|
+
# == Variables in templates
|
68
|
+
# From within a template there are two variables at your disposal:
|
69
|
+
# * notification (aliased as *a* for a shortcut)
|
70
|
+
# * params (aliased as *p*) [converted into a HashWithIndifferentAccess]
|
71
|
+
#
|
72
|
+
# @example Template for key: _notification.article.create_ (erb)
|
73
|
+
# <p>
|
74
|
+
# Article <strong><%= p[:name] %></strong>
|
75
|
+
# was written by <em><%= p["author"] %></em>
|
76
|
+
# <%= distance_of_time_in_words_to_now(a.created_at) %>
|
77
|
+
# </p>
|
78
|
+
def render(context, params = {})
|
79
|
+
partial_path = nil
|
80
|
+
if params.has_key? :display
|
81
|
+
# if i18n has been requested, let it render and bail
|
82
|
+
return context.render :text => self.text(params) if params[:display].to_sym == :"i18n"
|
83
|
+
partial_path = 'user_notification/'+params[:display].to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
controller = UserNotification.get_controller
|
87
|
+
if layout = params.delete(:layout)
|
88
|
+
layout = layout.to_s
|
89
|
+
layout = layout[0,8] == "layouts/" ? layout : "layouts/#{layout}"
|
90
|
+
end
|
91
|
+
|
92
|
+
locals = params.delete(:locals) || Hash.new
|
93
|
+
|
94
|
+
params_indifferent = self.parameters.with_indifferent_access
|
95
|
+
params_indifferent.merge!(params)
|
96
|
+
|
97
|
+
context.render :partial => (partial_path || self.template_path(self.key)),
|
98
|
+
:layout => layout,
|
99
|
+
:locals => locals.merge(:a => self, :notification => self,
|
100
|
+
:controller => controller,
|
101
|
+
:current_user => controller.respond_to?(:current_user) ?
|
102
|
+
controller.current_user : nil ,
|
103
|
+
:p => params_indifferent, :params => params_indifferent)
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
# Builds the path to template based on notification key
|
108
|
+
# TODO: verify that attribute `key` is splitted by commas
|
109
|
+
# and that the word before first comma is equal to
|
110
|
+
# "notification"
|
111
|
+
def template_path(key)
|
112
|
+
path = key.split(".")
|
113
|
+
path.delete_at(0) if path[0] == "notification"
|
114
|
+
path.unshift "user_notification"
|
115
|
+
path.join("/")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module UserNotification
|
2
|
+
# Enables per-class disabling of UserNotification functionality.
|
3
|
+
module Deactivatable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :user_notification_enabled_for_model
|
8
|
+
set_user_notification_class_defaults
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns true if UserNotification is enabled
|
12
|
+
# globally and for this class.
|
13
|
+
# @return [Boolean]
|
14
|
+
# @api private
|
15
|
+
# @since 0.5.0
|
16
|
+
# overrides the method from Common
|
17
|
+
def user_notification_enabled?
|
18
|
+
UserNotification.enabled? && self.class.user_notification_enabled_for_model
|
19
|
+
end
|
20
|
+
|
21
|
+
# Provides global methods to disable or enable UserNotification on a per-class
|
22
|
+
# basis.
|
23
|
+
module ClassMethods
|
24
|
+
# Switches user_notification off for this class
|
25
|
+
def user_notification_off
|
26
|
+
self.user_notification_enabled_for_model = false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Switches user_notification on for this class
|
30
|
+
def user_notification_on
|
31
|
+
self.user_notification_enabled_for_model = true
|
32
|
+
end
|
33
|
+
|
34
|
+
# @since 1.0.0
|
35
|
+
# @api private
|
36
|
+
def set_user_notification_class_defaults
|
37
|
+
super
|
38
|
+
self.user_notification_enabled_for_model = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
module UserNotification
|
2
|
+
# Main module extending classes we want to keep track of.
|
3
|
+
module Tracked
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
# A shortcut method for setting custom key, owner and parameters of {Notification}
|
6
|
+
# in one line. Accepts a hash with 3 keys:
|
7
|
+
# :key, :owner, :params. You can specify all of them or just the ones you want to overwrite.
|
8
|
+
#
|
9
|
+
# == Options
|
10
|
+
#
|
11
|
+
# [:key]
|
12
|
+
# See {Common#notification_key}
|
13
|
+
# [:owner]
|
14
|
+
# See {Common#notification_owner}
|
15
|
+
# [:params]
|
16
|
+
# See {Common#notification_params}
|
17
|
+
# [:recipient]
|
18
|
+
# Set the recipient for this notification. Useful for private notifications, which should only be visible to a certain user. See {Common#notification_recipient}.
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# @article = Article.new
|
22
|
+
# @article.title = "New article"
|
23
|
+
# @article.notification :key => "my.custom.article.key", :owner => @article.author, :params => {:title => @article.title}
|
24
|
+
# @article.save
|
25
|
+
# @article.notifications.last.key #=> "my.custom.article.key"
|
26
|
+
# @article.notifications.last.parameters #=> {:title => "New article"}
|
27
|
+
#
|
28
|
+
# @param options [Hash] instance options to set on the tracked model
|
29
|
+
# @return [nil]
|
30
|
+
def notification(options = {})
|
31
|
+
rest = options.clone
|
32
|
+
self.notification_key = rest.delete(:key) if rest[:key]
|
33
|
+
self.notification_owner = rest.delete(:owner) if rest[:owner]
|
34
|
+
self.notification_params = rest.delete(:params) if rest[:params]
|
35
|
+
self.notification_recipient = rest.delete(:recipient) if rest[:recipient]
|
36
|
+
self.notification_custom_fields = rest if rest.count > 0
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Module with basic +tracked+ method that enables tracking models.
|
41
|
+
module ClassMethods
|
42
|
+
# Adds required callbacks for creating and updating
|
43
|
+
# tracked models and adds +notifications+ relation for listing
|
44
|
+
# associated notifications.
|
45
|
+
#
|
46
|
+
# == Parameters:
|
47
|
+
# [:owner]
|
48
|
+
# Specify the owner of the {Notification} (person responsible for the action).
|
49
|
+
# It can be a Proc, Symbol or an ActiveRecord object:
|
50
|
+
# == Examples:
|
51
|
+
#
|
52
|
+
# tracked :owner => :author
|
53
|
+
# tracked :owner => proc {|o| o.author}
|
54
|
+
#
|
55
|
+
# Keep in mind that owner relation is polymorphic, so you can't just
|
56
|
+
# provide id number of the owner object.
|
57
|
+
# [:recipient]
|
58
|
+
# Specify the recipient of the {Notification}
|
59
|
+
# It can be a Proc, Symbol, or an ActiveRecord object
|
60
|
+
# == Examples:
|
61
|
+
#
|
62
|
+
# tracked :recipient => :author
|
63
|
+
# tracked :recipient => proc {|o| o.author}
|
64
|
+
#
|
65
|
+
# Keep in mind that recipient relation is polymorphic, so you can't just
|
66
|
+
# provide id number of the owner object.
|
67
|
+
# [:params]
|
68
|
+
# Accepts a Hash with custom parameters you want to pass to i18n.translate
|
69
|
+
# method. It is later used in {Renderable#text} method.
|
70
|
+
# == Example:
|
71
|
+
# class Article < ActiveRecord::Base
|
72
|
+
# include UserNotification::Model
|
73
|
+
# tracked :params => {
|
74
|
+
# :title => :title,
|
75
|
+
# :author_name => "Michael",
|
76
|
+
# :category_name => proc {|controller, model_instance| model_instance.category.name},
|
77
|
+
# :summary => proc {|controller, model_instance| truncate(model.text, :length => 30)}
|
78
|
+
# }
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# Values in the :params hash can either be an *exact* *value*, a *Proc/Lambda* executed before saving the notification or a *Symbol*
|
82
|
+
# which is a an attribute or a method name executed on the tracked model's instance.
|
83
|
+
#
|
84
|
+
# Everything specified here has a lower priority than parameters
|
85
|
+
# specified directly in {#notification} method.
|
86
|
+
# So treat it as a place where you provide 'default' values or where you
|
87
|
+
# specify what data should be gathered for every notification.
|
88
|
+
# For more dynamic settings refer to {Notification} model documentation.
|
89
|
+
# [:skip_defaults]
|
90
|
+
# Disables recording of notifications on create/update/destroy leaving that to programmer's choice. Check {UserNotification::Common#create_notification}
|
91
|
+
# for a guide on how to manually record notifications.
|
92
|
+
# [:only]
|
93
|
+
# Accepts a symbol or an array of symbols, of which any combination of the three is accepted:
|
94
|
+
# * _:create_
|
95
|
+
# * _:update_
|
96
|
+
# * _:destroy_
|
97
|
+
# Selecting one or more of these will make UserNotification create notifications
|
98
|
+
# automatically for the tracked model on selected actions.
|
99
|
+
#
|
100
|
+
# Resulting notifications will have have keys assigned to, respectively:
|
101
|
+
# * _article.create_
|
102
|
+
# * _article.update_
|
103
|
+
# * _article.destroy_
|
104
|
+
# Since only three options are valid,
|
105
|
+
# see _:except_ option for a shorter version
|
106
|
+
# [:except]
|
107
|
+
# Accepts a symbol or an array of symbols with values like in _:only_, above.
|
108
|
+
# Values provided will be subtracted from all default actions:
|
109
|
+
# (create, update, destroy).
|
110
|
+
#
|
111
|
+
# So, passing _create_ would track and automatically create
|
112
|
+
# notifications on _update_ and _destroy_ actions,
|
113
|
+
# but not on the _create_ action.
|
114
|
+
# [:on]
|
115
|
+
# Accepts a Hash with key being the *action* on which to execute *value* (proc)
|
116
|
+
# Currently supported only for CRUD actions which are enabled in _:only_
|
117
|
+
# or _:except_ options on this method.
|
118
|
+
#
|
119
|
+
# Key-value pairs in this option define callbacks that can decide
|
120
|
+
# whether to create an notification or not. Procs have two attributes for
|
121
|
+
# use: _model_ and _controller_. If the proc returns true, the notification
|
122
|
+
# will be created, if not, then notification will not be saved.
|
123
|
+
#
|
124
|
+
# == Example:
|
125
|
+
# # app/models/article.rb
|
126
|
+
# tracked :on => {:update => proc {|model, controller| model.published? }}
|
127
|
+
#
|
128
|
+
# In the example above, given a model Article with boolean column _published_.
|
129
|
+
# The notifications with key _article.update_ will only be created
|
130
|
+
# if the published status is set to true on that article.
|
131
|
+
# @param opts [Hash] options
|
132
|
+
# @return [nil] options
|
133
|
+
def tracked(opts = {})
|
134
|
+
options = opts.clone
|
135
|
+
|
136
|
+
all_options = [:create, :update, :destroy]
|
137
|
+
|
138
|
+
if !options.has_key?(:skip_defaults) && !options[:only] && !options[:except]
|
139
|
+
include Creation
|
140
|
+
include Destruction
|
141
|
+
include Update
|
142
|
+
end
|
143
|
+
options.delete(:skip_defaults)
|
144
|
+
|
145
|
+
if options[:except]
|
146
|
+
options[:only] = all_options - Array(options.delete(:except))
|
147
|
+
end
|
148
|
+
|
149
|
+
if options[:only]
|
150
|
+
Array(options[:only]).each do |opt|
|
151
|
+
if opt.eql?(:create)
|
152
|
+
include Creation
|
153
|
+
elsif opt.eql?(:destroy)
|
154
|
+
include Destruction
|
155
|
+
elsif opt.eql?(:update)
|
156
|
+
include Update
|
157
|
+
end
|
158
|
+
end
|
159
|
+
options.delete(:only)
|
160
|
+
end
|
161
|
+
|
162
|
+
if options[:owner]
|
163
|
+
self.notification_owner_global = options.delete(:owner)
|
164
|
+
end
|
165
|
+
if options[:recipient]
|
166
|
+
self.notification_recipient_global = options.delete(:recipient)
|
167
|
+
end
|
168
|
+
if options[:params]
|
169
|
+
self.notification_params_global = options.delete(:params)
|
170
|
+
end
|
171
|
+
if options.has_key?(:on) and options[:on].is_a? Hash
|
172
|
+
self.notification_hooks = options.delete(:on).select {|_, v| v.is_a? Proc}.symbolize_keys
|
173
|
+
end
|
174
|
+
|
175
|
+
options.each do |k, v|
|
176
|
+
self.notification_custom_fields_global[k] = v
|
177
|
+
end
|
178
|
+
|
179
|
+
nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|