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,5 @@
1
+ FactoryGirl.define do
2
+ factory :article do
3
+ user
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :comment do
3
+ article
4
+ user
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :notification, class: ActivityNotification::Notification do
3
+ association :target, factory: :user
4
+ association :notifiable, factory: :article
5
+ key "default.default"
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :user do
3
+ email ['a'..'z'].shuffle.join + '@example.com'
4
+ end
5
+ end
@@ -0,0 +1,259 @@
1
+ describe ActivityNotification::Notification, type: :model do
2
+
3
+ it_behaves_like :notification_api
4
+
5
+ describe "with association" do
6
+ it "belongs to target" do
7
+ target = create(:user)
8
+ notification = create(:notification, target: target)
9
+ expect(notification.reload.target).to eq(target)
10
+ end
11
+
12
+ it "belongs to notifiable" do
13
+ notifiable = create(:article)
14
+ notification = create(:notification, notifiable: notifiable)
15
+ expect(notification.reload.notifiable).to eq(notifiable)
16
+ end
17
+
18
+ it "belongs to group" do
19
+ group = create(:article)
20
+ notification = create(:notification, group: group)
21
+ expect(notification.reload.group).to eq(group)
22
+ end
23
+
24
+ it "belongs to notification as group_owner" do
25
+ group_owner = create(:notification, group_owner: nil)
26
+ group_member = create(:notification, group_owner: group_owner)
27
+ expect(group_member.reload.group_owner).to eq(group_owner)
28
+ end
29
+
30
+ it "has many notifications as group_members" do
31
+ group_owner = create(:notification, group_owner: nil)
32
+ group_member = create(:notification, group_owner: group_owner)
33
+ expect(group_owner.reload.group_members.first).to eq(group_member)
34
+ end
35
+
36
+ it "belongs to notifier" do
37
+ notifier = create(:user)
38
+ notification = create(:notification, notifier: notifier)
39
+ expect(notification.reload.notifier).to eq(notifier)
40
+ end
41
+ end
42
+
43
+ describe "with serializable column" do
44
+ it "has parameters for hash" do
45
+ parameters = {a: 1, b: 2, c: 3}
46
+ notification = create(:notification, parameters: parameters)
47
+ expect(notification.reload.parameters).to eq(parameters)
48
+ end
49
+ end
50
+
51
+ describe "with validation" do
52
+ before { @notification = build(:notification) }
53
+
54
+ it "is valid with target, notifiable and key" do
55
+ expect(@notification).to be_valid
56
+ end
57
+
58
+ it "is invalid with blank target" do
59
+ @notification.target = nil
60
+ expect(@notification).to be_invalid
61
+ expect(@notification.errors[:target].size).to eq(1)
62
+ end
63
+
64
+ it "is invalid with blank notifiable" do
65
+ @notification.notifiable = nil
66
+ expect(@notification).to be_invalid
67
+ expect(@notification.errors[:notifiable].size).to eq(1)
68
+ end
69
+
70
+ it "is invalid with blank key" do
71
+ @notification.key = nil
72
+ expect(@notification).to be_invalid
73
+ expect(@notification.errors[:key].size).to eq(1)
74
+ end
75
+ end
76
+
77
+ describe "with scope" do
78
+ context "to filter by notification status" do
79
+ before do
80
+ ActivityNotification::Notification.delete_all
81
+ @unopened_group_owner = create(:notification, group_owner: nil)
82
+ @unopened_group_member = create(:notification, group_owner: @unopened_group_owner)
83
+ @opened_group_owner = create(:notification, group_owner: nil, opened_at: DateTime.now)
84
+ @opened_group_member = create(:notification, group_owner: @opened_group_owner, opened_at: DateTime.now)
85
+ end
86
+
87
+ it "works with group_owners_only scope" do
88
+ notifications = ActivityNotification::Notification.group_owners_only
89
+ expect(notifications.size).to eq(2)
90
+ expect(notifications.where(opened_at: nil).first).to eq(@unopened_group_owner)
91
+ expect(notifications.where.not(opened_at: nil).first).to eq(@opened_group_owner)
92
+ end
93
+
94
+ it "works with group_members_only scope" do
95
+ notifications = ActivityNotification::Notification.group_members_only
96
+ expect(notifications.size).to eq(2)
97
+ expect(notifications.where(opened_at: nil).first).to eq(@unopened_group_member)
98
+ expect(notifications.where.not(opened_at: nil).first).to eq(@opened_group_member)
99
+ end
100
+
101
+ it "works with unopened_only scope" do
102
+ notifications = ActivityNotification::Notification.unopened_only
103
+ expect(notifications.size).to eq(2)
104
+ expect(notifications.where(group_owner: nil).first).to eq(@unopened_group_owner)
105
+ expect(notifications.where.not(group_owner: nil).first).to eq(@unopened_group_member)
106
+ end
107
+
108
+ it "works with unopened_index scope" do
109
+ notifications = ActivityNotification::Notification.unopened_index
110
+ expect(notifications.size).to eq(1)
111
+ expect(notifications.first).to eq(@unopened_group_owner)
112
+ end
113
+
114
+ it "works with opened_only! scope" do
115
+ notifications = ActivityNotification::Notification.opened_only!
116
+ expect(notifications.size).to eq(2)
117
+ expect(notifications.where(group_owner: nil).first).to eq(@opened_group_owner)
118
+ expect(notifications.where.not(group_owner: nil).first).to eq(@opened_group_member)
119
+ end
120
+
121
+ context "with opened_only scope" do
122
+ it "works" do
123
+ notifications = ActivityNotification::Notification.opened_only(4)
124
+ expect(notifications.size).to eq(2)
125
+ expect(notifications.where(group_owner: nil).first).to eq(@opened_group_owner)
126
+ expect(notifications.where.not(group_owner: nil).first).to eq(@opened_group_member)
127
+ end
128
+
129
+ it "works with limit" do
130
+ notifications = ActivityNotification::Notification.opened_only(1)
131
+ expect(notifications.size).to eq(1)
132
+ end
133
+ end
134
+
135
+ context "with opened_index scope" do
136
+ it "works" do
137
+ notifications = ActivityNotification::Notification.opened_index(4)
138
+ expect(notifications.size).to eq(1)
139
+ expect(notifications.first).to eq(@opened_group_owner)
140
+ end
141
+
142
+ it "works with limit" do
143
+ notifications = ActivityNotification::Notification.opened_index(0)
144
+ expect(notifications.size).to eq(0)
145
+ end
146
+ end
147
+
148
+ it "works with unopened_index_group_members_only scope" do
149
+ notifications = ActivityNotification::Notification.unopened_index_group_members_only
150
+ expect(notifications.size).to eq(1)
151
+ expect(notifications.first).to eq(@unopened_group_member)
152
+ end
153
+
154
+ context "with opened_index_group_members_only scope" do
155
+ it "works" do
156
+ notifications = ActivityNotification::Notification.opened_index_group_members_only(4)
157
+ expect(notifications.size).to eq(1)
158
+ expect(notifications.first).to eq(@opened_group_member)
159
+ end
160
+
161
+ it "works with limit" do
162
+ notifications = ActivityNotification::Notification.opened_index_group_members_only(0)
163
+ expect(notifications.size).to eq(0)
164
+ end
165
+ end
166
+ end
167
+
168
+ context "to filter by association" do
169
+ before do
170
+ ActivityNotification::Notification.delete_all
171
+ @target_1, @notifiable_1, @group_1, @key_1 = create(:user), create(:article), nil, "key.1"
172
+ @target_2, @notifiable_2, @group_2, @key_2 = create(:user), create(:comment), @notifiable_1, "key.2"
173
+ @notification_1 = create(:notification, target: @target_1, notifiable: @notifiable_1, group: @group_1, key: @key_1)
174
+ @notification_2 = create(:notification, target: @target_2, notifiable: @notifiable_2, group: @group_2, key: @key_2)
175
+ end
176
+
177
+ it "works with filtered_by_target scope" do
178
+ notifications = ActivityNotification::Notification.filtered_by_target(@target_1)
179
+ expect(notifications.size).to eq(1)
180
+ expect(notifications.first).to eq(@notification_1)
181
+ notifications = ActivityNotification::Notification.filtered_by_target(@target_2)
182
+ expect(notifications.size).to eq(1)
183
+ expect(notifications.first).to eq(@notification_2)
184
+ end
185
+
186
+ it "works with filtered_by_instance scope" do
187
+ notifications = ActivityNotification::Notification.filtered_by_instance(@notifiable_1)
188
+ expect(notifications.size).to eq(1)
189
+ expect(notifications.first).to eq(@notification_1)
190
+ notifications = ActivityNotification::Notification.filtered_by_instance(@notifiable_2)
191
+ expect(notifications.size).to eq(1)
192
+ expect(notifications.first).to eq(@notification_2)
193
+ end
194
+
195
+ it "works with filtered_by_type scope" do
196
+ notifications = ActivityNotification::Notification.filtered_by_type(@notifiable_1.class)
197
+ expect(notifications.size).to eq(1)
198
+ expect(notifications.first).to eq(@notification_1)
199
+ notifications = ActivityNotification::Notification.filtered_by_type(@notifiable_2.class)
200
+ expect(notifications.size).to eq(1)
201
+ expect(notifications.first).to eq(@notification_2)
202
+ end
203
+
204
+ it "works with filtered_by_group scope" do
205
+ notifications = ActivityNotification::Notification.filtered_by_group(@group_1)
206
+ expect(notifications.size).to eq(1)
207
+ expect(notifications.first).to eq(@notification_1)
208
+ notifications = ActivityNotification::Notification.filtered_by_group(@group_2)
209
+ expect(notifications.size).to eq(1)
210
+ expect(notifications.first).to eq(@notification_2)
211
+ end
212
+
213
+ it "works with filtered_by_key scope" do
214
+ notifications = ActivityNotification::Notification.filtered_by_key(@key_1)
215
+ expect(notifications.size).to eq(1)
216
+ expect(notifications.first).to eq(@notification_1)
217
+ notifications = ActivityNotification::Notification.filtered_by_key(@key_2)
218
+ expect(notifications.size).to eq(1)
219
+ expect(notifications.first).to eq(@notification_2)
220
+ end
221
+ end
222
+
223
+ context "to make order by created_at" do
224
+ before do
225
+ ActivityNotification::Notification.delete_all
226
+ unopened_group_owner = create(:notification, group_owner: nil)
227
+ unopened_group_member = create(:notification, group_owner: unopened_group_owner)
228
+ opened_group_owner = create(:notification, group_owner: nil, opened_at: DateTime.now)
229
+ opened_group_member = create(:notification, group_owner: opened_group_owner, opened_at: DateTime.now)
230
+ @earliest_notification = unopened_group_owner
231
+ @latest_notification = opened_group_member
232
+ end
233
+
234
+ it "works with latest_order scope" do
235
+ notifications = ActivityNotification::Notification.latest_order
236
+ expect(notifications.size).to eq(4)
237
+ expect(notifications.first).to eq(@latest_notification)
238
+ expect(notifications.last).to eq(@earliest_notification)
239
+ end
240
+
241
+ it "works with earliest_order scope" do
242
+ notifications = ActivityNotification::Notification.earliest_order
243
+ expect(notifications.size).to eq(4)
244
+ expect(notifications.first).to eq(@earliest_notification)
245
+ expect(notifications.last).to eq(@latest_notification)
246
+ end
247
+
248
+ it "returns the latest notification with latest scope" do
249
+ notification = ActivityNotification::Notification.latest
250
+ expect(notification).to eq(@latest_notification)
251
+ end
252
+
253
+ it "returns the earliest notification with earliest scope" do
254
+ notification = ActivityNotification::Notification.earliest
255
+ expect(notification).to eq(@earliest_notification)
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
File without changes
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
File without changes
File without changes
@@ -0,0 +1,12 @@
1
+ class Article < ActiveRecord::Base
2
+ include ActivityNotification::Notifiable
3
+ acts_as_notifiable :users,
4
+ targets: ->(article, key) { [article.user] },
5
+ notifier: :user,
6
+ email_allowed: true#,
7
+ #notifiable_path: ->(article) { concept_issue_path(issue.concept, issue) }
8
+
9
+ belongs_to :user
10
+ has_many :comments, dependent: :delete_all
11
+ has_many :commented_users, through: :comments, source: :user
12
+ end
@@ -0,0 +1,18 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :article
3
+ belongs_to :user
4
+
5
+ include ActivityNotification::Notifiable
6
+ acts_as_notifiable :users,
7
+ targets: ->(comment, key) { (comment.article.commented_users.to_a - [comment.user] + [comment.article.user]).uniq },
8
+ group: :article,
9
+ notifier: :user,
10
+ email_allowed: :custom_notification_email_to_users_allowed?,
11
+ parameters: {test_default_param: '1'}#,
12
+ #notifiable_path: :custom_notifiable_path
13
+
14
+ def custom_notification_email_to_users_allowed?(user, key)
15
+ true
16
+ end
17
+
18
+ end
File without changes
@@ -0,0 +1,8 @@
1
+ class User < ActiveRecord::Base
2
+ # devise :database_authenticatable, :registerable, :confirmable
3
+
4
+ include ActivityNotification::Target
5
+ acts_as_target email: :email, email_allowed: :confirmed_at
6
+
7
+ validates :email, presence: true
8
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ # path to your application root.
5
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
6
+
7
+ Dir.chdir APP_ROOT do
8
+ # This script is a starting point to setup your application.
9
+ # Add necessary setup steps to this file:
10
+
11
+ puts "== Installing dependencies =="
12
+ system "gem install bundler --conservative"
13
+ system "bundle check || bundle install"
14
+
15
+ # puts "\n== Copying sample files =="
16
+ # unless File.exist?("config/database.yml")
17
+ # system "cp config/database.yml.sample config/database.yml"
18
+ # end
19
+
20
+ puts "\n== Preparing database =="
21
+ system "bin/rake db:setup"
22
+
23
+ puts "\n== Removing old logs and tempfiles =="
24
+ system "rm -f log/*"
25
+ system "rm -rf tmp/cache"
26
+
27
+ puts "\n== Restarting application server =="
28
+ system "touch tmp/restart.txt"
29
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails.application
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ # Pick the frameworks you want:
4
+ require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_mailer/railtie"
7
+ require "action_view/railtie"
8
+ require "sprockets/railtie"
9
+ # require "rails/test_unit/railtie"
10
+
11
+ Bundler.require(*Rails.groups)
12
+ require "activity_notification"
13
+
14
+ module Dummy
15
+ class Application < Rails::Application
16
+ # Do not swallow errors in after_commit/after_rollback callbacks.
17
+ config.active_record.raise_in_transactional_callbacks = true
18
+ end
19
+ end
20
+