activity_notification 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +56 -0
- data/.rspec +3 -0
- data/.travis.yml +28 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +174 -0
- data/MIT-LICENSE +20 -0
- data/README.md +437 -0
- data/Rakefile +19 -0
- data/activity_notification.gemspec +33 -0
- data/app/controllers/activity_notification/notifications_controller.rb +119 -0
- data/app/controllers/activity_notification/notifications_with_devise_controller.rb +29 -0
- data/app/mailers/activity_notification/mailer.rb +13 -0
- data/app/views/activity_notification/mailer/default/default.html.erb +7 -0
- data/app/views/activity_notification/notifications/default/_default.html.erb +36 -0
- data/app/views/activity_notification/notifications/default/_index.html.erb +9 -0
- data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -0
- data/app/views/activity_notification/notifications/default/index.html.erb +17 -0
- data/app/views/activity_notification/notifications/default/open.js.erb +2 -0
- data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -0
- data/app/views/activity_notification/notifications/default/show.html.erb +2 -0
- data/config/locales/en.yml +8 -0
- data/lib/activity_notification.rb +52 -0
- data/lib/activity_notification/apis/notification_api.rb +147 -0
- data/lib/activity_notification/common.rb +86 -0
- data/lib/activity_notification/config.rb +23 -0
- data/lib/activity_notification/controllers/store_controller.rb +30 -0
- data/lib/activity_notification/helpers/polymorphic_helpers.rb +32 -0
- data/lib/activity_notification/helpers/view_helpers.rb +108 -0
- data/lib/activity_notification/mailers/helpers.rb +97 -0
- data/lib/activity_notification/models/notifiable.rb +136 -0
- data/lib/activity_notification/models/notification.rb +50 -0
- data/lib/activity_notification/models/notifier.rb +11 -0
- data/lib/activity_notification/models/target.rb +104 -0
- data/lib/activity_notification/rails.rb +6 -0
- data/lib/activity_notification/rails/routes.rb +105 -0
- data/lib/activity_notification/renderable.rb +142 -0
- data/lib/activity_notification/roles/acts_as_notifiable.rb +37 -0
- data/lib/activity_notification/roles/acts_as_target.rb +30 -0
- data/lib/activity_notification/version.rb +3 -0
- data/lib/generators/activity_notification/controllers_generator.rb +44 -0
- data/lib/generators/activity_notification/install_generator.rb +45 -0
- data/lib/generators/activity_notification/migration/migration_generator.rb +17 -0
- data/lib/generators/activity_notification/notification/notification_generator.rb +17 -0
- data/lib/generators/activity_notification/views_generator.rb +44 -0
- data/lib/generators/templates/README +53 -0
- data/lib/generators/templates/active_record/migration.rb +18 -0
- data/lib/generators/templates/activity_notification.rb +18 -0
- data/lib/generators/templates/controllers/README +13 -0
- data/lib/generators/templates/controllers/notifications_controller.rb +66 -0
- data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +74 -0
- data/lib/generators/templates/notification/notification.rb +3 -0
- data/lib/tasks/activity_notification_tasks.rake +4 -0
- data/spec/concerns/notification_api_spec.rb +531 -0
- data/spec/factories/articles.rb +5 -0
- data/spec/factories/comments.rb +6 -0
- data/spec/factories/notifications.rb +7 -0
- data/spec/factories/users.rb +5 -0
- data/spec/models/notification_spec.rb +259 -0
- data/spec/rails_app/Rakefile +6 -0
- data/spec/rails_app/app/controllers/application_controller.rb +5 -0
- data/spec/rails_app/app/controllers/concerns/.keep +0 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/mailers/.keep +0 -0
- data/spec/rails_app/app/models/.keep +0 -0
- data/spec/rails_app/app/models/article.rb +12 -0
- data/spec/rails_app/app/models/comment.rb +18 -0
- data/spec/rails_app/app/models/concerns/.keep +0 -0
- data/spec/rails_app/app/models/user.rb +8 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_app/bin/bundle +3 -0
- data/spec/rails_app/bin/rails +4 -0
- data/spec/rails_app/bin/rake +4 -0
- data/spec/rails_app/bin/setup +29 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +20 -0
- data/spec/rails_app/config/boot.rb +5 -0
- data/spec/rails_app/config/database.yml +25 -0
- data/spec/rails_app/config/environment.rb +12 -0
- data/spec/rails_app/config/environments/development.rb +44 -0
- data/spec/rails_app/config/environments/production.rb +79 -0
- data/spec/rails_app/config/environments/test.rb +45 -0
- data/spec/rails_app/config/initializers/activity_notification.rb +18 -0
- data/spec/rails_app/config/initializers/assets.rb +11 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/rails_app/config/initializers/devise.rb +274 -0
- data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails_app/config/initializers/inflections.rb +16 -0
- data/spec/rails_app/config/initializers/mime_types.rb +4 -0
- data/spec/rails_app/config/initializers/session_store.rb +3 -0
- data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_app/config/routes.rb +5 -0
- data/spec/rails_app/config/secrets.yml +22 -0
- data/spec/rails_app/db/migrate/20160715050420_create_notifications.rb +18 -0
- data/spec/rails_app/db/migrate/20160715050433_create_test_tables.rb +36 -0
- data/spec/rails_app/db/schema.rb +73 -0
- data/spec/rails_app/public/404.html +67 -0
- data/spec/rails_app/public/422.html +67 -0
- data/spec/rails_app/public/500.html +66 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/spec_helper.rb +34 -0
- metadata +309 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
class Notification < ActiveRecord::Base
|
3
|
+
include Renderable
|
4
|
+
include Common
|
5
|
+
include NotificationApi
|
6
|
+
self.table_name = ActivityNotification.config.table_name
|
7
|
+
|
8
|
+
belongs_to :target, polymorphic: true
|
9
|
+
belongs_to :notifiable, polymorphic: true
|
10
|
+
belongs_to :group, polymorphic: true
|
11
|
+
belongs_to :group_owner, class_name: :Notification
|
12
|
+
has_many :group_members,
|
13
|
+
class_name: "::ActivityNotification::Notification",
|
14
|
+
foreign_key: :group_owner_id
|
15
|
+
belongs_to :notifier, polymorphic: true
|
16
|
+
|
17
|
+
# Serialize parameters Hash
|
18
|
+
serialize :parameters, Hash
|
19
|
+
|
20
|
+
validates :target, presence: true
|
21
|
+
validates :notifiable, presence: true
|
22
|
+
validates :key, presence: true
|
23
|
+
|
24
|
+
scope :group_owners_only, -> { where(group_owner_id: nil) }
|
25
|
+
scope :group_members_only, -> { where.not(group_owner_id: nil) }
|
26
|
+
scope :unopened_only, -> { where(opened_at: nil) }
|
27
|
+
scope :unopened_index, -> { unopened_only.group_owners_only.latest_order }
|
28
|
+
scope :opened_only!, -> { where.not(opened_at: nil) }
|
29
|
+
scope :opened_only, ->(limit) { opened_only!.limit(limit) }
|
30
|
+
scope :opened_index, ->(limit) { opened_only(limit).group_owners_only.latest_order }
|
31
|
+
scope :unopened_index_group_members_only, -> { where(group_owner_id: unopened_index.pluck(:id)) }
|
32
|
+
scope :opened_index_group_members_only, ->(limit) { where(group_owner_id: opened_index(limit).pluck(:id)) }
|
33
|
+
|
34
|
+
scope :filtered_by_target, ->(target) { where(target: target) }
|
35
|
+
scope :filtered_by_instance, ->(notifiable) { where(notifiable: notifiable) }
|
36
|
+
scope :filtered_by_type, ->(notifiable_type) { where(notifiable_type: notifiable_type) }
|
37
|
+
scope :filtered_by_group, ->(group) { where(group: group) }
|
38
|
+
scope :filtered_by_key, ->(key) { where(key: key) }
|
39
|
+
|
40
|
+
scope :with_target, -> { includes(:target) }
|
41
|
+
scope :with_notifiable, -> { includes(:notifiable) }
|
42
|
+
scope :with_group, -> { includes(:group) }
|
43
|
+
scope :with_notifier, -> { includes(:notifier) }
|
44
|
+
|
45
|
+
scope :latest_order, -> { order(created_at: :desc) }
|
46
|
+
scope :earliest_order, -> { order(created_at: :asc) }
|
47
|
+
scope :latest, -> { latest_order.first }
|
48
|
+
scope :earliest, -> { earliest_order.first }
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
module Target
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
include Common
|
6
|
+
include ActsAsTarget
|
7
|
+
has_many :notifications,
|
8
|
+
class_name: "::ActivityNotification::Notification",
|
9
|
+
as: :target
|
10
|
+
class_attribute :_notification_email, :_notification_email_allowed
|
11
|
+
set_target_class_defaults
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def set_target_class_defaults
|
16
|
+
self._notification_email = nil
|
17
|
+
self._notification_email_allowed = false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def mailer_to
|
22
|
+
resolve_value(_notification_email)
|
23
|
+
end
|
24
|
+
|
25
|
+
def notification_email_allowed?(notifiable, key)
|
26
|
+
resolve_value(_notification_email_allowed, notifiable, key)
|
27
|
+
end
|
28
|
+
|
29
|
+
def unopened_notification_count
|
30
|
+
unopened_notification_index.count
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_unopened_notifications?
|
34
|
+
unopened_notification_index.exists?
|
35
|
+
end
|
36
|
+
|
37
|
+
#TODO is this switching the best solution?
|
38
|
+
def notification_index(limit = nil)
|
39
|
+
# When the target have unopened notifications
|
40
|
+
notifications.unopened_index.exists? ?
|
41
|
+
# Return unopened notifications
|
42
|
+
unopened_notification_index(limit) :
|
43
|
+
# Otherwise, return opened notifications
|
44
|
+
limit.present? ?
|
45
|
+
opened_notification_index(limit) :
|
46
|
+
opened_notification_index
|
47
|
+
end
|
48
|
+
|
49
|
+
def unopened_notification_index(limit = nil)
|
50
|
+
limit.present? ?
|
51
|
+
notifications.unopened_index.limit(limit) :
|
52
|
+
notifications.unopened_index
|
53
|
+
end
|
54
|
+
|
55
|
+
def opened_notification_index(limit = ActivityNotification.config.opened_limit)
|
56
|
+
notifications.opened_index(limit)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Wrapper methods of SimpleNotify class methods
|
61
|
+
|
62
|
+
def notify_to(notifiable, options = {})
|
63
|
+
Notification.notify_to(self, notifiable, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
def open_all_notifications(opened_at = nil)
|
67
|
+
Notification.open_all_of(self, opened_at)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Methods to be overriden
|
71
|
+
|
72
|
+
# Typical method to get notifications index
|
73
|
+
def notification_index_with_attributes(limit = nil)
|
74
|
+
# When the target have unopened notifications
|
75
|
+
unopened_notification_index.exists? ?
|
76
|
+
# Return unopened notifications
|
77
|
+
unopened_notification_index_with_attributes(limit) :
|
78
|
+
# Otherwise, return opened notifications
|
79
|
+
limit.present? ?
|
80
|
+
opened_notification_index_with_attributes(limit) :
|
81
|
+
opened_notification_index_with_attributes
|
82
|
+
end
|
83
|
+
|
84
|
+
def unopened_notification_index_with_attributes(limit = nil)
|
85
|
+
Notification.group_member_exists?(unopened_notification_index(limit)) ?
|
86
|
+
unopened_notification_index(limit).with_target.with_notifiable.with_group.with_notifier :
|
87
|
+
unopened_notification_index(limit).with_target.with_notifiable.with_notifier
|
88
|
+
end
|
89
|
+
|
90
|
+
def opened_notification_index_with_attributes(limit = ActivityNotification.config.opened_limit)
|
91
|
+
Notification.group_member_exists?(opened_notification_index(limit)) ?
|
92
|
+
opened_notification_index(limit).with_target.with_notifiable.with_group.with_notifier :
|
93
|
+
opened_notification_index(limit).with_target.with_notifiable.with_notifier
|
94
|
+
end
|
95
|
+
|
96
|
+
def authenticate_with_devise?(current_resource)
|
97
|
+
unless current_resource.instance_of? self.class
|
98
|
+
raise TypeError, "Defferent type of devise resource #{current_resource.class.to_s} has been passed to #{self.class}##{__method__}. You have to override #{self.class}##{__method__} method."
|
99
|
+
end
|
100
|
+
current_resource == self
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "active_support/core_ext/object/try"
|
2
|
+
require "active_support/core_ext/hash/slice"
|
3
|
+
|
4
|
+
module ActionDispatch::Routing
|
5
|
+
class Mapper
|
6
|
+
# Includes notify_to method for routes.
|
7
|
+
# This method is responsible to generate all needed routes for activity_notification
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# notify_to :users
|
12
|
+
# notify_to :users, with_devise: :users
|
13
|
+
# notify_to :users, with_devise: :users, only: [:open, :open_all, :move]
|
14
|
+
#
|
15
|
+
# When you have an User model configured as a target (e.g. defined acts_as_target),
|
16
|
+
# you can creat this inside your routes:
|
17
|
+
#
|
18
|
+
# notify_to :users
|
19
|
+
#
|
20
|
+
# This method creates the needed routes:
|
21
|
+
#
|
22
|
+
# # Notification routes
|
23
|
+
# user_notifications GET /users/:user_id/notifications(.:format)
|
24
|
+
# {controller:"activity_notification/notifications", action:"index", target_type:"users"}
|
25
|
+
# user_notification GET /users/:user_id/notifications/:id(.:format)
|
26
|
+
# {controller:"activity_notification/notifications", action:"show", target_type:"users"}
|
27
|
+
# user_notification DELETE /users/:user_id/notifications/:id(.:format)
|
28
|
+
# {controller:"activity_notification/notifications", action:"destroy", target_type:"users"}
|
29
|
+
# open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
|
30
|
+
# {controller:"activity_notification/notifications", action:"open_all", target_type:"users"}
|
31
|
+
# move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
|
32
|
+
# {controller:"activity_notification/notifications", action:"move", target_type:"users"}
|
33
|
+
# open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
|
34
|
+
# {controller:"activity_notification/notifications", action:"open", target_type:"users"}
|
35
|
+
#
|
36
|
+
# When you use devise for authentication and you want make notification target assciated with devise,
|
37
|
+
# you can creat this inside your routes:
|
38
|
+
#
|
39
|
+
# notify_to :users, with_devise: true
|
40
|
+
#
|
41
|
+
# This with_devise option creates the needed routes assciated with devise authentication:
|
42
|
+
#
|
43
|
+
# # Notification with devise routes
|
44
|
+
# user_notifications GET /users/:user_id/notifications(.:format)
|
45
|
+
# {controller:"activity_notification/notifications_with_devise", action:"index", devise_type:"users", target_type:"users"}
|
46
|
+
# user_notification GET /users/:user_id/notifications/:id(.:format)
|
47
|
+
# {controller:"activity_notification/notifications_with_devise", action:"show", devise_type:"users", target_type:"users"}
|
48
|
+
# user_notification DELETE /users/:user_id/notifications/:id(.:format)
|
49
|
+
# {controller:"activity_notification/notifications_with_devise", action:"destroy", devise_type:"users", target_type:"users"}
|
50
|
+
# open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
|
51
|
+
# {controller:"activity_notification/notifications_with_devise", action:"open_all", devise_type:"users", target_type:"users"}
|
52
|
+
# move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
|
53
|
+
# {controller:"activity_notification/notifications_with_devise", action:"move", devise_type:"users", target_type:"users"}
|
54
|
+
# open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
|
55
|
+
# {controller:"activity_notification/notifications_with_devise", action:"open", devise_type:"users", target_type:"users"}
|
56
|
+
#
|
57
|
+
# ==== Options
|
58
|
+
#TODO add document for options
|
59
|
+
#
|
60
|
+
def notify_to(*resources)
|
61
|
+
options = resources.extract_options!
|
62
|
+
|
63
|
+
#TODO check resources if it includes target module
|
64
|
+
|
65
|
+
if (with_devise = options.delete(:with_devise)).present?
|
66
|
+
options[:controller] ||= "activity_notification/notifications_with_devise"
|
67
|
+
options[:as] ||= "notifications"
|
68
|
+
#TODO check device configuration in model
|
69
|
+
devise_defaults = { devise_type: with_devise.to_s }
|
70
|
+
else
|
71
|
+
options[:controller] ||= "activity_notification/notifications"
|
72
|
+
end
|
73
|
+
options[:except] ||= []
|
74
|
+
options[:except].concat( [:new, :create, :edit, :update] )
|
75
|
+
|
76
|
+
#TODO other options
|
77
|
+
# :as, :path_prefix, :path_names ...
|
78
|
+
|
79
|
+
resources.each do |resource|
|
80
|
+
self.resources resource, only: :none do
|
81
|
+
options[:defaults] = (devise_defaults || {}).merge({ target_type: resource.to_s })
|
82
|
+
self.resources :notifications, options do
|
83
|
+
collection do
|
84
|
+
post :open_all unless ignore_path?(:open_all, options)
|
85
|
+
end
|
86
|
+
member do
|
87
|
+
get :move unless ignore_path?(:move, options)
|
88
|
+
post :open unless ignore_path?(:open, options)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def ignore_path?(action, options)
|
99
|
+
return true if options[:except].present? and options[:except].include?(action)
|
100
|
+
return true if options[:only].present? and not options[:only].include?(action)
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
# Provides logic for rendering notifications.
|
3
|
+
# Handles both i18n strings support and smart partials rendering (different templates per notification key).
|
4
|
+
# Deeply uses PublicActivity as reference
|
5
|
+
module Renderable
|
6
|
+
# Virtual attribute returning text description of the notification
|
7
|
+
# using the notification's key to translate using i18n.
|
8
|
+
def text(params = {})
|
9
|
+
k = key.split('.')
|
10
|
+
k.unshift('notification') if k.first != 'notification'
|
11
|
+
if params.has_key?(:target)
|
12
|
+
k.insert(1, params[:target])
|
13
|
+
else
|
14
|
+
k.insert(1, target.to_resource_name)
|
15
|
+
end
|
16
|
+
k = k.join('.')
|
17
|
+
|
18
|
+
I18n.t(k, parameters.merge(params) || {})
|
19
|
+
end
|
20
|
+
|
21
|
+
# Renders notification from views.
|
22
|
+
#
|
23
|
+
# @param [ActionView::Base] context
|
24
|
+
# @return [nil] nil
|
25
|
+
#
|
26
|
+
# The preferred way of rendering notifications is
|
27
|
+
# to provide a template specifying how the rendering should be happening.
|
28
|
+
# However, you can choose using _I18n_ based approach when developing
|
29
|
+
# an application that supports plenty of languages.
|
30
|
+
#
|
31
|
+
# If partial view exists that matches the "key" attribute
|
32
|
+
# renders that partial with local variables set to contain both
|
33
|
+
# Activity and activity_parameters (hash with indifferent access).
|
34
|
+
#
|
35
|
+
# If the partial view does not exist and you wish to fallback to rendering
|
36
|
+
# through the I18n translation, you can do so by passing in a :fallback
|
37
|
+
# parameter whose value equals :text.
|
38
|
+
#
|
39
|
+
# If you do not want to define a partial view, and instead want to have
|
40
|
+
# all missing views fallback to a default, you can define the :fallback
|
41
|
+
# value equal to the partial you wish to use when the partial defined
|
42
|
+
# by the notification key does not exist.
|
43
|
+
#
|
44
|
+
# @example Render a list of all @target's notifications of from a view (erb)
|
45
|
+
# <ul>
|
46
|
+
# <% @target.notifications.each do |notification| %>
|
47
|
+
# <li><%= render_notification(notification) %></li>
|
48
|
+
# <% end %>
|
49
|
+
# </ul>
|
50
|
+
#
|
51
|
+
# @example Fallback to the I18n text translation if the view is missing
|
52
|
+
# <ul>
|
53
|
+
# <% @target.notifications.each do |notification| %>
|
54
|
+
# <li><%= render_notification(notification, fallback: :text) %></li>
|
55
|
+
# <% end %>
|
56
|
+
# </ul>
|
57
|
+
#
|
58
|
+
# @example Fallback to a default view if the view for the current notification key is missing.
|
59
|
+
# The string is the partial name you wish to use.
|
60
|
+
# <ul>
|
61
|
+
# <% @target.notifications.each do |notification| %>
|
62
|
+
# <li><%= render_notification(notification, fallback: 'default') %></li>
|
63
|
+
# <% end %>
|
64
|
+
# </ul>
|
65
|
+
#
|
66
|
+
# # Layouts
|
67
|
+
#TODO
|
68
|
+
#
|
69
|
+
# # Creating a template
|
70
|
+
#
|
71
|
+
# To use templates for formatting how the notification should render,
|
72
|
+
# create a template based on target type and notification key, for example:
|
73
|
+
#
|
74
|
+
# Given a target type users and key _notification.article.create_, create directory tree
|
75
|
+
# _app/views/activity_notifications/users/article/_ and create the _create_ partial there
|
76
|
+
#
|
77
|
+
# Note that if a key consists of more than three parts splitted by commas, your
|
78
|
+
# directory structure will have to be deeper, for example:
|
79
|
+
# notification.article.comments.destroy => app/views/activity_notifications/users/articles/comments/_destroy.html.erb
|
80
|
+
#
|
81
|
+
# ## Custom Directory
|
82
|
+
#TODO
|
83
|
+
#
|
84
|
+
# ## Variables in templates
|
85
|
+
#TODO
|
86
|
+
def render(context, params = {})
|
87
|
+
params[:i18n] and return context.render text: self.text(params)
|
88
|
+
|
89
|
+
partial = partial_path(*params.values_at(:partial, :partial_root, :target))
|
90
|
+
layout = layout_path(*params.values_at(:layout, :layout_root))
|
91
|
+
locals = prepare_locals(params)
|
92
|
+
|
93
|
+
begin
|
94
|
+
context.render params.merge(partial: partial, layout: layout, locals: locals)
|
95
|
+
rescue ActionView::MissingTemplate => e
|
96
|
+
if params[:fallback] == :text
|
97
|
+
context.render text: self.text(params)
|
98
|
+
elsif params[:fallback].present?
|
99
|
+
partial = partial_path(*params.values_at(:fallback, :partial_root, :target))
|
100
|
+
context.render params.merge(partial: partial, layout: layout, locals: locals)
|
101
|
+
else
|
102
|
+
raise e
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def partial_path(path = nil, root = nil, target = nil)
|
108
|
+
controller = ActivityNotification.get_controller if ActivityNotification.respond_to?(:get_controller)
|
109
|
+
root ||= "activity_notification/notifications/#{target}" if target.present?
|
110
|
+
root ||= controller.target_view_path if controller.present? and controller.respond_to?(:target_view_path)
|
111
|
+
root ||= 'activity_notification/notifications/default'
|
112
|
+
path ||= self.key.gsub('.', '/')
|
113
|
+
select_path(path, root)
|
114
|
+
end
|
115
|
+
|
116
|
+
def layout_path(path = nil, root = nil)
|
117
|
+
path.nil? and return
|
118
|
+
root ||= 'layouts'
|
119
|
+
select_path(path, root)
|
120
|
+
end
|
121
|
+
|
122
|
+
def prepare_locals(params)
|
123
|
+
locals = params.delete(:locals) || {}
|
124
|
+
|
125
|
+
prepared_parameters = prepare_parameters(params)
|
126
|
+
locals.merge\
|
127
|
+
notification: self,
|
128
|
+
parameters: prepared_parameters
|
129
|
+
end
|
130
|
+
|
131
|
+
def prepare_parameters(params)
|
132
|
+
@prepared_params ||= self.parameters.with_indifferent_access.merge(params)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def select_path(path, root)
|
138
|
+
[root, path].map(&:to_s).join('/')
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
module ActsAsNotifiable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class_methods do
|
6
|
+
# Adds required callbacks for creating and updating
|
7
|
+
# notifiable models.
|
8
|
+
#
|
9
|
+
# == Parameters:
|
10
|
+
# [:targets]
|
11
|
+
#TODO
|
12
|
+
def acts_as_notifiable(target_type, opts = {})
|
13
|
+
options = opts.clone
|
14
|
+
assign_globals target_type, options
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def available_options
|
19
|
+
[:targets, :group, :notifier, :parameters, :email_allowed, :notifiable_path].freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def assign_globals(target_type, options)
|
23
|
+
[:targets, :group, :parameters, :email_allowed].each do |key|
|
24
|
+
if options[key]
|
25
|
+
self.send("_notification_#{key}".to_sym).store(target_type.to_sym, options.delete(key))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
[:notifier, :notifiable_path].each do |key|
|
29
|
+
if options[key]
|
30
|
+
self.send("_#{key}".to_sym).store(target_type.to_sym, options.delete(key))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|