activity_notification 0.0.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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