activity_notification 0.0.10 → 1.0.0

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -0
  3. data/Gemfile +6 -3
  4. data/Gemfile.lock +74 -58
  5. data/README.md +53 -26
  6. data/activity_notification.gemspec +2 -0
  7. data/app/controllers/activity_notification/notifications_controller.rb +4 -4
  8. data/app/mailers/activity_notification/mailer.rb +9 -3
  9. data/app/views/activity_notification/mailer/default/default.html.erb +9 -4
  10. data/app/views/activity_notification/mailer/default/default.text.erb +10 -0
  11. data/app/views/activity_notification/notifications/default/_default.html.erb +173 -34
  12. data/app/views/activity_notification/notifications/default/_index.html.erb +119 -11
  13. data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
  14. data/app/views/activity_notification/notifications/default/index.html.erb +25 -14
  15. data/app/views/activity_notification/notifications/default/open.js.erb +2 -2
  16. data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -2
  17. data/app/views/activity_notification/notifications/default/show.html.erb +1 -1
  18. data/gemfiles/Gemfile.rails-4.2 +0 -2
  19. data/gemfiles/Gemfile.rails-4.2.lock +3 -3
  20. data/gemfiles/Gemfile.rails-5.0 +1 -3
  21. data/lib/activity_notification.rb +10 -9
  22. data/lib/activity_notification/apis/notification_api.rb +108 -14
  23. data/lib/activity_notification/common.rb +11 -2
  24. data/lib/activity_notification/config.rb +13 -13
  25. data/lib/activity_notification/helpers/view_helpers.rb +26 -4
  26. data/lib/activity_notification/mailers/helpers.rb +8 -4
  27. data/lib/activity_notification/models.rb +4 -0
  28. data/lib/activity_notification/models/concerns/group.rb +32 -0
  29. data/lib/activity_notification/models/concerns/notifiable.rb +60 -32
  30. data/lib/activity_notification/models/concerns/notifier.rb +17 -1
  31. data/lib/activity_notification/models/concerns/target.rb +114 -55
  32. data/lib/activity_notification/models/notification.rb +26 -25
  33. data/lib/activity_notification/rails.rb +1 -0
  34. data/lib/activity_notification/renderable.rb +8 -3
  35. data/lib/activity_notification/roles/acts_as_common.rb +28 -0
  36. data/lib/activity_notification/roles/acts_as_group.rb +38 -0
  37. data/lib/activity_notification/roles/acts_as_notifiable.rb +56 -22
  38. data/lib/activity_notification/roles/acts_as_notifier.rb +25 -2
  39. data/lib/activity_notification/roles/acts_as_target.rb +27 -9
  40. data/lib/activity_notification/version.rb +1 -1
  41. data/lib/generators/templates/activity_notification.rb +1 -1
  42. data/spec/concerns/apis/notification_api_spec.rb +361 -2
  43. data/spec/concerns/common_spec.rb +36 -0
  44. data/spec/concerns/models/group_spec.rb +61 -0
  45. data/spec/concerns/models/notifiable_spec.rb +37 -0
  46. data/spec/concerns/models/notifier_spec.rb +48 -0
  47. data/spec/concerns/models/target_spec.rb +81 -31
  48. data/spec/factories/dummy/dummy_group.rb +4 -0
  49. data/spec/helpers/view_helpers_spec.rb +13 -0
  50. data/spec/mailers/mailer_spec.rb +8 -1
  51. data/spec/models/dummy/dummy_group_spec.rb +6 -0
  52. data/spec/rails_app/app/assets/stylesheets/application.css +15 -0
  53. data/spec/rails_app/app/assets/stylesheets/reset.css +85 -0
  54. data/spec/rails_app/app/assets/stylesheets/style.css +244 -0
  55. data/spec/rails_app/app/controllers/articles_controller.rb +1 -1
  56. data/spec/rails_app/app/models/admin.rb +2 -1
  57. data/spec/rails_app/app/models/article.rb +9 -2
  58. data/spec/rails_app/app/models/comment.rb +8 -2
  59. data/spec/rails_app/app/models/dummy/dummy_group.rb +4 -0
  60. data/spec/rails_app/app/models/user.rb +8 -3
  61. data/spec/rails_app/app/views/articles/_form.html.erb +14 -10
  62. data/spec/rails_app/app/views/articles/edit.html.erb +8 -6
  63. data/spec/rails_app/app/views/articles/index.html.erb +59 -67
  64. data/spec/rails_app/app/views/articles/new.html.erb +7 -5
  65. data/spec/rails_app/app/views/articles/show.html.erb +47 -36
  66. data/spec/rails_app/app/views/layouts/_header.html.erb +36 -9
  67. data/spec/rails_app/app/views/layouts/application.html.erb +8 -6
  68. data/spec/rails_app/config/environments/development.rb +9 -0
  69. data/spec/rails_app/config/initializers/activity_notification.rb +1 -1
  70. data/spec/rails_app/db/schema.rb +14 -20
  71. data/spec/rails_app/db/seeds.rb +5 -5
  72. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +13 -0
  73. data/spec/roles/acts_as_group_spec.rb +32 -0
  74. data/spec/roles/acts_as_notifiable_spec.rb +1 -1
  75. data/spec/roles/acts_as_notifier_spec.rb +15 -0
  76. data/spec/roles/acts_as_target_spec.rb +1 -1
  77. metadata +52 -2
@@ -29,7 +29,7 @@ describe ActivityNotification::Mailer do
29
29
 
30
30
  it "sends with default notification subject" do
31
31
  expect(ActivityNotification::Mailer.deliveries.last.subject)
32
- .to eq("Notification of Article")
32
+ .to eq("Notification of article")
33
33
  end
34
34
  end
35
35
 
@@ -76,6 +76,13 @@ describe ActivityNotification::Mailer do
76
76
  .to eq("New comment to your article")
77
77
  end
78
78
  end
79
+
80
+ context "when fallback option is :none and the template is missing" do
81
+ it "raise ActionView::MissingTemplate" do
82
+ expect { ActivityNotification::Mailer.send_notification_email(notification, fallback: :none).deliver_now }
83
+ .to raise_error(ActionView::MissingTemplate)
84
+ end
85
+ end
79
86
  end
80
87
 
81
88
  context "with deliver_later" do
@@ -0,0 +1,6 @@
1
+ describe Dummy::DummyGroup, type: :model do
2
+
3
+ it_behaves_like :group
4
+ it_behaves_like :common
5
+
6
+ end
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,85 @@
1
+ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video {
2
+ margin: 0;
3
+ padding: 0;
4
+ border: 0;
5
+ outline: 0;
6
+ font-size: 100%;
7
+ vertical-align: baseline;
8
+ background: transparent;
9
+ list-style: none;
10
+ font-weight: normal;
11
+ }
12
+
13
+ body {
14
+ line-height: 1;
15
+ }
16
+
17
+ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
18
+ display: block;
19
+ }
20
+
21
+ nav, ul {
22
+ list-style: none;
23
+ }
24
+
25
+ blockquote, q {
26
+ quotes: none;
27
+ }
28
+
29
+ blockquote:before, blockquote:after, q:before, q:after {
30
+ content: '';
31
+ content: none;
32
+ }
33
+
34
+ a {
35
+ margin: 0;
36
+ padding: 0;
37
+ font-size: 100%;
38
+ vertical-align: baseline;
39
+ background: transparent;
40
+ text-decoration: none;
41
+ }
42
+
43
+ a:focus {
44
+ outline: none;
45
+ }
46
+
47
+ ins {
48
+ background-color: #ff9;
49
+ color: #000;
50
+ text-decoration: none;
51
+ }
52
+
53
+ mark {
54
+ background-color: #ff9;
55
+ color: #000;
56
+ font-style: italic;
57
+ font-weight: bold;
58
+ }
59
+
60
+ del {
61
+ text-decoration: line-through;
62
+ }
63
+
64
+ abbr[title], dfn[title] {
65
+ border-bottom: 1px dotted;
66
+ cursor: help;
67
+ }
68
+
69
+ table {
70
+ border-collapse: collapse;
71
+ border-spacing: 0;
72
+ }
73
+
74
+ hr {
75
+ display: block;
76
+ height: 0;
77
+ border: 0;
78
+ border-top: 1px solid #ddd;
79
+ margin: 1em 0;
80
+ padding: 0;
81
+ }
82
+
83
+ input, select {
84
+ vertical-align: middle;
85
+ }
@@ -0,0 +1,244 @@
1
+ body {
2
+ font-family: 'Lucida Grande', Meiryo, sans-serif;
3
+ color: #4f4f4f;
4
+ font-weight: normal;
5
+ font-style: normal;
6
+ background-color: #fafafa;
7
+ }
8
+ a {
9
+ color: #4363ba;
10
+ }
11
+ a:hover {
12
+ color: #27a5eb;
13
+ }
14
+
15
+ /* notice */
16
+ .notice_wrapper {
17
+ width: 100%;
18
+ background-color: #fafafa;
19
+ border-bottom: 1px solid #e5e5e5;
20
+ }
21
+ .notice_wrapper .notice {
22
+ font-size: 14px;
23
+ padding: 14px 40px;
24
+ }
25
+
26
+ /* header */
27
+ header{
28
+ width: 100%;
29
+ border-bottom: 1px solid #e5e5e5;
30
+ background-color: #fff;
31
+ }
32
+ header .header_area {
33
+ padding: 20px 40px;
34
+ }
35
+ header .header_area:after{
36
+ content: "";
37
+ clear: both;
38
+ display: block;
39
+ }
40
+ header .header_area .header_root_wrapper{
41
+ float: left;
42
+ }
43
+ header .header_area .header_root_wrapper a{
44
+ font-size: 24px;
45
+ letter-spacing: 0.1em;
46
+ }
47
+ header .header_area .header_menu_wrapper,
48
+ header .header_area .header_notification_wrapper {
49
+ float: right;
50
+ }
51
+ header .header_area .header_menu_wrapper p,
52
+ header .header_area .header_notification_wrapper p {
53
+ font-size: 14px;
54
+ font-weight: bold;
55
+ height: 24px;
56
+ }
57
+ header .header_area .header_menu_wrapper p a,
58
+ header .header_area .header_notification_wrapper p a {
59
+ margin-left: 10px;
60
+ }
61
+
62
+ /* article */
63
+ article{
64
+ width: 1000px;
65
+ margin: 0 auto;
66
+ padding: 40px 40px;
67
+ }
68
+
69
+ section{
70
+ position: relative;
71
+ width: 600px;
72
+ border: 1px solid #e5e5e5;
73
+ background-color: #fff;
74
+
75
+ padding: 20px;
76
+ box-sizing: border-box;
77
+ margin-bottom: 30px;
78
+ }
79
+ section:last-of-type{
80
+ margin-bottom: 0;
81
+ }
82
+
83
+ .create_button_wrapper{
84
+ position: absolute;
85
+ right: 0;
86
+ top: 0;
87
+ padding: 20px;
88
+ margin-top: 10px;
89
+ }
90
+
91
+ h1 {
92
+ font-size: 24px;
93
+ letter-spacing: 0.1em;
94
+ margin-bottom: 10px;
95
+ }
96
+ .list_wrapper + h2{
97
+ margin-top: 20px;
98
+ }
99
+ h2 {
100
+ font-size: 20px;
101
+ letter-spacing: 0.1em;
102
+ line-height: 1.4;
103
+ margin-bottom: 10px;
104
+ }
105
+ p{
106
+ font-size: 16px;
107
+ line-height: 2.0;
108
+ }
109
+
110
+ /* list */
111
+ .list_wrapper {
112
+ padding: 15px 10px;
113
+ position: relative;
114
+ border-bottom: 1px solid #e5e5e5;
115
+ }
116
+ .list_wrapper:last-child {
117
+ border-bottom: none;
118
+ }
119
+ .list_wrapper:after{
120
+ content: "";
121
+ clear: both;
122
+ display: block;
123
+ }
124
+ .list_wrapper .list_image {
125
+ float: left;
126
+ width: 40px;
127
+ height: 40px;
128
+ background-position: center;
129
+ background-repeat: no-repeat;
130
+ background-size: cover;
131
+ background-color: #979797;
132
+ }
133
+ .list_wrapper .list_image.large {
134
+ width: 120px;
135
+ height: 90px;
136
+ }
137
+ .list_image.large + .list_description_wrapper {
138
+ width: calc(100% - 130px);
139
+ }
140
+ .list_wrapper .list_description_wrapper {
141
+ float: left;
142
+ width: calc(100% - 50px);
143
+ margin-top: 0;
144
+ margin-left: 10px;
145
+ }
146
+ .list_wrapper .list_description_wrapper .list_title {
147
+ font-size: 18px;
148
+ font-weight: bold;
149
+ line-height: 1.4;
150
+ }
151
+ .list_wrapper .list_description_wrapper .list_description {
152
+ color: #979797;
153
+ font-size: 14px;
154
+ line-height: 1.6;
155
+ }
156
+ .list_wrapper .list_description_wrapper .list_description span{
157
+ color: #4f4f4f;
158
+ font-weight: bold;
159
+ }
160
+ .list_wrapper .list_description_wrapper .list_button_wrapper{
161
+ margin-top: 16px;
162
+ text-align: right;
163
+ margin-bottom: 10px;
164
+ }
165
+
166
+ /* form */
167
+ .input_wrapper{
168
+ width: 100%;
169
+ background-color: #fff;
170
+ border: 1px solid #e5e5e5;
171
+ border-radius: 5px;
172
+ padding: 10px;
173
+ box-sizing: border-box;
174
+ cursor: text;
175
+ margin-bottom: 10px;
176
+ }
177
+ .input_wrapper input{
178
+ width: 100%;
179
+ font-size: 16px;
180
+ outline: 0;
181
+ border: none;
182
+ }
183
+ .textarea_wrapper{
184
+ width: 100%;
185
+ background-color: #fff;
186
+ border: 1px solid #e5e5e5;
187
+ border-radius: 5px;
188
+ padding: 10px;
189
+ box-sizing: border-box;
190
+ cursor: text;
191
+ }
192
+ .textarea_wrapper textarea{
193
+ width: 100%;
194
+ height: 100px;
195
+ font-size: 16px;
196
+ outline: 0;
197
+ border: none;
198
+ resize: none;
199
+ }
200
+ .submit_button_wrapper{
201
+ text-align: right;
202
+ margin-top: 10px;
203
+ }
204
+ .left_button_wrapper{
205
+ margin-top: 16px;
206
+ text-align: left;
207
+ margin-bottom: 10px;
208
+ }
209
+
210
+ /* button */
211
+ .gray_button{
212
+ color: #4f4f4f;
213
+ font-weight: bold;
214
+ font-size: 12px;
215
+ padding: 10px 14px;
216
+ margin-left: 10px;
217
+ border: 1px solid #e5e5e5;
218
+ background-color: #fafafa;
219
+ }
220
+ .gray_button:first-child {
221
+ margin-left: 0;
222
+ }
223
+ .gray_button:hover{
224
+ color: #4f4f4f;
225
+ border: 1px solid #e5e5e5;
226
+ background-color: #efefef;
227
+ }
228
+ .green_button{
229
+ color: #fff;
230
+ font-weight: bold;
231
+ font-size: 12px;
232
+ padding: 10px 14px;
233
+ margin-left: 10px;
234
+ border: 1px solid #59e58f;
235
+ background-color: #59e58f;
236
+ }
237
+ .green_button:first-child {
238
+ margin-left: 0;
239
+ }
240
+ .green_button:hover{
241
+ color: #fff;
242
+ border: 1px solid #3fbc60;
243
+ background-color: #3fbc60;
244
+ }
@@ -52,7 +52,7 @@ class ArticlesController < ApplicationController
52
52
  private
53
53
  # Use callbacks to share common setup or constraints between actions.
54
54
  def set_article
55
- @article = Article.find(params[:id])
55
+ @article = Article.includes(:user).find_by_id(params[:id])
56
56
  end
57
57
 
58
58
  # Only allow a trusted parameter "white list" through.
@@ -4,5 +4,6 @@ class Admin < ActiveRecord::Base
4
4
 
5
5
  acts_as_notification_target email: :email,
6
6
  email_allowed: ->(admin, key) { admin.user.confirmed_at.present? },
7
- devise_resource: :user
7
+ devise_resource: :user,
8
+ printable_name: ->(admin) { "admin (#{admin.user.name})" }
8
9
  end
@@ -1,11 +1,18 @@
1
1
  class Article < ActiveRecord::Base
2
2
  belongs_to :user
3
- has_many :comments, dependent: :delete_all
3
+ has_many :comments, dependent: :destroy
4
4
  has_many :commented_users, through: :comments, source: :user
5
5
  validates :user, presence: true
6
6
 
7
7
  acts_as_notifiable :users,
8
8
  targets: ->(article, key) { User.all.to_a - [article.user] },
9
9
  notifier: :user,
10
- email_allowed: true
10
+ email_allowed: true,
11
+ printable_name: ->(article) { "new article \"#{article.title}\"" },
12
+ dependent_notifications: :delete_all
13
+ acts_as_notification_group printable_name: ->(article) { "article \"#{article.title}\"" }
14
+
15
+ def author?(user)
16
+ self.user == user
17
+ end
11
18
  end
@@ -6,15 +6,21 @@ class Comment < ActiveRecord::Base
6
6
 
7
7
  acts_as_notifiable :users,
8
8
  targets: ->(comment, key) {
9
- (comment.article.commented_users.to_a - [comment.user] + [comment.article.user]).uniq
9
+ ([comment.article.user] + comment.article.commented_users.to_a - [comment.user]).uniq
10
10
  },
11
11
  group: :article,
12
12
  notifier: :user,
13
13
  email_allowed: true,
14
14
  parameters: { test_default_param: '1' },
15
- notifiable_path: :article_notifiable_path
15
+ notifiable_path: :article_notifiable_path,
16
+ printable_name: ->(comment) { "comment \"#{comment.body}\"" },
17
+ dependent_notifications: :delete_all
16
18
 
17
19
  def article_notifiable_path
18
20
  article_path(article)
19
21
  end
22
+
23
+ def author?(user)
24
+ self.user == user
25
+ end
20
26
  end
@@ -0,0 +1,4 @@
1
+ class Dummy::DummyGroup < ActiveRecord::Base
2
+ self.table_name = :articles
3
+ include ActivityNotification::Group
4
+ end
@@ -1,8 +1,13 @@
1
1
  class User < ActiveRecord::Base
2
2
  devise :database_authenticatable, :registerable, :confirmable
3
3
  validates :email, presence: true
4
- has_many :articles, dependent: :delete_all
5
- has_many :comments, through: :articles, dependent: :delete_all
4
+ has_many :articles, dependent: :destroy
5
+ has_one :admin, dependent: :destroy
6
6
 
7
- acts_as_target email: :email, email_allowed: :confirmed_at
7
+ acts_as_target email: :email, email_allowed: :confirmed_at, printable_name: :name
8
+ acts_as_notifier printable_name: :name
9
+
10
+ def admin?
11
+ admin.present?
12
+ end
8
13
  end