diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 4b8e2c71f..bff182b9d 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -297,10 +297,16 @@ class ApplicationRecord < ActiveRecord::Base concerning :UserMethods do class_methods do + def user_status_counter(counter_name, options = {}) + class_eval do + belongs_to :user_status, {foreign_key: :creator_id, primary_key: :user_id, counter_cache: counter_name}.merge(options) + end + end + def belongs_to_creator(options = {}) class_eval do belongs_to :creator, options.merge(class_name: "User") - before_validation(on: :create) do |rec| + before_validation(on: :create) do |rec| if rec.creator_id.nil? rec.creator_id = CurrentUser.id rec.creator_ip_addr = CurrentUser.ip_addr if rec.respond_to?(:creator_ip_addr=) diff --git a/app/models/blip.rb b/app/models/blip.rb index cf9314ca7..2e9542dce 100644 --- a/app/models/blip.rb +++ b/app/models/blip.rb @@ -1,6 +1,7 @@ class Blip < ApplicationRecord simple_versioning belongs_to_creator + user_status_counter :blip_count validates_presence_of :body belongs_to :parent, class_name: "Blip", foreign_key: "response_to", optional: true has_many :responses, class_name: "Blip", foreign_key: "response_to" diff --git a/app/models/comment.rb b/app/models/comment.rb index 48ae5d4b2..ed7728250 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -8,6 +8,7 @@ class Comment < ApplicationRecord belongs_to :post belongs_to_creator belongs_to_updater + user_status_counter :comment_count has_many :votes, :class_name => "CommentVote", :dependent => :destroy after_create :update_last_commented_at_on_create after_update(:if => ->(rec) {(!rec.is_deleted? || !rec.saved_change_to_is_deleted?) && CurrentUser.id != rec.creator_id}) do |rec| @@ -18,7 +19,7 @@ class Comment < ApplicationRecord ModAction.log(:comment_delete, {comment_id: rec.id, user_id: rec.creator_id}) end mentionable( - :message_field => :body, + :message_field => :body, :title => ->(user_name) {"#{creator_name} mentioned you in a comment on post ##{post_id}"}, :body => ->(user_name) {"@#{creator_name} mentioned you in a \"comment\":/posts/#{post_id}#comment-#{id} on post ##{post_id}:\n\n[quote]\n#{DText.excerpt(body, "@"+user_name)}\n[/quote]\n"}, ) diff --git a/app/models/favorite.rb b/app/models/favorite.rb index 2457278fd..48568f2f8 100644 --- a/app/models/favorite.rb +++ b/app/models/favorite.rb @@ -3,6 +3,7 @@ class Favorite < ApplicationRecord end belongs_to :post - belongs_to :user, counter_cache: 'favorite_count' + belongs_to :user + user_status_counter :favorite_count, foreign_key: :user_id scope :for_user, ->(user_id) {where("user_id = #{user_id.to_i}")} end diff --git a/app/models/forum_post.rb b/app/models/forum_post.rb index 9bb380187..58fb22e92 100644 --- a/app/models/forum_post.rb +++ b/app/models/forum_post.rb @@ -5,6 +5,7 @@ class ForumPost < ApplicationRecord attr_readonly :topic_id belongs_to_creator belongs_to_updater + user_status_counter :forum_post_count belongs_to :topic, :class_name => "ForumTopic" has_many :votes, class_name: "ForumPostVote" has_one :tag_alias @@ -28,7 +29,7 @@ class ForumPost < ApplicationRecord ModAction.log(:forum_post_delete, {forum_post_id: rec.id, forum_topic_id: rec.topic_id, user_id: rec.creator_id}) end mentionable( - :message_field => :body, + :message_field => :body, :title => ->(user_name) {%{#{creator_name} mentioned you in topic ##{topic_id} (#{topic.title})}}, :body => ->(user_name) {%{@#{creator_name} mentioned you in topic ##{topic_id} ("#{topic.title}":[/forum_topics/#{topic_id}?page=#{forum_topic_page}]):\n\n[quote]\n#{DText.excerpt(body, "@"+user_name)}\n[/quote]\n}}, ) @@ -102,7 +103,7 @@ class ForumPost < ApplicationRecord super(options) end - + def hidden_attributes super + [:text_index] end diff --git a/app/models/note_version.rb b/app/models/note_version.rb index 9b821b267..fc3a84f02 100644 --- a/app/models/note_version.rb +++ b/app/models/note_version.rb @@ -1,5 +1,6 @@ class NoteVersion < ApplicationRecord - belongs_to_updater :counter_cache => "note_update_count" + user_status_counter :note_count, foreign_key: :updater_id + belongs_to_updater scope :for_user, ->(user_id) {where("updater_id = ?", user_id)} def self.search(params) diff --git a/app/models/pool.rb b/app/models/pool.rb index 5d6b7dee9..3435cb67e 100644 --- a/app/models/pool.rb +++ b/app/models/pool.rb @@ -4,6 +4,7 @@ class Pool < ApplicationRecord array_attribute :post_ids, parse: /\d+/, cast: :to_i belongs_to_creator + user_status_counter :pool_count validates_uniqueness_of :name, case_sensitive: false, if: :name_changed? validate :validate_name, if: :name_changed? diff --git a/app/models/post.rb b/app/models/post.rb index fecb40f1c..3d751a406 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -42,7 +42,8 @@ class Post < ApplicationRecord belongs_to :updater, :class_name => "User", optional: true # this is handled in versions belongs_to :approver, class_name: "User", optional: true - belongs_to :uploader, :class_name => "User", :counter_cache => "post_upload_count" + belongs_to :uploader, :class_name => "User" + user_status_counter :post_count, foreign_key: :uploader_id belongs_to :parent, class_name: "Post", optional: true has_one :upload, :dependent => :destroy has_one :artist_commentary, :dependent => :destroy diff --git a/app/models/post_archive.rb b/app/models/post_archive.rb index c762e9590..df61f20db 100644 --- a/app/models/post_archive.rb +++ b/app/models/post_archive.rb @@ -2,7 +2,8 @@ class PostArchive < ApplicationRecord extend Memoist belongs_to :post - belongs_to_updater counter_cache: "post_update_count" + belongs_to_updater + user_status_counter :post_update_count, foreign_key: :updater_id before_validation :fill_version, on: :create before_validation :fill_changes, on: :create diff --git a/app/models/post_set.rb b/app/models/post_set.rb index 9efd6ea62..04ecf0dde 100644 --- a/app/models/post_set.rb +++ b/app/models/post_set.rb @@ -17,7 +17,8 @@ class PostSet < ApplicationRecord end end has_many :maintainers, class_name: "User", through: :post_set_maintainers - belongs_to_creator counter_cache: 'set_count' + belongs_to_creator + user_status_counter :set_count validates_length_of :name, :shortname, in: 3..100, message: "must be between three and one hundred characters long" validates_uniqueness_of :name, :shortname, case_sensitive: false, message: "is already taken" @@ -309,4 +310,4 @@ class PostSet < ApplicationRecord include ValidationMethods include AccessMethods include PostMethods -end \ No newline at end of file +end diff --git a/app/models/user.rb b/app/models/user.rb old mode 100755 new mode 100644 index aea806b19..64d518a08 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -72,6 +72,7 @@ class User < ApplicationRecord before_create :promote_to_admin_if_first_user before_create :customize_new_user #after_create :notify_sock_puppets + after_create :create_user_status has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy has_many :posts, :foreign_key => "uploader_id" has_many :post_approvals, :dependent => :destroy @@ -84,7 +85,6 @@ class User < ApplicationRecord has_one :api_key has_one :dmail_filter - has_one :super_voter has_many :note_versions, :foreign_key => "updater_id" has_many :dmails, -> {order("dmails.id desc")}, :foreign_key => "owner_id" has_many :saved_searches @@ -381,6 +381,10 @@ class User < ApplicationRecord def level_class "user-#{level_string.downcase}" end + + def create_user_status + UserStatus.create!(user_id: id) + end end module EmailMethods diff --git a/app/models/user_status.rb b/app/models/user_status.rb new file mode 100644 index 000000000..2944a07b1 --- /dev/null +++ b/app/models/user_status.rb @@ -0,0 +1,2 @@ +class UserStatus < ApplicationRecord +end diff --git a/app/models/wiki_page_version.rb b/app/models/wiki_page_version.rb index 1f39a5467..eb0bdc4fb 100644 --- a/app/models/wiki_page_version.rb +++ b/app/models/wiki_page_version.rb @@ -2,6 +2,7 @@ class WikiPageVersion < ApplicationRecord array_attribute :other_names belongs_to :wiki_page belongs_to_updater + user_status_counter :wiki_edit_count, foreign_key: :updater_id belongs_to :artist, optional: true delegate :visible?, :to => :wiki_page diff --git a/db/migrate/20190602115848_add_user_statuses.rb b/db/migrate/20190602115848_add_user_statuses.rb new file mode 100644 index 000000000..1b1026074 --- /dev/null +++ b/db/migrate/20190602115848_add_user_statuses.rb @@ -0,0 +1,19 @@ +class AddUserStatuses < ActiveRecord::Migration[5.2] + def change + create_table :user_statuses do |t| + t.timestamps + t.integer :user_id, index: true, null: false + t.integer :post_count, null: false, default: 0 + t.integer :post_deleted_count, null: false, default: 0 + t.integer :post_update_count, null: false, default: 0 + t.integer :favorite_count, null: false, default: 0 + t.integer :wiki_edit_count, null: false, default: 0 + t.integer :note_count, null: false, default: 0 + t.integer :forum_post_count, null: false, default: 0 + t.integer :comment_count, null: false, default: 0 + t.integer :pool_count, null: false, default: 0 + t.integer :blip_count, null: false, default: 0 + t.integer :set_count, null: false, default: 0 + end + end +end diff --git a/db/structure.sql b/db/structure.sql index 6615ed762..23d803103 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -2515,6 +2515,48 @@ CREATE SEQUENCE public.user_password_reset_nonces_id_seq ALTER SEQUENCE public.user_password_reset_nonces_id_seq OWNED BY public.user_password_reset_nonces.id; +-- +-- Name: user_statuses; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_statuses ( + id bigint NOT NULL, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + user_id integer NOT NULL, + post_count integer DEFAULT 0 NOT NULL, + post_deleted_count integer DEFAULT 0 NOT NULL, + post_update_count integer DEFAULT 0 NOT NULL, + favorite_count integer DEFAULT 0 NOT NULL, + wiki_edit_count integer DEFAULT 0 NOT NULL, + note_count integer DEFAULT 0 NOT NULL, + forum_post_count integer DEFAULT 0 NOT NULL, + comment_count integer DEFAULT 0 NOT NULL, + pool_count integer DEFAULT 0 NOT NULL, + blip_count integer DEFAULT 0 NOT NULL, + set_count integer DEFAULT 0 NOT NULL +); + + +-- +-- Name: user_statuses_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.user_statuses_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: user_statuses_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.user_statuses_id_seq OWNED BY public.user_statuses.id; + + -- -- Name: users; Type: TABLE; Schema: public; Owner: - -- @@ -3097,6 +3139,13 @@ ALTER TABLE ONLY public.user_name_change_requests ALTER COLUMN id SET DEFAULT ne ALTER TABLE ONLY public.user_password_reset_nonces ALTER COLUMN id SET DEFAULT nextval('public.user_password_reset_nonces_id_seq'::regclass); +-- +-- Name: user_statuses id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_statuses ALTER COLUMN id SET DEFAULT nextval('public.user_statuses_id_seq'::regclass); + + -- -- Name: users id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3638,6 +3687,14 @@ ALTER TABLE ONLY public.user_password_reset_nonces ADD CONSTRAINT user_password_reset_nonces_pkey PRIMARY KEY (id); +-- +-- Name: user_statuses user_statuses_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_statuses + ADD CONSTRAINT user_statuses_pkey PRIMARY KEY (id); + + -- -- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4698,6 +4755,13 @@ CREATE INDEX index_user_name_change_requests_on_original_name ON public.user_nam CREATE INDEX index_user_name_change_requests_on_user_id ON public.user_name_change_requests USING btree (user_id); +-- +-- Name: index_user_statuses_on_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_user_statuses_on_user_id ON public.user_statuses USING btree (user_id); + + -- -- Name: index_users_on_email; Type: INDEX; Schema: public; Owner: - -- @@ -5057,6 +5121,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20190428132152'), ('20190430120155'), ('20190510184237'), -('20190510184245'); +('20190510184245'), +('20190602115848');