fixes #2191
This commit is contained in:
@@ -11,5 +11,6 @@ class DailyMaintenance
|
|||||||
UserUploadClamper.new.clamp_all!
|
UserUploadClamper.new.clamp_all!
|
||||||
TagSubscription.process_all
|
TagSubscription.process_all
|
||||||
ApiCacheGenerator.new.generate_tag_cache
|
ApiCacheGenerator.new.generate_tag_cache
|
||||||
|
ForumSubscription.process_all!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
class UserMailer < ActionMailer::Base
|
class UserMailer < ActionMailer::Base
|
||||||
|
add_template_helper ApplicationHelper
|
||||||
default :from => Danbooru.config.contact_email, :content_type => "text/html"
|
default :from => Danbooru.config.contact_email, :content_type => "text/html"
|
||||||
|
|
||||||
def dmail_notice(dmail)
|
def dmail_notice(dmail)
|
||||||
@@ -13,4 +14,10 @@ class UserMailer < ActionMailer::Base
|
|||||||
def upgrade_fail(email)
|
def upgrade_fail(email)
|
||||||
mail(:to => "#{user.name} <#{email}>", :subject => "#{Danbooru.config.app_name} account upgrade")
|
mail(:to => "#{user.name} <#{email}>", :subject => "#{Danbooru.config.app_name} account upgrade")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def forum_notice(user, forum_topic, forum_posts)
|
||||||
|
@forum_topic = forum_topic
|
||||||
|
@forum_posts = forum_posts
|
||||||
|
mail(:to => "#{user.name} <#{user.email}>", :subject => "#{Danbooru.config.app_name} forum topic #{forum_topic.title} updated")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class ForumPost < ActiveRecord::Base
|
class ForumPost < ActiveRecord::Base
|
||||||
attr_accessible :body, :topic_id, :as => [:member, :builder, :janitor, :gold, :platinum, :contributor, :admin, :moderator, :default]
|
attr_accessible :body, :topic_id, :receive_email_notifications, :as => [:member, :builder, :janitor, :gold, :platinum, :contributor, :admin, :moderator, :default]
|
||||||
attr_accessible :is_locked, :is_sticky, :is_deleted, :as => [:admin, :moderator, :janitor]
|
attr_accessible :is_locked, :is_sticky, :is_deleted, :as => [:admin, :moderator, :janitor]
|
||||||
attr_readonly :topic_id
|
attr_readonly :topic_id
|
||||||
belongs_to :creator, :class_name => "User"
|
belongs_to :creator, :class_name => "User"
|
||||||
@@ -15,6 +15,8 @@ class ForumPost < ActiveRecord::Base
|
|||||||
validate :validate_topic_is_unlocked
|
validate :validate_topic_is_unlocked
|
||||||
before_destroy :validate_topic_is_unlocked
|
before_destroy :validate_topic_is_unlocked
|
||||||
after_save :delete_topic_if_original_post
|
after_save :delete_topic_if_original_post
|
||||||
|
after_save :update_email_notifications
|
||||||
|
attr_accessor :receive_email_notifications
|
||||||
|
|
||||||
module SearchMethods
|
module SearchMethods
|
||||||
def body_matches(body)
|
def body_matches(body)
|
||||||
@@ -188,4 +190,22 @@ class ForumPost < ActiveRecord::Base
|
|||||||
def hidden_attributes
|
def hidden_attributes
|
||||||
super + [:text_index]
|
super + [:text_index]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def receive_email_notifications
|
||||||
|
@receive_email_notifications ||= ForumSubscription.where(:forum_topic_id => topic_id, :user_id => CurrentUser.user.id).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_email_notifications
|
||||||
|
subscription = ForumSubscription.where(:forum_topic_id => topic_id, :user_id => CurrentUser.user.id).first
|
||||||
|
|
||||||
|
if receive_email_notifications == "1"
|
||||||
|
if subscription
|
||||||
|
subscription.update_attribute(:last_read_at, updated_at)
|
||||||
|
else
|
||||||
|
ForumSubscription.create(:forum_topic_id => topic_id, :user_id => CurrentUser.user.id, :last_read_at => updated_at)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
subscription.destroy if subscription
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
22
app/models/forum_subscription.rb
Normal file
22
app/models/forum_subscription.rb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
class ForumSubscription < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :forum_topic
|
||||||
|
attr_accessible :user, :forum_topic, :user_id, :forum_topic_id, :last_read_at, :delete_key
|
||||||
|
|
||||||
|
def self.prune!
|
||||||
|
where("last_read_at < ?", 3.months.ago).delete_all
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.process_all!
|
||||||
|
ForumSubscription.find_each do |subscription|
|
||||||
|
forum_topic = subscription.forum_topic
|
||||||
|
if forum_topic.updated_at > subscription.last_read_at
|
||||||
|
CurrentUser.scoped(subscription.user, "127.0.0.1") do
|
||||||
|
forum_posts = forum_topic.posts.where("created_at >= ?", subscription.last_read_at).order("id desc")
|
||||||
|
UserMailer.forum_notice(subscription.user, forum_topic, forum_posts).deliver
|
||||||
|
subscription.update_attribute(:last_read_at, forum_topic.updated_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,6 +11,7 @@ class ForumTopic < ActiveRecord::Base
|
|||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
has_many :posts, lambda {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id", :dependent => :destroy
|
has_many :posts, lambda {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id", :dependent => :destroy
|
||||||
has_one :original_post, lambda {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id"
|
has_one :original_post, lambda {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id"
|
||||||
|
has_many :subscriptions, :class_name => "ForumSubscription"
|
||||||
before_validation :initialize_creator, :on => :create
|
before_validation :initialize_creator, :on => :create
|
||||||
before_validation :initialize_updater
|
before_validation :initialize_updater
|
||||||
before_validation :initialize_is_deleted, :on => :create
|
before_validation :initialize_is_deleted, :on => :create
|
||||||
@@ -99,6 +100,24 @@ class ForumTopic < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module SubscriptionMethods
|
||||||
|
def update_subscription!(user)
|
||||||
|
user_subscription = subscriptions.where(:user_id => user.id).first
|
||||||
|
|
||||||
|
if user_subscription
|
||||||
|
user_subscription.update_attribute(:last_read_at, updated_at)
|
||||||
|
else
|
||||||
|
subscriptions.create(:user_id => user.id, :last_read_at => updated_at, :delete_key => SecureRandom.urlsafe_base64(10))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def notify_subscriptions!
|
||||||
|
ForumSubscription.where(:forum_topic_id => id).where("last_read_at < ?", updated_at).find_each do |subscription|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
extend SearchMethods
|
extend SearchMethods
|
||||||
include CategoryMethods
|
include CategoryMethods
|
||||||
include VisitMethods
|
include VisitMethods
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
<%= f.input :topic_id, :as => :hidden %>
|
<%= f.input :topic_id, :as => :hidden %>
|
||||||
<%= dtext_field "forum_post", "body" %>
|
<%= dtext_field "forum_post", "body" %>
|
||||||
|
|
||||||
|
<%= f.input :receive_email_notifications, :as => :boolean %>
|
||||||
|
|
||||||
<%= f.button :submit, "Submit" %>
|
<%= f.button :submit, "Submit" %>
|
||||||
<%= dtext_preview_button "forum_post", "body" %>
|
<%= dtext_preview_button "forum_post", "body" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<%= stylesheet_link_tag "application", :media => "screen" %>
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p><%= h @dmail.from.name %> said:</p>
|
<p><%= h @dmail.from.name %> said:</p>
|
||||||
|
|
||||||
|
|||||||
21
app/views/user_mailer/forum_notice.html.erb
Normal file
21
app/views/user_mailer/forum_notice.html.erb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<%= stylesheet_link_tag "application", :media => "screen" %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><%= @forum_topic.title %> was updated:</p>
|
||||||
|
|
||||||
|
<% @forum_posts.each do |forum_post| %>
|
||||||
|
<div class="prose">
|
||||||
|
<p class="author">
|
||||||
|
<%= forum_post.creator_name %> said:
|
||||||
|
</p>
|
||||||
|
<%= format_text(forum_post.body) %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<p><%= link_to "View topic", forum_topic_path(@forum_topic, :page => @forum_topic.last_page, :host => Danbooru.config.hostname, :only_path => false) %></p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
db/migrate/20140725003232_create_forum_subscriptions.rb
Normal file
13
db/migrate/20140725003232_create_forum_subscriptions.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class CreateForumSubscriptions < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :forum_subscriptions do |t|
|
||||||
|
t.integer :user_id
|
||||||
|
t.integer :forum_topic_id
|
||||||
|
t.datetime :last_read_at
|
||||||
|
t.string :delete_key
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :forum_subscriptions, :user_id
|
||||||
|
add_index :forum_subscriptions, :forum_topic_id
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -2012,6 +2012,38 @@ CREATE SEQUENCE forum_posts_id_seq
|
|||||||
ALTER SEQUENCE forum_posts_id_seq OWNED BY forum_posts.id;
|
ALTER SEQUENCE forum_posts_id_seq OWNED BY forum_posts.id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: forum_subscriptions; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE forum_subscriptions (
|
||||||
|
id integer NOT NULL,
|
||||||
|
user_id integer,
|
||||||
|
forum_topic_id integer,
|
||||||
|
last_read_at timestamp without time zone,
|
||||||
|
delete_key character varying(255)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: forum_subscriptions_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE forum_subscriptions_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: forum_subscriptions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE forum_subscriptions_id_seq OWNED BY forum_subscriptions.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: forum_topic_visits; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
-- Name: forum_topic_visits; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -3954,6 +3986,13 @@ ALTER TABLE ONLY favorites_99 ALTER COLUMN id SET DEFAULT nextval('favorites_id_
|
|||||||
ALTER TABLE ONLY forum_posts ALTER COLUMN id SET DEFAULT nextval('forum_posts_id_seq'::regclass);
|
ALTER TABLE ONLY forum_posts ALTER COLUMN id SET DEFAULT nextval('forum_posts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY forum_subscriptions ALTER COLUMN id SET DEFAULT nextval('forum_subscriptions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
@@ -4300,6 +4339,14 @@ ALTER TABLE ONLY forum_posts
|
|||||||
ADD CONSTRAINT forum_posts_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT forum_posts_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: forum_subscriptions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY forum_subscriptions
|
||||||
|
ADD CONSTRAINT forum_subscriptions_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: forum_topic_visits_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
-- Name: forum_topic_visits_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -6185,6 +6232,20 @@ CREATE INDEX index_forum_posts_on_text_index ON forum_posts USING gin (text_inde
|
|||||||
CREATE INDEX index_forum_posts_on_topic_id ON forum_posts USING btree (topic_id);
|
CREATE INDEX index_forum_posts_on_topic_id ON forum_posts USING btree (topic_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_forum_subscriptions_on_forum_topic_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_forum_subscriptions_on_forum_topic_id ON forum_subscriptions USING btree (forum_topic_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_forum_subscriptions_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_forum_subscriptions_on_user_id ON forum_subscriptions USING btree (user_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_forum_topic_visits_on_forum_topic_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: index_forum_topic_visits_on_forum_topic_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -6192,6 +6253,13 @@ CREATE INDEX index_forum_posts_on_topic_id ON forum_posts USING btree (topic_id)
|
|||||||
CREATE INDEX index_forum_topic_visits_on_forum_topic_id ON forum_topic_visits USING btree (forum_topic_id);
|
CREATE INDEX index_forum_topic_visits_on_forum_topic_id ON forum_topic_visits USING btree (forum_topic_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_forum_topic_visits_on_last_read_at; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX index_forum_topic_visits_on_last_read_at ON forum_topic_visits USING btree (last_read_at);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_forum_topic_visits_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: index_forum_topic_visits_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
@@ -6992,3 +7060,5 @@ INSERT INTO schema_migrations (version) VALUES ('20140701224800');
|
|||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20140722225753');
|
INSERT INTO schema_migrations (version) VALUES ('20140722225753');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20140725003232');
|
||||||
|
|
||||||
|
|||||||
4
test/factories/forum_subscription.rb
Normal file
4
test/factories/forum_subscription.rb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FactoryGirl.define do
|
||||||
|
factory(:forum_subscription) do
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -14,6 +14,33 @@ class ForumPostTest < ActiveSupport::TestCase
|
|||||||
CurrentUser.ip_addr = nil
|
CurrentUser.ip_addr = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "#receive_email_notifications" do
|
||||||
|
should "return true if a matching subscription exists" do
|
||||||
|
FactoryGirl.create(:forum_subscription, :forum_topic_id => @topic.id, :user_id => CurrentUser.user.id)
|
||||||
|
assert_equal(true, ForumPost.new(:topic_id => @topic.id).receive_email_notifications)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "return false if there is no matching subscription" do
|
||||||
|
assert_equal(false, ForumPost.new(:topic_id => @topic.id).receive_email_notifications)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "#update_email_notifications" do
|
||||||
|
should "create a forum subscription if one doesn't exist" do
|
||||||
|
assert_difference("ForumSubscription.count", 1) do
|
||||||
|
FactoryGirl.create(:forum_post, :topic_id => @topic.id, :receive_email_notifications => true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "update the forum subscription if one already exists" do
|
||||||
|
FactoryGirl.create(:forum_subscription, :forum_topic_id => @topic.id, :user_id => CurrentUser.user.id)
|
||||||
|
assert_difference("ForumSubscription.count", 0) do
|
||||||
|
FactoryGirl.create(:forum_post, :topic_id => @topic.id, :receive_email_notifications => true)
|
||||||
|
end
|
||||||
|
assert_not_nil(ForumSubscription.last.last_read_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "that belongs to a topic with several pages of posts" do
|
context "that belongs to a topic with several pages of posts" do
|
||||||
setup do
|
setup do
|
||||||
Danbooru.config.stubs(:posts_per_page).returns(3)
|
Danbooru.config.stubs(:posts_per_page).returns(3)
|
||||||
|
|||||||
Reference in New Issue
Block a user