noticed 1.0.0 → 1.2.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a68b0a9d002890caff4346a36eac937e9efe9c759fa656586d7c23984f974593
4
- data.tar.gz: 22f5537095dcb8fb2f0a09f558c7b277d9840611bc29fc263544cc6344edc7f8
3
+ metadata.gz: e5b998072ed72c9844842d8610a9ffcea75cf16f958296aa3d53e1a3c050b6db
4
+ data.tar.gz: 589f43985b3dc7740977730d10917d0b111706fe56c4daafedbacc08e7f2ce84
5
5
  SHA512:
6
- metadata.gz: a0a1fc6372bd1eb3f128eaecc8b05bbd37ee6a540f30ef05fafcd8b593dc01e00c53d4ecb135c93184c6d264940707b4513f0b33eeca4d57c52ee87b80870ca8
7
- data.tar.gz: ee98827a78024e374126ad2f0f5fb9210320808fb244c4171ab543d27c2c875d6a05ca6045b4b3b2dab2fff17c9ec9ae514d3a7f98105d5b74642d0c6150bcec
6
+ metadata.gz: 9f4a336ed688008a5abc3f91099a5ecc4128361beffd216e0e2e0bc0a1670286e607577d2f4ce13f1e36c2fb2fff3d93fbab9a10914d0321a2d1e0c2449ea715
7
+ data.tar.gz: b4a67b79dcf34892dcd11b56ad83e2c393a2da49c3eb38e3e911411164b4150ec27a836e53d1d7875ea40141276a398878e8c23304c326287299b26bafebacba
data/README.md CHANGED
@@ -1,74 +1,183 @@
1
- # Noticed - Notifications for your Ruby on Rails app.
1
+ <p align="center">
2
+ <h1>Noticed</h1>
3
+ </p>
2
4
 
3
- [![Build Status](https://github.com/excid3/noticed/workflows/Tests/badge.svg)](https://github.com/excid3/noticed/actions)
5
+ ### 🎉 Notifications for your Ruby on Rails app.
6
+
7
+ [![Build Status](https://github.com/excid3/noticed/workflows/Tests/badge.svg)](https://github.com/excid3/noticed/actions) [![Gem Version](https://badge.fury.io/rb/noticed.svg)](https://badge.fury.io/rb/noticed)
4
8
 
5
9
  Currently, we support these notification delivery methods out of the box:
6
10
 
7
11
  * Database
8
12
  * Email
9
- * Websocket (realtime)
13
+ * ActionCable channels
14
+ * Slack
15
+ * Microsoft Teams
10
16
  * Twilio (SMS)
11
17
  * Vonage / Nexmo (SMS)
12
18
 
13
19
  And you can easily add new notification types for any other delivery methods.
14
20
 
15
- ## Installation
16
- Add this line to your application's Gemfile:
21
+ ## 🎬 Screencast
22
+
23
+ <div style="width:50%">
24
+ <a href="https://www.youtube.com/watch?v=Scffi4otlFc"><img src="https://i.imgur.com/UvVKWwD.png" title="How to add Notifications to Rails with Noticed" /></a>
25
+ </div>
26
+
27
+ [Watch Screencast](https://www.youtube.com/watch?v=Scffi4otlFc)
28
+
29
+ ## 🚀 Installation
30
+ Run the following command to add Noticed to your Gemfile
17
31
 
18
32
  ```ruby
19
- gem 'noticed'
33
+ bundle add "noticed"
20
34
  ```
21
35
 
22
- And then execute:
23
- ```bash
24
- $ bundle
36
+ To save notifications to your database, use the following command to generate a Notification model.
37
+
38
+ ```ruby
39
+ rails generate noticed:model
25
40
  ```
26
41
 
27
- Or install it yourself as:
28
- ```bash
29
- $ gem install noticed
42
+ This will generate a Notification model and instructions for associating User models with the notifications table.
43
+
44
+ ## 📝 Usage
45
+
46
+ To generate a notification object, simply run:
47
+
48
+ `rails generate noticed:notification CommentNotification`
49
+
50
+ #### Sending Notifications
51
+
52
+ To send a notification to a user:
53
+
54
+ ```ruby
55
+ # Instantiate a new notification
56
+ notification = CommentNotification.with(comment: @comment)
57
+
58
+ # Deliver notification in background job
59
+ notification.deliver_later(@comment.post.author)
60
+
61
+ # Deliver notification immediately
62
+ notification.deliver(@comment.post.author)
63
+
64
+ # Deliver notification to multiple recipients
65
+ notification.deliver_later(User.all)
30
66
  ```
31
67
 
32
- ## Usage
68
+ This will instantiate a new notification with the `comment` stored in the notification's params.
69
+
70
+ Each delivery method is able to transform this metadata that's best for the format. For example, the database may simply store the comment so it can be linked when rendering in the navbar. The websocket mechanism may transform this into a browser notification or insert it into the navbar.
71
+
72
+ #### Notification Objects
73
+
74
+ Notifications inherit from `Noticed::Base`. This provides all their functionality and allows them to be delivered.
33
75
 
34
- You can define a Notification as a class that inherits from Noticed::Base. To add delivery methods, simply `include` the module for the delivery methods you would like to use.
76
+ To add delivery methods, simply `include` the module for the delivery methods you would like to use.
35
77
 
36
78
  ```ruby
37
79
  class CommentNotification < Noticed::Base
38
80
  deliver_by :database
39
81
  deliver_by :action_cable
40
- deliver_by :email, if: :email_notifications?
82
+ deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
83
+
84
+ # I18n helpers
85
+ def message
86
+ t(".message")
87
+ end
88
+
89
+ # URL helpers are accessible in notifications
90
+ # Don't forget to set your default_url_options so Rails knows how to generate urls
91
+ def url
92
+ post_path(params[:post])
93
+ end
41
94
 
42
95
  def email_notifications?
43
96
  !!recipient.preferences[:email]
44
97
  end
98
+
99
+ after_deliver do
100
+ # Anything you want
101
+ end
45
102
  end
46
103
  ```
47
104
 
48
- To send a notification to a user:
105
+ **Shared Options**
106
+
107
+ * `if: :method_name` - Calls `method_name`and cancels delivery method if `false` is returned
108
+ * `unless: :method_name` - Calls `method_name`and cancels delivery method if `true` is returned
109
+ * `delay: ActiveSupport::Duration` - Delays the delivery for the given duration of time
110
+
111
+ ##### Helper Methods
112
+
113
+ You can define helper methods inside your Notification object to make it easier to render.
114
+
115
+ ##### URL Helpers
116
+
117
+ Rails url helpers are included in notification classes by default so you have full access to them just like you would in your controllers and views.
118
+
119
+ Don't forget, you'll need to configure `default_url_options` in order for Rails to know what host and port to use when generating URLs.
49
120
 
50
121
  ```ruby
51
- notification = CommentNotification.with(comment: @comment.to_gid)
122
+ Rails.application.routes.default_url_options[:host] = 'localhost:3000'
123
+ ```
52
124
 
53
- # Deliver notification in background job
54
- notification.deliver_later(@comment.post.author)
125
+ **Callbacks**
55
126
 
56
- # Deliver notification immediately
57
- notification.deliver(@comment.post.author)
127
+ Like ActiveRecord, notifications have several different types of callbacks.
128
+
129
+ ```ruby
130
+ class CommentNotification < Noticed::Base
131
+ deliver_by :database
132
+ deliver_by :email, mailer: 'CommentMailer'
133
+
134
+ # Callbacks for the entire delivery
135
+ before_deliver :whatever
136
+ around_deliver :whatever
137
+ after_deliver :whatever
138
+
139
+ # Callbacks for each delivery method
140
+ before_database :whatever
141
+ around_database :whatever
142
+ after_database :whatever
143
+
144
+ before_email :whatever
145
+ around_email :whatever
146
+ after_email :whatever
147
+ end
58
148
  ```
59
149
 
60
- This will instantiate a new notification with the `comment` global ID stored in the metadata.
150
+ When using `deliver_later` callbacks will be run around queuing the delivery method jobs (not inside the jobs as they actually execute).
61
151
 
62
- Each delivery method is able to transfrom this metadata that's best for the format. For example, the database may simply store the comment so it can be linked when rendering in the navbar. The websocket mechanism may transform this into a browser notification or insert it into the navbar.
152
+ Defining custom delivery methods allows you to add callbacks that run inside the background job as each individual delivery is executed. See the Custom Delivery Methods section for more information.
63
153
 
64
- **Shared Options**
154
+ ##### Translations
65
155
 
66
- * `if: :method_name` - Calls `method_name`and cancels delivery method if `false` is returned
67
- * `unless: :method_name` - Calls `method_name`and cancels delivery method if `true` is returned
156
+ We've added `translate` and `t` helpers like Rails has to provide an easy way of scoping translations. If the key starts with a period, it will automatically scope the key under `notifications` and the underscored name of the notification class it is used in.
157
+
158
+ For example:
159
+
160
+ `t(".message")` looks up `en.notifications.new_comment.message`
161
+
162
+ ##### User Preferences
163
+
164
+ You can use the `if:` and `unless: ` options on your delivery methods to check the user's preferences and skip processing if they have disabled that type of notification.
165
+
166
+ For example:
167
+
168
+ ```ruby
169
+ class CommentNotification < Noticed::Base
170
+ deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
171
+
172
+ def email_notifications?
173
+ recipient.email_notifications?
174
+ end
175
+ end
176
+ ```
68
177
 
69
- ## Delivery Methods
178
+ ## 🚛 Delivery Methods
70
179
 
71
- The delivery methods are designed to be overriden so that you can customi1ze the notification for each medium.
180
+ The delivery methods are designed to be modular so you can customize the way each type gets delivered.
72
181
 
73
182
  For example, emails will require a subject, body, and email address while an SMS requires a phone number and simple message. You can define the formats for each of these in your Notification and the delivery method will handle the processing of it.
74
183
 
@@ -78,7 +187,17 @@ Writes notification to the database.
78
187
 
79
188
  `deliver_by :database`
80
189
 
81
- **Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods.
190
+ **Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods. For that same reason, the delivery can't be delayed (via the `delay` option) or an error will be raised.
191
+
192
+ ##### Options
193
+
194
+ * `association` - *Optional*
195
+
196
+ The name of the database association to use. Defaults to `:notifications`
197
+
198
+ * `format: :format_for_database` - *Optional*
199
+
200
+ Use a custom method to define the attributes saved to the database
82
201
 
83
202
  ### Email
84
203
 
@@ -86,7 +205,7 @@ Sends an email notification. Emails will always be sent with `deliver_later`
86
205
 
87
206
  `deliver_by :email, mailer: "UserMailer"`
88
207
 
89
- **Options**
208
+ ##### Options
90
209
 
91
210
  * `mailer` - **Required**
92
211
 
@@ -96,13 +215,17 @@ Sends an email notification. Emails will always be sent with `deliver_later`
96
215
 
97
216
  Used to customize the method on the mailer that is called
98
217
 
218
+ * `format: :format_for_email` - *Optional*
219
+
220
+ Use a custom method to define the params sent to the mailer. `recipient` will be merged into the params.
221
+
99
222
  ### ActionCable
100
223
 
101
224
  Sends a notification to the browser via websockets (ActionCable channel by default).
102
225
 
103
226
  `deliver_by :action_cable`
104
227
 
105
- **Options**
228
+ ##### Options
106
229
 
107
230
  * `format: :format_for_action_cable` - *Optional*
108
231
 
@@ -120,7 +243,7 @@ Sends a Slack notification via webhook.
120
243
 
121
244
  `deliver_by :slack`
122
245
 
123
- **Options**
246
+ ##### Options
124
247
 
125
248
  * `format: :format_for_slack` - *Optional*
126
249
 
@@ -132,17 +255,53 @@ Sends a Slack notification via webhook.
132
255
 
133
256
  Defaults to `Rails.application.credentials.slack[:notification_url]`
134
257
 
258
+ ### Microsoft Teams
259
+
260
+ Sends a Teams notification via webhook.
261
+
262
+ `deliver_by :microsoft_teams`
263
+
264
+ #### Options
265
+
266
+ * `format: :format_for_teams` - *Optional*
267
+
268
+ Use a custom method to define the payload sent to slack. Method should return a Hash.
269
+ Documentation for posting via Webhooks available at: https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
270
+
271
+ ```ruby
272
+ {
273
+ title: "This is the title for the card",
274
+ text: "This is the body text for the card",
275
+ sections: [{activityTitle: "Section Title", activityText: "Section Text"}],
276
+ "potentialAction": [{
277
+ "@type": "OpenUri",
278
+ name: "Button Text",
279
+ targets: [{
280
+ os: "default",
281
+ uri: "https://example.com/foo/action"
282
+ }]
283
+ }]
284
+
285
+ }
286
+ ```
287
+
288
+ * `url: :url_for_teams_channel`: - *Optional*
289
+
290
+ Use a custom method to retrieve the MS Teams Webhook URL. Method should return a string.
291
+
292
+ Defaults to `Rails.application.credentials.microsoft_teams[:notification_url]`
293
+
135
294
  ### Twilio SMS
136
295
 
137
296
  Sends an SMS notification via Twilio.
138
297
 
139
298
  `deliver_by :twilio`
140
299
 
141
- **Options**
300
+ ##### Options
142
301
 
143
302
  * `credentials: :get_twilio_credentials` - *Optional*
144
303
 
145
- Use a custom method to retrieve the credentials for Twilio. Method should return a Hash with `:account_sid`, `:auth_token` and `:phone_ number` keys.
304
+ Use a custom method to retrieve the credentials for Twilio. Method should return a Hash with `:account_sid`, `:auth_token` and `:phone_number` keys.
146
305
 
147
306
  Defaults to `Rails.application.credentials.twilio[:account_sid]` and `Rails.application.credentials.twilio[:auth_token]`
148
307
 
@@ -168,11 +327,11 @@ Sends an SMS notification via Twilio.
168
327
 
169
328
  ### Vonage SMS
170
329
 
171
- Sends an SMS notification vai Vonage / Nexmo.
330
+ Sends an SMS notification via Vonage / Nexmo.
172
331
 
173
332
  `deliver_by :vonage`
174
333
 
175
- **Options:**
334
+ ##### Options
176
335
 
177
336
  * `credentials: :get_credentials` - *Optional*
178
337
 
@@ -195,65 +354,210 @@ Sends an SMS notification vai Vonage / Nexmo.
195
354
  }
196
355
  ```
197
356
 
198
- ### User Preferences
357
+ ### 🚚 Custom Delivery Methods
199
358
 
200
- Each delivery method implements a `deliver_with_#{name}` method that receives the recipient as the first argument. You can override this method to check the user's preferences and skip processing if they have disabled that type of notification.
359
+ To generate a custom delivery method, simply run
201
360
 
202
- For example:
361
+ `rails generate noticed:delivery_method Discord`
203
362
 
204
- ```ruby
205
- class CommentNotification < Noticed::Base
206
- deliver_by :email, if: :email_notifications?
363
+ This will generate a new `DeliveryMethods::Discord` class inside the `app/notifications/delivery_methods` folder, which can be used to deliver notifications to Discord.
207
364
 
208
- def email_notifications?
209
- recipient.email_notifications?
365
+ ```ruby
366
+ class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
367
+ def deliver
368
+ # Logic for sending a Discord notification
210
369
  end
211
370
  end
212
371
  ```
213
372
 
214
- ### Custom Delivery Methods
215
-
216
- You can define a custom delivery method easily by adding a `deliver_by` line with a unique name and class option. The class will be instantiated and should inherit from `Noticed::DeliveryMethods::Base`.
373
+ You can use the custom delivery method thus created by adding a `deliver_by` line with a unique name and `class` option in your notification class.
217
374
 
218
375
  ```ruby
219
376
  class MyNotification < Noticed::Base
220
- deliver_by :discord, class: "DiscordNotification"
377
+ deliver_by :discord, class: "DeliveryMethods::Discord"
221
378
  end
222
379
  ```
223
380
 
381
+ Delivery methods have access to the following methods and attributes:
382
+
383
+ * `notification` - The instance of the Notification. You can call methods on the notification to let the user easily override formatting and other functionality of the delivery method.
384
+ * `options` - Any configuration options on the `deliver_by` line.
385
+ * `recipient` - The object who should receive the notification. This is typically a User, Account, or other ActiveRecord model.
386
+ * `params` - The params passed into the notification. This is details about the event that happened. For example, a user commenting on a post would have params of `{ user: User.first }`
387
+
388
+ #### Validating options passed to Custom Delivery methods
389
+
390
+ The presence of the delivery method options is automatically validated if using the `option(s)` method.
391
+
392
+ If you want to validate that the passed options contain valid values, or to add any custom validations, override the `self.validate!(delivery_method_options)` method from the `Noticed::DeliveryMethods::Base` class.
393
+
224
394
  ```ruby
225
- class DiscordNotification < Noticed::DeliveryMethods::Base
395
+ class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
396
+ option :username # Requires the username option to be passed
397
+
226
398
  def deliver
227
399
  # Logic for sending a Discord notification
228
400
  end
401
+
402
+ def self.validate!(delivery_method_options)
403
+ super # Don't forget to call super, otherwise option presence won't be validated
404
+
405
+   # Custom validations
406
+ if delivery_method_options[:username].blank?
407
+ raise Noticed::ValidationError, 'the `username` option must be present'
408
+ end
409
+ end
410
+ end
411
+
412
+ class CommentNotification < Noticed::Base
413
+ deliver_by :discord, class: 'DeliveryMethods::Discord'
229
414
  end
230
415
  ```
231
416
 
232
- Delivery methods have access to the following methods and attributes:
417
+ Now it will raise an error because a required argument is missing.
233
418
 
234
- * `notification` - The instance of the Notification. You can call methods on the notification to let the user easily override formatting and other functionality of the delivery method.
235
- * `options` - Any configuration options on the `deliver_by` line.
236
- * `recipient` - The object who should receive the notification. This is typically a User, Account, or other ActiveRecord model.
237
- * `params` - The params passed into the notification. This is details about the event that happened. For example, a user commenting on a post would have params of `{ user: User.first }`
419
+ To fix the error, the argument has to be passed correctly. For example:
420
+
421
+ ```ruby
422
+ class CommentNotification < Noticed::Base
423
+ deliver_by :discord, class: 'DeliveryMethods::Discord', username: User.admin.username
424
+ end
425
+ ```
426
+
427
+ #### Callbacks
428
+
429
+ Callbacks for delivery methods wrap the *actual* delivery of the notification. You can use `before_deliver`, `around_deliver` and `after_deliver` in your custom delivery methods.
430
+
431
+ ```ruby
432
+ class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
433
+ after_deliver do
434
+ # Do whatever you want
435
+ end
436
+ end
437
+ ```
238
438
 
239
439
  #### Limitations
240
440
 
241
441
  Rails 6.1+ can serialize Class and Module objects as arguments to ActiveJob. The following syntax should work for Rails 6.1+:
242
442
 
243
443
  ```ruby
244
- deliver_by DiscordNotification
444
+ deliver_by DeliveryMethods::Discord
245
445
  ```
246
446
 
247
- For Rails 6.0 and earlier, you must pass strings of the class names in the `deliver_by` options.
447
+ For Rails 6.0, you must pass strings of the class names in the `deliver_by` options.
248
448
 
249
449
  ```ruby
250
- deliver_by :discord, class: "DiscordNotification"
450
+ deliver_by :discord, class: "DeliveryMethods::Discord"
251
451
  ```
252
452
 
253
453
  We recommend the Rails 6.0 compatible options to prevent confusion.
254
454
 
255
- ## Contributing
256
- Contribution directions go here.
455
+ ### 📦 Database Model
456
+
457
+ The Notification database model includes several helpful features to make working with database notifications easier.
458
+
459
+ #### Class methods
460
+
461
+ Sorting notifications by newest first:
462
+
463
+ ```ruby
464
+ user.notifications.newest_first
465
+ ```
466
+
467
+ Query for read or unread notifications:
468
+
469
+ ```ruby
470
+ user.notifications.read
471
+ user.notifications.unread
472
+ ```
473
+
474
+
475
+ Marking all notifications as read or unread:
476
+
477
+ ```ruby
478
+ user.notifications.mark_as_read!
479
+ user.notifications.mark_as_unread!
480
+ ```
481
+
482
+ #### Instance methods
483
+
484
+ Convert back into a Noticed notification object:
485
+
486
+ ```ruby
487
+ @notification.to_notification
488
+ ```
489
+
490
+ Mark notification as read / unread:
491
+
492
+ ```ruby
493
+ @notification.mark_as_read!
494
+ @notification.mark_as_unread!
495
+ ```
496
+
497
+ Check if read / unread:
498
+
499
+ ```ruby
500
+ @notification.read?
501
+ @notification.unread?
502
+ ```
503
+
504
+ #### Associating Notifications
505
+
506
+ Adding notification associations to your models makes querying and deleting notifications easy and is a pretty critical feature of most applications.
507
+
508
+ For example, in most cases, you'll want to delete notifications for records that are destroyed.
509
+
510
+ ##### JSON Columns
511
+
512
+ If you're using MySQL or Postgresql, the `params` column on the notifications table is in `json` or `jsonb` format and can be queried against directly.
513
+
514
+ For example, we can query the notifications and delete them on destroy like so:
515
+
516
+ ```ruby
517
+ class Post < ApplicationRecord
518
+ def notifications
519
+ # Exact match
520
+ @notifications ||= Notification.where(params: { post: self })
521
+
522
+ # Or Postgres syntax to query the post key in the JSON column
523
+ # @notifications ||= Notification.where("params->'post' = ?", Noticed::Coder.dump(self).to_json)
524
+ end
525
+
526
+ before_destroy :destroy_notifications
527
+
528
+ def destroy_notifications
529
+ notifications.destroy_all
530
+ end
531
+ end
532
+ ```
533
+
534
+ ##### Polymorphic Association
535
+
536
+ If your notification is only associated with one model or you're using a `text` column for your params column , then a polymorphic association is what you'll want to use.
537
+
538
+ 1. Add a polymorphic association to the Notification model. `rails g migration AddNotifiableToNotifications notifiable:belongs_to{polymorphic}`
539
+
540
+ 2. Add `has_many :notifications, as: :notifiable, dependent: :destroy` to each model
541
+
542
+ 3. Customize database `format: ` option to write the `notifiable` attribute(s) when saving the notification
543
+
544
+ ```ruby
545
+ class ExampleNotification < Noticed::Base
546
+ deliver_by :database, format: :format_for_database
547
+
548
+ def format_for_database
549
+ {
550
+ notifiable: params.delete(:post),
551
+ type: self.class.name,
552
+ params: params
553
+ }
554
+ end
555
+ end
556
+ ```
557
+
558
+ ## 🙏 Contributing
559
+
560
+ This project uses [Standard](https://github.com/testdouble/standard) for formatting Ruby code. Please make sure to run `standardrb` before submitting pull requests.
257
561
 
258
- ## License
562
+ ## 📝 License
259
563
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -18,6 +18,10 @@ require "bundler/gem_tasks"
18
18
 
19
19
  require "rake/testtask"
20
20
 
21
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
22
+ load "rails/tasks/engine.rake"
23
+ load "rails/tasks/statistics.rake"
24
+
21
25
  Rake::TestTask.new(:test) do |t|
22
26
  t.libs << "test"
23
27
  t.pattern = "test/**/*_test.rb"
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/named_base"
4
+
5
+ module Noticed
6
+ module Generators
7
+ class DeliveryMethodGenerator < Rails::Generators::NamedBase
8
+ include Rails::Generators::ResourceHelpers
9
+
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ desc "Generates a class for a custom delivery method with the given NAME."
13
+
14
+ def generate_notification
15
+ template "delivery_method.rb", "app/notifications/delivery_methods/#{singular_name}.rb"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/named_base"
4
+
5
+ module Noticed
6
+ module Generators
7
+ class ModelGenerator < Rails::Generators::NamedBase
8
+ include Rails::Generators::ResourceHelpers
9
+
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ desc "Generates a Notification model for storing notifications."
13
+
14
+ argument :name, type: :string, default: "Notification", banner: "Notification"
15
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
16
+
17
+ def generate_notification
18
+ generate :model, name, "recipient:references{polymorphic}", "type", params_column, "read_at:datetime:index", *attributes
19
+ end
20
+
21
+ def add_noticed_model
22
+ inject_into_class model_path, class_name, " include Noticed::Model\n"
23
+ end
24
+
25
+ def add_not_nullable
26
+ migration_path = Dir.glob(Rails.root.join("db/migrate/*")).max_by { |f| File.mtime(f) }
27
+
28
+ # Force is required because null: false already exists in the file and Thor isn't smart enough to tell the difference
29
+ insert_into_file migration_path, after: "t.string :type", force: true do
30
+ ", null: false"
31
+ end
32
+ end
33
+
34
+ def done
35
+ readme "README" if behavior == :invoke
36
+ end
37
+
38
+ private
39
+
40
+ def model_path
41
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
42
+ end
43
+
44
+ def params_column
45
+ case ActiveRecord::Base.configurations.configs_for(spec_name: "primary").config["adapter"]
46
+ when "mysql2"
47
+ "params:json"
48
+ when "postgresql"
49
+ "params:jsonb"
50
+ else
51
+ "params:text"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end