proclaim 0.3.1 → 0.4.0

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