activity_notification 0.0.8

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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +56 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +28 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +174 -0
  8. data/MIT-LICENSE +20 -0
  9. data/README.md +437 -0
  10. data/Rakefile +19 -0
  11. data/activity_notification.gemspec +33 -0
  12. data/app/controllers/activity_notification/notifications_controller.rb +119 -0
  13. data/app/controllers/activity_notification/notifications_with_devise_controller.rb +29 -0
  14. data/app/mailers/activity_notification/mailer.rb +13 -0
  15. data/app/views/activity_notification/mailer/default/default.html.erb +7 -0
  16. data/app/views/activity_notification/notifications/default/_default.html.erb +36 -0
  17. data/app/views/activity_notification/notifications/default/_index.html.erb +9 -0
  18. data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -0
  19. data/app/views/activity_notification/notifications/default/index.html.erb +17 -0
  20. data/app/views/activity_notification/notifications/default/open.js.erb +2 -0
  21. data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -0
  22. data/app/views/activity_notification/notifications/default/show.html.erb +2 -0
  23. data/config/locales/en.yml +8 -0
  24. data/lib/activity_notification.rb +52 -0
  25. data/lib/activity_notification/apis/notification_api.rb +147 -0
  26. data/lib/activity_notification/common.rb +86 -0
  27. data/lib/activity_notification/config.rb +23 -0
  28. data/lib/activity_notification/controllers/store_controller.rb +30 -0
  29. data/lib/activity_notification/helpers/polymorphic_helpers.rb +32 -0
  30. data/lib/activity_notification/helpers/view_helpers.rb +108 -0
  31. data/lib/activity_notification/mailers/helpers.rb +97 -0
  32. data/lib/activity_notification/models/notifiable.rb +136 -0
  33. data/lib/activity_notification/models/notification.rb +50 -0
  34. data/lib/activity_notification/models/notifier.rb +11 -0
  35. data/lib/activity_notification/models/target.rb +104 -0
  36. data/lib/activity_notification/rails.rb +6 -0
  37. data/lib/activity_notification/rails/routes.rb +105 -0
  38. data/lib/activity_notification/renderable.rb +142 -0
  39. data/lib/activity_notification/roles/acts_as_notifiable.rb +37 -0
  40. data/lib/activity_notification/roles/acts_as_target.rb +30 -0
  41. data/lib/activity_notification/version.rb +3 -0
  42. data/lib/generators/activity_notification/controllers_generator.rb +44 -0
  43. data/lib/generators/activity_notification/install_generator.rb +45 -0
  44. data/lib/generators/activity_notification/migration/migration_generator.rb +17 -0
  45. data/lib/generators/activity_notification/notification/notification_generator.rb +17 -0
  46. data/lib/generators/activity_notification/views_generator.rb +44 -0
  47. data/lib/generators/templates/README +53 -0
  48. data/lib/generators/templates/active_record/migration.rb +18 -0
  49. data/lib/generators/templates/activity_notification.rb +18 -0
  50. data/lib/generators/templates/controllers/README +13 -0
  51. data/lib/generators/templates/controllers/notifications_controller.rb +66 -0
  52. data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +74 -0
  53. data/lib/generators/templates/notification/notification.rb +3 -0
  54. data/lib/tasks/activity_notification_tasks.rake +4 -0
  55. data/spec/concerns/notification_api_spec.rb +531 -0
  56. data/spec/factories/articles.rb +5 -0
  57. data/spec/factories/comments.rb +6 -0
  58. data/spec/factories/notifications.rb +7 -0
  59. data/spec/factories/users.rb +5 -0
  60. data/spec/models/notification_spec.rb +259 -0
  61. data/spec/rails_app/Rakefile +6 -0
  62. data/spec/rails_app/app/controllers/application_controller.rb +5 -0
  63. data/spec/rails_app/app/controllers/concerns/.keep +0 -0
  64. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  65. data/spec/rails_app/app/mailers/.keep +0 -0
  66. data/spec/rails_app/app/models/.keep +0 -0
  67. data/spec/rails_app/app/models/article.rb +12 -0
  68. data/spec/rails_app/app/models/comment.rb +18 -0
  69. data/spec/rails_app/app/models/concerns/.keep +0 -0
  70. data/spec/rails_app/app/models/user.rb +8 -0
  71. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  72. data/spec/rails_app/bin/bundle +3 -0
  73. data/spec/rails_app/bin/rails +4 -0
  74. data/spec/rails_app/bin/rake +4 -0
  75. data/spec/rails_app/bin/setup +29 -0
  76. data/spec/rails_app/config.ru +4 -0
  77. data/spec/rails_app/config/application.rb +20 -0
  78. data/spec/rails_app/config/boot.rb +5 -0
  79. data/spec/rails_app/config/database.yml +25 -0
  80. data/spec/rails_app/config/environment.rb +12 -0
  81. data/spec/rails_app/config/environments/development.rb +44 -0
  82. data/spec/rails_app/config/environments/production.rb +79 -0
  83. data/spec/rails_app/config/environments/test.rb +45 -0
  84. data/spec/rails_app/config/initializers/activity_notification.rb +18 -0
  85. data/spec/rails_app/config/initializers/assets.rb +11 -0
  86. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  87. data/spec/rails_app/config/initializers/cookies_serializer.rb +3 -0
  88. data/spec/rails_app/config/initializers/devise.rb +274 -0
  89. data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  90. data/spec/rails_app/config/initializers/inflections.rb +16 -0
  91. data/spec/rails_app/config/initializers/mime_types.rb +4 -0
  92. data/spec/rails_app/config/initializers/session_store.rb +3 -0
  93. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  94. data/spec/rails_app/config/routes.rb +5 -0
  95. data/spec/rails_app/config/secrets.yml +22 -0
  96. data/spec/rails_app/db/migrate/20160715050420_create_notifications.rb +18 -0
  97. data/spec/rails_app/db/migrate/20160715050433_create_test_tables.rb +36 -0
  98. data/spec/rails_app/db/schema.rb +73 -0
  99. data/spec/rails_app/public/404.html +67 -0
  100. data/spec/rails_app/public/422.html +67 -0
  101. data/spec/rails_app/public/500.html +66 -0
  102. data/spec/rails_app/public/favicon.ico +0 -0
  103. data/spec/spec_helper.rb +34 -0
  104. metadata +309 -0
@@ -0,0 +1,86 @@
1
+ module ActivityNotification
2
+
3
+ # Used to transform value from metadata to data.
4
+ # Accepts Symbols, which it will send against context.
5
+ # Accepts Procs, which it will execute with controller and context.
6
+ # Both Symbols and Procs will be passed arguments of this method.
7
+ def self.resolve_value(context, thing, *args)
8
+ case thing
9
+ when Symbol
10
+ begin
11
+ context.__send__(thing, *args)
12
+ rescue ArgumentError => e
13
+ context.__send__(thing)
14
+ end
15
+ when Proc
16
+ begin
17
+ thing.call(ActivityNotification.get_controller, context, *args)
18
+ rescue ArgumentError => e
19
+ thing.call(ActivityNotification.get_controller, context)
20
+ end
21
+ when Hash
22
+ thing.dup.tap do |hash|
23
+ hash.each do |key, value|
24
+ hash[key] = ActivityNotification.resolve_value(context, value, *args)
25
+ end
26
+ end
27
+ else
28
+ thing
29
+ end
30
+ end
31
+
32
+ module Common
33
+
34
+ # Used to transform value from metadata to data which belongs model instance.
35
+ # Accepts Symbols, which it will send against this instance.
36
+ # Accepts Procs, which it will execute with this instance.
37
+ # Both Symbols and Procs will be passed arguments of this method.
38
+ def resolve_value(thing, *args)
39
+ case thing
40
+ when Symbol
41
+ begin
42
+ __send__(thing, *args)
43
+ rescue ArgumentError => e
44
+ __send__(thing)
45
+ end
46
+ when Proc
47
+ begin
48
+ thing.call(self, *args)
49
+ rescue ArgumentError => e
50
+ thing.call(self)
51
+ end
52
+ when Hash
53
+ thing.dup.tap do |hash|
54
+ hash.each do |key, value|
55
+ hash[key] = resolve_value(value, *args)
56
+ end
57
+ end
58
+ else
59
+ thing
60
+ end
61
+ end
62
+
63
+ def to_class_name
64
+ self.class.name
65
+ end
66
+
67
+ def to_resource_name
68
+ self.class.name.demodulize.singularize.underscore
69
+ end
70
+
71
+ def to_resources_name
72
+ self.class.name.demodulize.pluralize.underscore
73
+ end
74
+
75
+ #TODO Is it the best solution?
76
+ def printable_type
77
+ "#{self.class.name.demodulize.humanize}"
78
+ end
79
+
80
+ #TODO Is it the best solution?
81
+ def printable_name
82
+ "#{self.printable_type} (#{id})"
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,23 @@
1
+ module ActivityNotification
2
+ # Class used to initialize configuration object.
3
+ class Config
4
+ attr_accessor :enabled,
5
+ :table_name,
6
+ :mailer_sender,
7
+ :mailer,
8
+ :parent_mailer,
9
+ :parent_controller,
10
+ :opened_limit
11
+
12
+ def initialize
13
+ @enabled = true
14
+ @table_name = "notifications"
15
+ @mailer_sender = nil
16
+ @mailer = "ActivityNotification::Mailer"
17
+ @parent_mailer = 'ActionMailer::Base'
18
+ @parent_controller = 'ApplicationController'
19
+ @opened_limit = 10
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ module ActivityNotification
2
+ class << self
3
+ # Setter for remembering controller instance
4
+ def set_controller(controller)
5
+ Thread.current[:activity_notification_controller] = controller
6
+ end
7
+
8
+ # Getter for accessing the controller instance
9
+ def get_controller
10
+ Thread.current[:activity_notification_controller]
11
+ end
12
+ end
13
+
14
+ # Module included in controllers to allow p_a access to controller instance
15
+ module StoreController
16
+ extend ActiveSupport::Concern
17
+
18
+ included do
19
+ around_action :store_controller_for_activity_notification if respond_to?(:around_action)
20
+ around_filter :store_controller_for_activity_notification unless respond_to?(:around_action)
21
+ end
22
+
23
+ def store_controller_for_activity_notification
24
+ ActivityNotification.set_controller(self)
25
+ yield
26
+ ensure
27
+ ActivityNotification.set_controller(nil)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ module ActivityNotification
2
+ module PolymorphicHelpers
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class ::String
7
+ def to_model_name
8
+ singularize.camelize
9
+ end
10
+
11
+ def to_model_class
12
+ to_model_name.classify.constantize
13
+ end
14
+
15
+ def to_resource_name
16
+ singularize.underscore
17
+ end
18
+
19
+ def to_resources_name
20
+ pluralize.underscore
21
+ end
22
+
23
+ def to_boolean(default = nil)
24
+ return true if ['true', '1', 'yes', 'on', 't'].include? self
25
+ return false if ['false', '0', 'no', 'off', 'f'].include? self
26
+ return default
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,108 @@
1
+ # Provides a shortcut from views to the rendering method.
2
+ module ActivityNotification
3
+ # Module extending ActionView::Base and adding `render_notification` helper.
4
+ module ViewHelpers
5
+ # View helper for rendering an notification, calls {ActivityNotification::Notification#render} internally.
6
+ def render_notification notifications, options = {}
7
+ if notifications.is_a? ActivityNotification::Notification
8
+ notifications.render self, options
9
+ elsif notifications.respond_to?(:map)
10
+ return nil if notifications.empty?
11
+ notifications.map {|notification| notification.render self, options.dup }.join.html_safe
12
+ end
13
+ end
14
+ alias_method :render_notifications, :render_notification
15
+
16
+ # View helper for rendering embedded partial template of target's notifications
17
+ def render_notification_of target, options = {}
18
+ return unless target.is_a? ActivityNotification::Target
19
+
20
+ partial_path = options.delete(:partial) || "index"
21
+ partial_root = options[:partial_root] ||
22
+ "activity_notification/notifications/#{target.to_resources_name}"
23
+ partial = select_path(partial_path, partial_root)
24
+ layout = options[:layout].present? ?
25
+ select_path(options.delete(:layout), (options[:layout_root] || "layouts")) :
26
+ nil
27
+ locals = (options[:locals] || {}).merge(target: target)
28
+
29
+ # Prepare content for notifications index
30
+ notification_options = options.merge\
31
+ target: target.to_resources_name,
32
+ partial: options[:notification_partial],
33
+ layout: options[:notification_layout]
34
+ case options[:index_content]
35
+ when :simple
36
+ notification_index = target.notification_index
37
+ when :none
38
+ else
39
+ notification_index = target.notification_index_with_attributes
40
+ end
41
+
42
+ if notification_index.present?
43
+ content_for :notification_index do
44
+ begin
45
+ render_notifications notification_index, notification_options
46
+ rescue ActionView::MissingTemplate => e
47
+ notification_options.delete(:target)
48
+ render_notifications notification_index, notification_options
49
+ end
50
+ end
51
+ end
52
+
53
+ # Render partial index
54
+ begin
55
+ render options.merge(partial: partial, layout: layout, locals: locals)
56
+ rescue ActionView::MissingTemplate => e
57
+ partial_root = "activity_notification/notifications/default"
58
+ partial = select_path(partial_path, partial_root)
59
+ render options.merge(partial: partial, layout: layout, locals: locals)
60
+ end
61
+ end
62
+ alias_method :render_notifications_of, :render_notification_of
63
+
64
+ # Url helper methods
65
+ #TODO Is there any other better solution?
66
+ #TODO Must handle devise namespace
67
+ def notification_path_for(notification, params = {})
68
+ send("#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
69
+ end
70
+
71
+ def move_notification_path_for(notification, params = {})
72
+ send("move_#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
73
+ end
74
+
75
+ def open_notification_path_for(notification, params = {})
76
+ send("open_#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
77
+ end
78
+
79
+ def open_all_notifications_path_for(target, params = {})
80
+ send("open_all_#{target.to_resource_name}_notifications_path", target, params)
81
+ end
82
+
83
+ def notification_url_for(notification, params = {})
84
+ send("#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
85
+ end
86
+
87
+ def move_notification_url_for(notification, params = {})
88
+ send("move_#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
89
+ end
90
+
91
+ def open_notification_url_for(notification, params = {})
92
+ send("open_#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
93
+ end
94
+
95
+ def open_all_notifications_url_for(target, params = {})
96
+ send("open_all_#{target.to_resource_name}_notifications_url", target, params)
97
+ end
98
+
99
+ private
100
+
101
+ def select_path(path, root)
102
+ [root, path].map(&:to_s).join('/')
103
+ end
104
+
105
+ end
106
+
107
+ ActionView::Base.class_eval { include ViewHelpers }
108
+ end
@@ -0,0 +1,97 @@
1
+ module ActivityNotification
2
+ module Mailers
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ protected
7
+
8
+ # Configure default email options
9
+ def notification_mail(notification, options = {})
10
+ initialize_from_notification(notification)
11
+ headers = headers_for(notification.key, options)
12
+ begin
13
+ mail headers
14
+ rescue ActionView::MissingTemplate => e
15
+ mail headers.merge(template_name: 'default')
16
+ end
17
+ end
18
+
19
+ def initialize_from_notification(notification)
20
+ @notification, @target, @notifiable = notification, notification.target, notification.notifiable
21
+ end
22
+
23
+ def headers_for(key, options)
24
+ if @notifiable.respond_to?(:overriding_notification_email_key) and
25
+ @notifiable.overriding_notification_email_key(@target, key).present?
26
+ key = @notifiable.overriding_notification_email_key(@target, key)
27
+ end
28
+ headers = {
29
+ subject: subject_for(key),
30
+ to: mailer_to(@target),
31
+ from: mailer_sender(@target.to_resource_name),
32
+ reply_to: mailer_reply_to(@target.to_resource_name),
33
+ template_path: template_paths,
34
+ template_name: template_name(key)
35
+ }.merge(options)
36
+
37
+ @email = headers[:to]
38
+ headers
39
+ end
40
+
41
+ def mailer_to(target)
42
+ target.mailer_to
43
+ end
44
+
45
+ def mailer_reply_to(target_type)
46
+ mailer_sender(target_type, :reply_to)
47
+ end
48
+
49
+ def mailer_from(target_type)
50
+ mailer_sender(target_type, :from)
51
+ end
52
+
53
+ def mailer_sender(target_type, sender = :from)
54
+ default_sender = default_params[sender]
55
+ if default_sender.present?
56
+ default_sender.respond_to?(:to_proc) ? instance_eval(&default_sender) : default_sender
57
+ elsif ActivityNotification.config.mailer_sender.is_a?(Proc)
58
+ ActivityNotification.config.mailer_sender.call(target_type)
59
+ else
60
+ ActivityNotification.config.mailer_sender
61
+ end
62
+ end
63
+
64
+ def template_paths
65
+ paths = ['activity_notification/mailer/default']
66
+ paths.unshift("activity_notification/mailer/#{@target.to_resources_name}") if @target.present?
67
+ paths
68
+ end
69
+
70
+ def template_name(key)
71
+ key.gsub('.', '/')
72
+ end
73
+
74
+
75
+ # Set up a subject doing an I18n lookup.
76
+ # At first, it attempts to set a subject based on the current mapping:
77
+ # en:
78
+ # notification:
79
+ # {target}:
80
+ # {key}:
81
+ # mail_subject: '...'
82
+ #
83
+ # If one does not exist, it fallbacks to default:
84
+ # Notification for #{notification.printable_type}
85
+ #
86
+ def subject_for(key)
87
+ k = key.split('.')
88
+ k.unshift('notification') if k.first != 'notification'
89
+ k.insert(1, @target.to_resource_name)
90
+ k = k.join('.')
91
+ I18n.t(:mail_subject, scope: k,
92
+ default: ["Notification of #{@notifiable.printable_type}"])
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,136 @@
1
+ module ActivityNotification
2
+ module Notifiable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Common
7
+ include ActsAsNotifiable
8
+ include ActionDispatch::Routing::PolymorphicRoutes
9
+ include Rails.application.routes.url_helpers
10
+ class_attribute :_notification_targets,
11
+ :_notification_group,
12
+ :_notifier,
13
+ :_notification_parameters,
14
+ :_notification_email_allowed,
15
+ :_notifiable_path
16
+ set_notifiable_class_defaults
17
+ end
18
+
19
+ def default_url_options
20
+ Rails.application.routes.default_url_options
21
+ end
22
+
23
+ class_methods do
24
+ def set_notifiable_class_defaults
25
+ self._notification_targets = {}
26
+ self._notification_group = {}
27
+ self._notifier = {}
28
+ self._notification_parameters = {}
29
+ self._notification_email_allowed = {}
30
+ self._notifiable_path = {}
31
+ end
32
+ end
33
+
34
+ # Methods to be overriden
35
+
36
+ def notification_targets(target_type, key)
37
+ plural_target_type = target_type.to_s.underscore.pluralize
38
+ plural_target_type_sym = plural_target_type.to_sym
39
+ target_typed_method_name = "notification_#{plural_target_type}"
40
+ if respond_to?(target_typed_method_name)
41
+ send(target_typed_method_name, key)
42
+ else
43
+ if _notification_targets[plural_target_type_sym]
44
+ resolve_value(_notification_targets[plural_target_type_sym], key)
45
+ else
46
+ raise NotImplementedError, "You have to implement #{self.class}##{target_typed_method_name} or set :targets in acts_as_notifiable"
47
+ end
48
+ end
49
+ end
50
+
51
+ def notification_group(target_type, key)
52
+ plural_target_type = target_type.to_s.underscore.pluralize
53
+ plural_target_type_sym = plural_target_type.to_sym
54
+ target_typed_method_name = "notification_group_for_#{plural_target_type}"
55
+ if respond_to?(target_typed_method_name)
56
+ send(target_typed_method_name, key)
57
+ else
58
+ resolve_value(_notification_group[plural_target_type_sym])
59
+ end
60
+ end
61
+
62
+ def notification_parameters(target_type, key)
63
+ plural_target_type = target_type.to_s.underscore.pluralize
64
+ plural_target_type_sym = plural_target_type.to_sym
65
+ target_typed_method_name = "notification_parameters_for_#{plural_target_type}"
66
+ if respond_to?(target_typed_method_name)
67
+ send(target_typed_method_name, key)
68
+ else
69
+ resolve_value(_notification_parameters[plural_target_type_sym], key) || {}
70
+ end
71
+ end
72
+
73
+ def notifier(target_type, key)
74
+ plural_target_type = target_type.to_s.underscore.pluralize
75
+ plural_target_type_sym = plural_target_type.to_sym
76
+ target_typed_method_name = "notifier_for_#{plural_target_type}"
77
+ if respond_to?(target_typed_method_name)
78
+ send(target_typed_method_name, key)
79
+ else
80
+ resolve_value(_notifier[plural_target_type_sym])
81
+ end
82
+ end
83
+
84
+ def notification_email_allowed?(target, key)
85
+ plural_target_type_sym = target.to_resources_name.to_sym
86
+ if _notification_email_allowed[plural_target_type_sym]
87
+ resolve_value(_notification_email_allowed[plural_target_type_sym], target, key)
88
+ else
89
+ true
90
+ end
91
+ end
92
+
93
+ def notifiable_path(target_type, key = nil)
94
+ plural_target_type = target_type.to_s.underscore.pluralize
95
+ plural_target_type_sym = plural_target_type.to_sym
96
+ target_typed_method_name = "notifiable_path_for_#{plural_target_type}"
97
+ if respond_to?(target_typed_method_name)
98
+ send(target_typed_method_name, key)
99
+ elsif _notifiable_path[plural_target_type_sym]
100
+ resolve_value(_notifiable_path[plural_target_type_sym])
101
+ else
102
+ begin
103
+ polymorphic_path(self)
104
+ rescue NoMethodError => e
105
+ raise NotImplementedError, "You have to implement #{self.class}##{__method__}, set :notifiable_path in acts_as_notifiable or set polymorphic_path routing for #{self.class}"
106
+ rescue ActionController::UrlGenerationError => e
107
+ raise NotImplementedError, "You have to implement #{self.class}##{__method__}, set :notifiable_path in acts_as_notifiable or set polymorphic_path routing for #{self.class}"
108
+ end
109
+ end
110
+ end
111
+
112
+ # TODO docs
113
+ # overriding_notification_render_key(target, key)
114
+
115
+ # TODO docs
116
+ # overriding_notification_email_key(target, key)
117
+
118
+ # Wrapper methods of SimpleNotify class methods
119
+
120
+ def notify(target_type, options = {})
121
+ Notification.notify(target_type, self, options)
122
+ end
123
+
124
+ def notify_to(target, options = {})
125
+ Notification.notify_to(target, self, options)
126
+ end
127
+
128
+ def notify_all(targets, options = {})
129
+ Notification.notify_all(targets, self, options)
130
+ end
131
+
132
+ def default_notification_key
133
+ "#{to_resource_name}.default"
134
+ end
135
+ end
136
+ end