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
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'ActivityNotification'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
Bundler::GemHelper.install_tasks
|
19
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "activity_notification/version"
|
5
|
+
|
6
|
+
# Describe your gem and declare its dependencies:
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "activity_notification"
|
9
|
+
s.version = ActivityNotification::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Shota Yamazaki"]
|
12
|
+
s.email = ["shota.yamazaki.8@gmail.com"]
|
13
|
+
s.homepage = "https://github.com/simukappu/activity_notification"
|
14
|
+
s.summary = "Integrated user activity notifications for Rails"
|
15
|
+
s.description = "Integrated user activity notifications for Rails. Provides functions to configure multiple notification targets and make activity notifications with notifiable models, like adding comments, responding etc."
|
16
|
+
s.license = "MIT"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.required_ruby_version = '>= 2.1.0'
|
22
|
+
|
23
|
+
s.add_dependency 'rails', '~> 4.2'
|
24
|
+
#s.add_dependency 'railties', '>= 3.0.0'
|
25
|
+
s.add_dependency 'i18n', '>= 0.5.0'
|
26
|
+
s.add_dependency 'activerecord', '>= 3.0'
|
27
|
+
|
28
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.11'
|
29
|
+
s.add_development_dependency "rspec-rails", '~> 3.5.1'
|
30
|
+
s.add_development_dependency "factory_girl_rails", '~> 4.7.0'
|
31
|
+
s.add_development_dependency 'simplecov', '~> 0.12.0'
|
32
|
+
s.add_development_dependency "devise", '~> 4.2.0'
|
33
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
class NotificationsController < ActivityNotification.config.parent_controller.constantize
|
3
|
+
include ActivityNotification::StoreController
|
4
|
+
include ActivityNotification::PolymorphicHelpers
|
5
|
+
prepend_before_action :set_target
|
6
|
+
before_action :set_notification, except: [:index, :open_all]
|
7
|
+
before_action :set_view_prefixes, except: [:move]
|
8
|
+
|
9
|
+
DEFAULT_VIEW_DIRECTORY = "default"
|
10
|
+
|
11
|
+
# GET /:target_type/:target_id/notifcations
|
12
|
+
def index
|
13
|
+
@notifications = load_notification_index(params[:filter], params[:limit]) if params[:reload].to_s.to_boolean(true)
|
14
|
+
respond_to do |format|
|
15
|
+
format.html # index.html.erb
|
16
|
+
format.json { render json: @notifications.to_json(include: [:target, :notifiable, :group]) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# POST /:target_type/:target_id/notifcations/open_all
|
21
|
+
def open_all
|
22
|
+
@target.open_all_notifications
|
23
|
+
@notifications = load_notification_index(params[:filter], params[:limit]) if params[:reload].to_s.to_boolean(true)
|
24
|
+
return_back_or_ajax(params[:filter], params[:limit])
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET /:target_type/:target_id/notifcations/:id
|
28
|
+
def show
|
29
|
+
end
|
30
|
+
|
31
|
+
# DELETE /:target_type/:target_id/notifcations/:id
|
32
|
+
def destroy
|
33
|
+
@notification.destroy
|
34
|
+
@notifications = load_notification_index(params[:filter], params[:limit]) if params[:reload].to_s.to_boolean(true)
|
35
|
+
return_back_or_ajax(params[:filter], params[:limit])
|
36
|
+
end
|
37
|
+
|
38
|
+
# POST /:target_type/:target_id/notifcations/:id/open
|
39
|
+
def open
|
40
|
+
@notification.open!
|
41
|
+
@notifications = load_notification_index(params[:filter], params[:limit]) if params[:reload].to_s.to_boolean(true)
|
42
|
+
params[:move].to_s.to_boolean(false) ?
|
43
|
+
move :
|
44
|
+
return_back_or_ajax(params[:filter], params[:limit])
|
45
|
+
end
|
46
|
+
|
47
|
+
# GET /:target_type/:target_id/notifcations/:id/move
|
48
|
+
def move
|
49
|
+
@notification.open! if params[:open].to_s.to_boolean(false)
|
50
|
+
redirect_to @notification.notifiale_path
|
51
|
+
end
|
52
|
+
|
53
|
+
# No action routing
|
54
|
+
# This method is called from target_view_path method
|
55
|
+
# This method can be overriden
|
56
|
+
def controller_path
|
57
|
+
"activity_notification/notifications"
|
58
|
+
end
|
59
|
+
|
60
|
+
# No action routing
|
61
|
+
# This method needs to be public since it is called from view helper
|
62
|
+
def target_view_path
|
63
|
+
target_type = @target.to_resources_name
|
64
|
+
view_path = [controller_path, target_type].join('/')
|
65
|
+
lookup_context.exists?(action_name, view_path) ?
|
66
|
+
view_path :
|
67
|
+
[controller_path, DEFAULT_VIEW_DIRECTORY].join('/')
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def set_target
|
73
|
+
if (target_type = params[:target_type]).present?
|
74
|
+
target_class = target_type.to_model_class
|
75
|
+
@target = params[:target_id].present? ?
|
76
|
+
target_class.find_by_id!(params[:target_id]) :
|
77
|
+
target_class.find_by_id!(params["#{target_type.to_resource_name}_id"])
|
78
|
+
else
|
79
|
+
render text: "400 Bad Request: Missing parameter", status: 400
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_notification
|
84
|
+
@notification = Notification.find_by_id!(params[:id])
|
85
|
+
if @target.present? and @notification.target != @target
|
86
|
+
render text: "403 Forbidden: Wrong target", status: 403
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def load_notification_index(filter, limit)
|
91
|
+
limit = nil unless limit.to_i > 0
|
92
|
+
case filter
|
93
|
+
when 'opened'
|
94
|
+
@target.opened_notification_index_with_attributes(limit)
|
95
|
+
when 'unopened'
|
96
|
+
@target.unopened_notification_index_with_attributes(limit)
|
97
|
+
else
|
98
|
+
@target.notification_index_with_attributes(limit)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def set_view_prefixes
|
103
|
+
lookup_context.prefixes.prepend(target_view_path)
|
104
|
+
end
|
105
|
+
|
106
|
+
def return_back_or_ajax(filter, limit)
|
107
|
+
respond_to do |format|
|
108
|
+
if request.xhr?
|
109
|
+
format.js
|
110
|
+
elsif request.referer
|
111
|
+
redirect_to :back, filter: filter, limit: limit and return
|
112
|
+
else
|
113
|
+
redirect_to action: :index, filter: filter, limit: limit and return
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
class NotificationsWithDeviseController < NotificationsController
|
3
|
+
prepend_before_action :authenticate_devise_resource!
|
4
|
+
before_action :authenticate_target!
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def authenticate_devise_resource!
|
9
|
+
authenticate_method_name = "authenticate_#{params[:devise_type].to_resource_name}!"
|
10
|
+
if respond_to?(authenticate_method_name)
|
11
|
+
send(authenticate_method_name)
|
12
|
+
else
|
13
|
+
render text: "403 Forbidden: Unauthenticated", status: 403
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def authenticate_target!
|
18
|
+
current_resource_method_name = "current_#{params[:devise_type].to_resource_name}"
|
19
|
+
if respond_to?(current_resource_method_name)
|
20
|
+
unless @target.authenticate_with_devise?(send(current_resource_method_name))
|
21
|
+
render text: "403 Forbidden: Unauthorized target", status: 403
|
22
|
+
end
|
23
|
+
else
|
24
|
+
render text: "403 Forbidden: Unauthenticated", status: 403
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
if defined?(ActionMailer)
|
2
|
+
class ActivityNotification::Mailer < ActivityNotification.config.parent_mailer.constantize
|
3
|
+
include ActivityNotification::Mailers::Helpers
|
4
|
+
|
5
|
+
def send_notification_email(notification)
|
6
|
+
if notification.target.notification_email_allowed?(notification.notifiable, notification.key) and
|
7
|
+
notification.notifiable.notification_email_allowed?(notification.target, notification.key)
|
8
|
+
notification_mail(notification)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<li>
|
2
|
+
<div>
|
3
|
+
<%= notification.notifier.present? ? notification.notifier.printable_name : 'Someone' %>
|
4
|
+
<% if notification.group_member_exists? %>
|
5
|
+
<%= " and other #{notification.group_member_count} people" %>
|
6
|
+
<% end %>
|
7
|
+
notified you of <%= notification.notifiable.printable_name %>
|
8
|
+
<%= "in #{notification.group.printable_name}" if notification.group.present? %>
|
9
|
+
</div>
|
10
|
+
<div>
|
11
|
+
<%= notification.opened? ? "Opened" : "Unopened" %>
|
12
|
+
</div>
|
13
|
+
<div>
|
14
|
+
<%= link_to "Move", move_notification_path_for(notification) %>
|
15
|
+
</div>
|
16
|
+
<% if notification.unopened? %>
|
17
|
+
<div>
|
18
|
+
<%= link_to "Open and move (GET)", move_notification_path_for(notification, open: true) %>
|
19
|
+
</div>
|
20
|
+
<div>
|
21
|
+
<%= link_to "Open and move (POST)", open_notification_path_for(notification, move: true), method: :post %>
|
22
|
+
</div>
|
23
|
+
<div>
|
24
|
+
<%= link_to "Open", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post %>
|
25
|
+
</div>
|
26
|
+
<div>
|
27
|
+
<%= link_to "Open (Ajax)", open_notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :post, remote: true %>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
30
|
+
<div>
|
31
|
+
<%= link_to "Destroy", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete %>
|
32
|
+
</div>
|
33
|
+
<div>
|
34
|
+
<%= link_to "Destroy (Ajax)", notification_path_for(notification, filter: params[:filter], limit: params[:limit]), method: :delete, remote: true %>
|
35
|
+
</div>
|
36
|
+
</li>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div>
|
2
|
+
<%= link_to open_all_notifications_path_for(@target), method: :post, remote: true do %>
|
3
|
+
<div id="notification_count"><%= @target.unopened_notification_count %></div>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<div id="notification_index">
|
7
|
+
<%= yield :notification_index %>
|
8
|
+
</div>
|
9
|
+
</div>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Notifications for <%= @target.printable_name %></h1>
|
2
|
+
<div id="notification_count"><%= @target.unopened_notification_count %></div>
|
3
|
+
|
4
|
+
<div>
|
5
|
+
<%= link_to "Open all", open_all_notifications_path_for(@target), method: :post %>
|
6
|
+
</div>
|
7
|
+
<div>
|
8
|
+
<%= link_to "Open all (ajax)", open_all_notifications_path_for(@target), method: :post, remote: true %>
|
9
|
+
</div>
|
10
|
+
<ul>
|
11
|
+
<div id="notifications">
|
12
|
+
<%= render_notification(@notifications, fallback: :default) %>
|
13
|
+
<%#= render_notification(@notifications, fallback: :text) %>
|
14
|
+
</div>
|
15
|
+
</ul>
|
16
|
+
|
17
|
+
<%#= render_notifications_of @target, fallback: :default, index_content: :with_attributes %>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'active_support'
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module ActivityNotification
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
autoload :Notification, 'activity_notification/models/notification'
|
10
|
+
autoload :Target, 'activity_notification/models/target'
|
11
|
+
autoload :Notifiable, 'activity_notification/models/notifiable'
|
12
|
+
autoload :ActsAsTarget, 'activity_notification/roles/acts_as_target'
|
13
|
+
autoload :ActsAsNotifiable, 'activity_notification/roles/acts_as_notifiable'
|
14
|
+
autoload :StoreController, 'activity_notification/controllers/store_controller'
|
15
|
+
autoload :NotificationApi, 'activity_notification/apis/notification_api'
|
16
|
+
autoload :Common
|
17
|
+
autoload :Config
|
18
|
+
autoload :Renderable
|
19
|
+
autoload :VERSION
|
20
|
+
|
21
|
+
|
22
|
+
module Mailers
|
23
|
+
autoload :Helpers, 'activity_notification/mailers/helpers'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns ActivityNotification's configuration object.
|
27
|
+
def self.config
|
28
|
+
@config ||= ActivityNotification::Config.new
|
29
|
+
end
|
30
|
+
|
31
|
+
# Lets you set global configuration options.
|
32
|
+
#
|
33
|
+
# All available options and their defaults are in the example below:
|
34
|
+
# @example Initializer for Rails
|
35
|
+
# ActivityNotification.configure do |config|
|
36
|
+
# config.enabled = false
|
37
|
+
# config.table_name = "notifications"
|
38
|
+
# ...
|
39
|
+
# end
|
40
|
+
def self.configure(&block)
|
41
|
+
yield(config) if block_given?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# Load ActivityNotification helpers
|
47
|
+
require 'activity_notification/helpers/polymorphic_helpers'
|
48
|
+
require 'activity_notification/helpers/view_helpers'
|
49
|
+
|
50
|
+
# Define Rails::Engine
|
51
|
+
require 'activity_notification/rails'
|
52
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module ActivityNotification
|
2
|
+
module NotificationApi
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# Define store_notification as private clas method
|
6
|
+
included do
|
7
|
+
private_class_method :store_notification
|
8
|
+
end
|
9
|
+
|
10
|
+
# For notification API
|
11
|
+
class_methods do
|
12
|
+
def notify(target_type, notifiable, options = {})
|
13
|
+
targets = notifiable.notification_targets(target_type, options[:key])
|
14
|
+
unless targets.blank?
|
15
|
+
notify_all(targets, notifiable, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def notify_all(targets, notifiable, options = {})
|
20
|
+
targets.each do |target|
|
21
|
+
notify_to(target, notifiable, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def notify_to(target, notifiable, options = {})
|
26
|
+
send_email = options.has_key?(:send_email) ? options[:send_email] : true
|
27
|
+
send_later = options.has_key?(:send_later) ? options[:send_later] : true
|
28
|
+
# Store notification
|
29
|
+
notification = store_notification(target, notifiable, options)
|
30
|
+
# Send notification email
|
31
|
+
notification.send_notification_email(send_later) if send_email
|
32
|
+
notification
|
33
|
+
end
|
34
|
+
|
35
|
+
# Open all notifications of specified target
|
36
|
+
def open_all_of(target, opened_at = nil)
|
37
|
+
opened_at = DateTime.now if opened_at.blank?
|
38
|
+
Notification.where(target: target, opened_at: nil).update_all(opened_at: opened_at)
|
39
|
+
end
|
40
|
+
|
41
|
+
#TODO description
|
42
|
+
# Call from controllers or views to avoid N+1
|
43
|
+
def group_member_exists?(notifications)
|
44
|
+
Notification.where(group_owner_id: notifications.pluck(:id)).exists?
|
45
|
+
end
|
46
|
+
|
47
|
+
def available_options
|
48
|
+
[:key, :group, :parameters, :notifier, :send_email, :send_later].freeze
|
49
|
+
end
|
50
|
+
|
51
|
+
# Private class methods
|
52
|
+
|
53
|
+
def store_notification(target, notifiable, options = {})
|
54
|
+
target_type = target.to_class_name
|
55
|
+
key = options[:key] || notifiable.default_notification_key
|
56
|
+
group = options[:group] || notifiable.notification_group(target_type, key)
|
57
|
+
notifier = options[:notifier] || notifiable.notifier(target_type, key)
|
58
|
+
parameters = options[:parameters] || {}
|
59
|
+
parameters.merge!(options.except(*available_options))
|
60
|
+
parameters.merge!(notifiable.notification_parameters(target_type, key))
|
61
|
+
|
62
|
+
# Bundle notification group by target, notifiable_type, group and key
|
63
|
+
# Defferent notifiable.id can be made in a same group
|
64
|
+
group_owner = Notification.where(target: target, notifiable_type: notifiable.to_class_name, key: key, group: group)
|
65
|
+
.where(group_owner_id: nil, opened_at: nil).earliest
|
66
|
+
if group.present? and group_owner.present?
|
67
|
+
create(target: target, notifiable: notifiable, key: key, group: group, group_owner: group_owner, parameters: parameters, notifier: notifier)
|
68
|
+
else
|
69
|
+
create(target: target, notifiable: notifiable, key: key, group: group, parameters: parameters, notifier: notifier)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Public instance methods
|
76
|
+
|
77
|
+
def send_notification_email(send_later = true)
|
78
|
+
if send_later
|
79
|
+
Mailer.send_notification_email(self).deliver_later
|
80
|
+
else
|
81
|
+
Mailer.send_notification_email(self).deliver_now
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def open!(opened_at = nil)
|
86
|
+
opened_at = DateTime.now if opened_at.blank?
|
87
|
+
update(opened_at: opened_at)
|
88
|
+
group_members.update_all(opened_at: opened_at)
|
89
|
+
end
|
90
|
+
|
91
|
+
def unopened?
|
92
|
+
!opened?
|
93
|
+
end
|
94
|
+
|
95
|
+
def opened?
|
96
|
+
opened_at.present?
|
97
|
+
end
|
98
|
+
|
99
|
+
def group_owner?
|
100
|
+
group_owner_id.blank?
|
101
|
+
end
|
102
|
+
|
103
|
+
def group_member?
|
104
|
+
group_owner_id.present?
|
105
|
+
end
|
106
|
+
|
107
|
+
# Cache group-by query result to avoid N+1 call
|
108
|
+
def group_member_exists?(limit = ActivityNotification.config.opened_limit)
|
109
|
+
group_member_count(limit) > 0
|
110
|
+
end
|
111
|
+
|
112
|
+
# Cache group-by query result to avoid N+1 call
|
113
|
+
def group_member_count(limit = ActivityNotification.config.opened_limit)
|
114
|
+
notification = group_member? ? group_owner : self
|
115
|
+
notification.opened? ?
|
116
|
+
notification.opened_group_member_count(limit) :
|
117
|
+
notification.unopened_group_member_count
|
118
|
+
end
|
119
|
+
|
120
|
+
def notifiale_path
|
121
|
+
notifiable.notifiable_path(target_type)
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
# Protected instance methods
|
126
|
+
protected
|
127
|
+
|
128
|
+
def unopened_group_member_count
|
129
|
+
# Cache group-by query result to avoid N+1 call
|
130
|
+
unopened_group_member_counts = target.notifications
|
131
|
+
.unopened_index_group_members_only
|
132
|
+
.group(:group_owner_id)
|
133
|
+
.count
|
134
|
+
unopened_group_member_counts[id] || 0
|
135
|
+
end
|
136
|
+
|
137
|
+
def opened_group_member_count(limit = ActivityNotification.config.opened_limit)
|
138
|
+
# Cache group-by query result to avoid N+1 call
|
139
|
+
opened_group_member_counts = target.notifications
|
140
|
+
.opened_index_group_members_only(limit)
|
141
|
+
.group(:group_owner_id)
|
142
|
+
.count
|
143
|
+
opened_group_member_counts[id] || 0
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|