proclaim 0.3.1 → 0.4.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +9 -0
  3. data/README.md +91 -10
  4. data/Rakefile +1 -1
  5. data/VERSION +1 -1
  6. data/app/assets/javascripts/proclaim/comments_handler.js.coffee +3 -0
  7. data/app/assets/stylesheets/proclaim/subscriptions.css.scss +33 -0
  8. data/app/controllers/proclaim/comments_controller.rb +3 -1
  9. data/app/controllers/proclaim/posts_controller.rb +10 -6
  10. data/app/controllers/proclaim/subscriptions_controller.rb +31 -14
  11. data/app/helpers/proclaim/application_helper.rb +3 -8
  12. data/app/models/proclaim/comment.rb +1 -0
  13. data/app/models/proclaim/post.rb +2 -0
  14. data/app/models/proclaim/subscription.rb +7 -6
  15. data/app/policies/proclaim/image_policy.rb +1 -1
  16. data/app/policies/proclaim/subscription_policy.rb +10 -6
  17. data/app/views/layouts/proclaim/subscription_mailer.html.erb +34 -4
  18. data/app/views/proclaim/posts/edit.html.erb +3 -1
  19. data/app/views/proclaim/posts/index.html.erb +2 -0
  20. data/app/views/proclaim/posts/new.html.erb +3 -1
  21. data/app/views/proclaim/posts/show.html.erb +3 -1
  22. data/app/views/proclaim/subscription_mailer/welcome_email.html.erb +9 -7
  23. data/app/views/proclaim/subscriptions/_form.html.erb +7 -2
  24. data/app/views/proclaim/subscriptions/index.html.erb +89 -0
  25. data/app/views/proclaim/subscriptions/new.html.erb +3 -1
  26. data/app/views/proclaim/subscriptions/show.html.erb +26 -0
  27. data/config/routes.rb +2 -6
  28. data/db/migrate/20150123115226_add_name_to_subscriptions.rb +7 -0
  29. data/lib/generators/proclaim/templates/initialize_proclaim.rb +19 -0
  30. data/lib/proclaim.rb +93 -0
  31. data/lib/proclaim/engine.rb +18 -0
  32. data/lib/proclaim/version.rb +1 -1
  33. data/test/controllers/proclaim/subscriptions_controller_test.rb +76 -21
  34. data/test/dummy/db/schema.rb +4 -3
  35. data/test/factories/proclaim/subscription.rb +1 -0
  36. data/test/integration/with_javascript/post_subscription_test.rb +29 -0
  37. data/test/integration/without_javascript/blog_subscription_test.rb +29 -2
  38. data/test/integration/without_javascript/manage_subscriptions_test.rb +37 -0
  39. data/test/integration/without_javascript/unsubscribe_test.rb +6 -6
  40. data/test/mailers/proclaim/subscription_mailer_test.rb +10 -6
  41. data/test/models/proclaim/subscription_test.rb +5 -0
  42. data/test/policies/proclaim/image_policy_test.rb +83 -0
  43. data/test/policies/proclaim/post_policy_test.rb +11 -0
  44. data/test/policies/proclaim/subscription_policy_test.rb +27 -15
  45. data/test/unit/proclaim/new_comment_callback_test.rb +62 -0
  46. data/test/unit/proclaim/new_subscription_callback_test.rb +62 -0
  47. data/test/unit/proclaim/post_published_callback_test.rb +74 -0
  48. metadata +15 -5
  49. data/app/views/proclaim/subscriptions/subscribed.html.erb +0 -7
  50. data/app/views/proclaim/subscriptions/unsubscribe.html.erb +0 -7
  51. data/app/views/proclaim/subscriptions/unsubscribed.html.erb +0 -3
@@ -1,5 +1,13 @@
1
1
  module Proclaim
2
2
  class SubscriptionPolicy < ApplicationPolicy
3
+ def index?
4
+ not @user.nil? # A user can view the list of subscriptions
5
+ end
6
+
7
+ def show?
8
+ true # Anyone can show the subscription since it requires a token
9
+ end
10
+
3
11
  def create?
4
12
  # A user can subscribe to anything. Guests can only subscribe to
5
13
  # published posts or the blog in general.
@@ -10,12 +18,8 @@ module Proclaim
10
18
  end
11
19
  end
12
20
 
13
- def unsubscribe?
14
- destroy?
15
- end
16
-
17
21
  def destroy?
18
- true # Anyone can unsubscribe (it requires a token anyway)
22
+ show?
19
23
  end
20
24
 
21
25
  class Scope < Scope
@@ -24,7 +28,7 @@ module Proclaim
24
28
  scope.all # Users can access all subscriptions
25
29
  else
26
30
  # Guests can see none
27
- nil
31
+ scope.none
28
32
  end
29
33
  end
30
34
  end
@@ -2,9 +2,11 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
5
6
 
6
7
  <style>
7
- * {
8
+ *
9
+ {
8
10
  box-sizing: border-box;
9
11
  }
10
12
 
@@ -16,6 +18,7 @@
16
18
  table.post
17
19
  {
18
20
  width: 600px;
21
+ table-layout: fixed;
19
22
  margin: 0 auto;
20
23
  }
21
24
 
@@ -36,6 +39,7 @@
36
39
  td.post_title h1
37
40
  {
38
41
  margin: 0 0 10px 0;
42
+ font-size: 30px;
39
43
  padding: 0;
40
44
  }
41
45
 
@@ -48,7 +52,6 @@
48
52
  {
49
53
  float: left;
50
54
  max-width: 35%;
51
- max-width: calc(33.33% + 40px);
52
55
  min-height: 18px;
53
56
  }
54
57
 
@@ -56,7 +59,7 @@
56
59
  {
57
60
  margin: 0px;
58
61
  vertical-align: top;
59
- max-width: 600px;
62
+ max-width: 100%;
60
63
  border: 0px none;
61
64
  }
62
65
 
@@ -94,6 +97,7 @@
94
97
  td.post_body
95
98
  {
96
99
  padding-bottom: 10px;
100
+ font-size: 18px;
97
101
  }
98
102
 
99
103
  td.post_body blockquote
@@ -117,6 +121,32 @@
117
121
  color: #888;
118
122
  }
119
123
  </style>
124
+
125
+ <style data-premailer="ignore">
126
+ @media only screen and (min-width: 521px) and (max-width: 620px)
127
+ {
128
+ table[class="post"]
129
+ {
130
+ width: 500px !important;
131
+ }
132
+ }
133
+
134
+ @media only screen and (min-width: 421px) and (max-width: 520px)
135
+ {
136
+ table[class="post"]
137
+ {
138
+ width: 400px !important;
139
+ }
140
+ }
141
+
142
+ @media only screen and (max-width: 420px)
143
+ {
144
+ table[class="post"]
145
+ {
146
+ width: 320px !important;
147
+ }
148
+ }
149
+ </style>
120
150
  </head>
121
151
  <body>
122
152
  <table class = "main">
@@ -134,7 +164,7 @@
134
164
  <% else %>
135
165
  You're receiving this email because you requested to be notified if a new post was made at <%= link_to url, posts_url %>.
136
166
  <% end %>
137
- If you no longer wish to receive these emails, simply <%= link_to "unsubscribe", unsubscribe_url(@subscription.token) %>.
167
+ If you no longer wish to receive these emails, simply <%= link_to "unsubscribe", subscription_url(@subscription.token) %>.
138
168
  </td>
139
169
  </tr>
140
170
  </table>
@@ -1,3 +1,5 @@
1
- <h1>Edit post</h1>
1
+ <% proclaim_title "Edit Post" %>
2
+
3
+ <h1><%= content_for :proclaim_title %></h1>
2
4
 
3
5
  <%= render 'form' %>
@@ -1,3 +1,5 @@
1
+ <% proclaim_title "Posts" %>
2
+
1
3
  <% if policy(Proclaim::Post).new? %>
2
4
  <%= link_to 'New Post', new_post_path %>
3
5
  <% end %>
@@ -1,3 +1,5 @@
1
- <h1>New post</h1>
1
+ <% proclaim_title "New Post" %>
2
+
3
+ <h1><%= content_for :proclaim_title %></h1>
2
4
 
3
5
  <%= render 'form' %>
@@ -1,3 +1,5 @@
1
+ <% proclaim_title @post.title %>
2
+
1
3
  <script type="text/javascript">
2
4
  $(document).ready(function()
3
5
  {
@@ -28,7 +30,7 @@
28
30
  </div>
29
31
 
30
32
  <div class = "post">
31
- <h1 class = "post_title"><%= @post.title %></h1>
33
+ <h1 class = "post_title"><%= content_for :proclaim_title %></h1>
32
34
 
33
35
  <div class = "post_body show">
34
36
  <%= @post.body.html_safe %>
@@ -1,11 +1,7 @@
1
1
  <table class = "post">
2
2
  <tr>
3
3
  <td class = "post_title"><h1>
4
- <% if @subscription.post %>
5
- You'll be notified!
6
- <% else %>
7
- Thanks for subscribing!
8
- <% end %>
4
+ Hello, <%= @subscription.name %>!
9
5
  </h1></td>
10
6
  </tr>
11
7
 
@@ -13,12 +9,18 @@
13
9
  <td class = "post_body">
14
10
  <% if @subscription.post %>
15
11
  <p>
16
- You signed up to be notified of any new comments on <%= link_to "this post", @subscription.post %>.
12
+ You signed up to be notified of any new comments on
13
+ <%= link_to "this post", @subscription.post %>.
17
14
  </p>
18
15
  <% else %>
19
16
  <p>
20
- You'll now begin receiving a notification each time a new post is made at <%= link_to root_url.gsub(/\A.*:\/\//, '').gsub(/\A(.*?)\/*\z/, '\1'), posts_url %>.
17
+ You signed up to receive a notification each time a new post is
18
+ made at
19
+ <%= link_to root_url.gsub(/\A.*:\/\//, '').gsub(/\A(.*?)\/*\z/, '\1'),
20
+ posts_url %>.
21
21
  </p>
22
+
23
+ <p>Thanks for subscribing!</p>
22
24
  <% end %>
23
25
  </td>
24
26
  </tr>
@@ -11,9 +11,14 @@
11
11
  </div>
12
12
  <% end %>
13
13
 
14
+ <div class="field">
15
+ <%= f.label :name %><br>
16
+ <%= f.text_field :name %>
17
+ </div>
18
+
14
19
  <div class="field">
15
20
  <%= f.label :email %><br>
16
- <%= f.text_field :email %>
21
+ <%= f.email_field :email %>
17
22
  </div>
18
23
 
19
24
  <%
@@ -27,6 +32,6 @@
27
32
  </div>
28
33
 
29
34
  <div class="actions">
30
- <%= f.submit "Subscribe" %>
35
+ <%= f.submit %>
31
36
  </div>
32
37
  <% end %>
@@ -0,0 +1,89 @@
1
+ <% proclaim_title "Manage Subscriptions" %>
2
+
3
+ <h1><%= content_for :proclaim_title %></h1>
4
+
5
+ <%= link_to "New Blog Subscription", new_subscription_path %>
6
+
7
+ <%
8
+ blog_subscriptions = @subscriptions.select {|subscription| subscription.post.nil?}
9
+ post_subscriptions = @subscriptions - blog_subscriptions
10
+
11
+ posts = Hash.new
12
+
13
+ post_subscriptions.each do | subscription |
14
+ post_title = subscription.post.title
15
+ unless posts.has_key? post_title
16
+ posts[post_title] = Array.new
17
+ end
18
+
19
+ posts[post_title] << subscription
20
+ end
21
+ %>
22
+
23
+ <% unless posts.empty? %>
24
+ <div class = "post_subscriptions">
25
+ <h2>Post Subscriptions</h2>
26
+ <% posts.each do | post_title, subscriptions | %>
27
+ <h4><%= post_title %></h4>
28
+ <table class = "subscriptions">
29
+ <thead>
30
+ <tr>
31
+ <th>Name</th>
32
+ <th>Email</th>
33
+ <th></th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ <% subscriptions.each do | subscription | %>
38
+ <tr class = "subscription">
39
+ <td><%= subscription.name %></td>
40
+ <td><%= subscription.email %></td>
41
+ <td style = "text-align: right;">
42
+ <% if policy(subscription).destroy? %>
43
+ <%= link_to 'Delete',
44
+ subscription_path(subscription.token),
45
+ method: :delete,
46
+ data: { confirm: 'Are you sure?' } %>
47
+ <% end %>
48
+ </td>
49
+ </tr>
50
+ <% end %>
51
+ </tbody>
52
+ </table>
53
+ <% end %>
54
+ </div>
55
+ <% end %>
56
+
57
+ <% unless blog_subscriptions.empty? %>
58
+ <div class = "blog_subscriptions">
59
+ <h2>Blog Subscriptions</h2>
60
+ <table class = "subscriptions">
61
+ <thead>
62
+ <tr>
63
+ <th>Name</th>
64
+ <th>Email</th>
65
+ <th></th>
66
+ </tr>
67
+ </thead>
68
+ <tbody>
69
+ <% blog_subscriptions.each do | subscription | %>
70
+ <tr class = "subscription">
71
+ <td><%= subscription.name %></td>
72
+ <td><%= subscription.email %></td>
73
+ <td style = "text-align: right;">
74
+ <% if policy(subscription).destroy? %>
75
+ <%= link_to 'Delete', subscription_path(subscription.token), method: :delete, data: { confirm: 'Are you sure?' } %>
76
+ <% end %>
77
+ </td>
78
+ </tr>
79
+ <% end %>
80
+ </tbody>
81
+ </table>
82
+ </div>
83
+ <% end %>
84
+
85
+ <% if posts.empty? and blog_subscriptions.empty? %>
86
+ <p style = "margin-top: 10px;">
87
+ This blog has no current subscribers.
88
+ </p>
89
+ <% end %>
@@ -1,4 +1,6 @@
1
- <h1>New subscription</h1>
1
+ <% proclaim_title "New Subscription" %>
2
+
3
+ <h1><%= content_for :proclaim_title %></h1>
2
4
 
3
5
  <p>
4
6
  Subscribe to receive each new blog post in an email as soon as it's
@@ -0,0 +1,26 @@
1
+ <% proclaim_title "Subscription for #{@subscription.name}" %>
2
+
3
+ <h1><%= content_for :proclaim_title %></h1>
4
+
5
+ <p>
6
+ <% if @subscription.post %>
7
+ Will be notified of new comments on
8
+ <%= link_to @subscription.post.title, @subscription.post %>
9
+ <% else %>
10
+ Will be notified of new blog posts.
11
+ <% end %>
12
+ </p>
13
+ <p>
14
+ <% if policy(@subscription).destroy? %>
15
+ <%= button_to 'Unsubscribe',
16
+ subscription_path(@subscription.token),
17
+ method: :delete,
18
+ data: {
19
+ confirm: "Are you sure you'd like to unsubscribe from "\
20
+ "this notification item? Note that if you've "\
21
+ "subscribed elsewhere (e.g. other posts), "\
22
+ "you'll still receive notifications for them "\
23
+ "unless you unsubscribe from them as well."
24
+ } %>
25
+ <% end %>
26
+ </p>
data/config/routes.rb CHANGED
@@ -7,12 +7,8 @@ Proclaim::Engine.routes.draw do
7
7
 
8
8
  resources :comments, only: [:create, :update, :destroy]
9
9
 
10
- resources :subscriptions, only: [:new, :create]
11
-
12
- get 'subscriptions/subscribed' => 'subscriptions#subscribed', as: :subscribed
13
- get 'subscriptions/unsubscribe' => 'subscriptions#unsubscribed', as: :unsubscribed
14
- get 'subscriptions/unsubscribe/:token' => 'subscriptions#unsubscribe', as: :unsubscribe
15
- delete 'subscriptions/unsubscribe/:token' => 'subscriptions#destroy'
10
+ # Subscription administration is authenticated via tokens
11
+ resources :subscriptions, param: :token, except: [:edit, :update]
16
12
 
17
13
  root 'posts#index'
18
14
  end
@@ -0,0 +1,7 @@
1
+ class AddNameToSubscriptions < ActiveRecord::Migration
2
+ def change
3
+ change_table :proclaim_subscriptions do |t|
4
+ t.string :name, null: false, default: ""
5
+ end
6
+ end
7
+ end
@@ -38,4 +38,23 @@ Proclaim.setup do |config|
38
38
 
39
39
  # Email address to use in the "from" field of all emails
40
40
  #config.mailer_sender = '"My Blog" <blog@example.com>'
41
+
42
+ # Secret key to use for subscription tokens. Changing this will invalidate
43
+ # any tokens already generated.
44
+ #config.secret_key = nil
45
+
46
+ # Register a callback to be called when a post is published
47
+ #config.after_post_published do |post|
48
+ # puts "A post was just published!"
49
+ #end
50
+
51
+ # Register a callback to be called when a new comment is created
52
+ #config.after_new_comment do |comment|
53
+ # puts "A new comment was just made!"
54
+ #end
55
+
56
+ # Register a callback to be called when a new subscription is created
57
+ #config.after_new_subscription do |subscription|
58
+ # puts "A new subscription was just created!"
59
+ #end
41
60
  end
data/lib/proclaim.rb CHANGED
@@ -35,7 +35,100 @@ module Proclaim
35
35
  mattr_accessor :mailer_sender
36
36
  @@mailer_sender = nil
37
37
 
38
+ mattr_accessor :secret_key
39
+ @@secret_key = nil
40
+
41
+ # Callbacks (must be Procs)
42
+ mattr_accessor :post_published_callbacks
43
+ @@post_published_callbacks = Array.new
44
+ private_class_method :post_published_callbacks, :post_published_callbacks=
45
+
46
+ mattr_accessor :new_comment_callbacks
47
+ @@new_comment_callbacks = Array.new
48
+ private_class_method :new_comment_callbacks, :new_comment_callbacks=
49
+
50
+ mattr_accessor :new_subscription_callbacks
51
+ @@new_subscription_callbacks = Array.new
52
+ private_class_method :new_subscription_callbacks,
53
+ :new_subscription_callbacks=
54
+
55
+ # Default way to setup Proclaim from initializer
38
56
  def self.setup
39
57
  yield self
40
58
  end
59
+
60
+ def self.after_post_published(*callbacks, &block)
61
+ callbacks.each do |callback|
62
+ if callback.respond_to? :call
63
+ @@post_published_callbacks.unshift(callback)
64
+ else
65
+ raise "Proclaim does not support callbacks that aren't blocks or "\
66
+ "Procs"
67
+ end
68
+ end
69
+
70
+ if block_given?
71
+ @@post_published_callbacks.unshift(block)
72
+ end
73
+ end
74
+
75
+ def self.reset_post_published_callbacks
76
+ @@post_published_callbacks = Array.new
77
+ end
78
+
79
+ def self.after_new_comment(*callbacks, &block)
80
+ callbacks.each do |callback|
81
+ if callback.respond_to? :call
82
+ @@new_comment_callbacks.unshift(callback)
83
+ else
84
+ raise "Proclaim does not support callbacks that aren't blocks or "\
85
+ "Procs"
86
+ end
87
+ end
88
+
89
+ if block_given?
90
+ @@new_comment_callbacks.unshift(block)
91
+ end
92
+ end
93
+
94
+ def self.reset_new_comment_callbacks
95
+ @@new_comment_callbacks = Array.new
96
+ end
97
+
98
+ def self.after_new_subscription(*callbacks, &block)
99
+ callbacks.each do |callback|
100
+ if callback.respond_to? :call
101
+ @@new_subscription_callbacks.unshift(callback)
102
+ else
103
+ raise "Proclaim does not support callbacks that aren't blocks or "\
104
+ "Procs"
105
+ end
106
+ end
107
+
108
+ if block_given?
109
+ @@new_subscription_callbacks.unshift(block)
110
+ end
111
+ end
112
+
113
+ def self.reset_new_subscription_callbacks
114
+ @@new_subscription_callbacks = Array.new
115
+ end
116
+
117
+ def self.notify_post_published(post)
118
+ @@post_published_callbacks.each do |callback|
119
+ callback.call(post)
120
+ end
121
+ end
122
+
123
+ def self.notify_new_comment(comment)
124
+ @@new_comment_callbacks.each do |callback|
125
+ callback.call(comment)
126
+ end
127
+ end
128
+
129
+ def self.notify_new_subscription(subscription)
130
+ @@new_subscription_callbacks.each do |callback|
131
+ callback.call(subscription)
132
+ end
133
+ end
41
134
  end