diff --git a/app/models/post.rb b/app/models/post.rb index d9b647d58..44d816833 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -29,7 +29,7 @@ class Post < ApplicationRecord validate :post_is_not_its_own_parent validate :uploader_is_not_limited, on: :create before_save :update_tag_post_counts - before_save :set_tag_counts + before_save :update_tag_category_counts before_create :autoban after_save :create_version after_save :update_parent_on_save @@ -323,22 +323,14 @@ class Post < ApplicationRecord end end - def set_tag_count(category, tagcount) - send("tag_count_#{category}=", tagcount) - end - - def inc_tag_count(category) - set_tag_count(category, send("tag_count_#{category}") + 1) - end - - def set_tag_counts - self.tag_count = 0 - TagCategory.categories.each {|x| set_tag_count(x, 0)} - categories = Tag.categories_for(tag_array, disable_caching: true) - categories.each_value do |category| - self.tag_count += 1 - inc_tag_count(TagCategory.reverse_mapping[category]) + # Update tag_count_general, tag_count_copyright, etc. + def update_tag_category_counts + TagCategory.categories.each do |category_name| + tag_count = tags.select { |t| t.category_name.downcase == category_name }.size + send("tag_count_#{category_name}=", tag_count) end + + self.tag_count = tag_array.size end def merge_old_changes diff --git a/app/models/tag.rb b/app/models/tag.rb index dae7bfae7..423aba1f7 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -129,16 +129,9 @@ class Tag < ApplicationRecord Tag.where(name: tag_name).pick(:category).to_i end - def categories_for(tag_names, options = {}) - if options[:disable_caching] - Array(tag_names).inject({}) do |hash, tag_name| - hash[tag_name] = select_category_for(tag_name) - hash - end - else - Cache.get_multi(Array(tag_names), "tc") do |tag| - Tag.select_category_for(tag) - end + def categories_for(tag_names) + Cache.get_multi(Array(tag_names), "tc") do |tag| + Tag.select_category_for(tag) end end end @@ -157,7 +150,7 @@ class Tag < ApplicationRecord def update_category_post_counts Post.with_timeout(30_000) do Post.raw_tag_match(name).find_each do |post| - post.set_tag_counts + post.update_tag_category_counts post.save! end end diff --git a/script/fixes/088_fix_post_tag_category_counts.rb b/script/fixes/088_fix_post_tag_category_counts.rb new file mode 100755 index 000000000..f1cc7f264 --- /dev/null +++ b/script/fixes/088_fix_post_tag_category_counts.rb @@ -0,0 +1,44 @@ +#!/usr/bin/env ruby + +require_relative "base" + +with_confirmation do + # Fix posts that have a tag_count_* column inconsistent with the true count. + posts = Post.find_by_sql(<<~SQL.squish) + UPDATE posts + SET + tag_count_general = true_tag_count_general, + tag_count_artist = true_tag_count_artist, + tag_count_copyright = true_tag_count_copyright, + tag_count_character = true_tag_count_character, + tag_count_meta = true_tag_count_meta, + tag_count = true_tag_count + FROM ( + SELECT + posts.id AS post_id, + COUNT(*) FILTER (WHERE category = 0) AS true_tag_count_general, + COUNT(*) FILTER (WHERE category = 1) AS true_tag_count_artist, + COUNT(*) FILTER (WHERE category = 3) AS true_tag_count_copyright, + COUNT(*) FILTER (WHERE category = 4) AS true_tag_count_character, + COUNT(*) FILTER (WHERE category = 5) AS true_tag_count_meta, + COUNT(*) AS true_tag_count + FROM + posts, + unnest(string_to_array(tag_string, ' ')) tag + JOIN tags ON tags.name = tag + GROUP BY posts.id + ) tag_category_counts + WHERE + posts.id = tag_category_counts.post_id AND ( + posts.tag_count_general != tag_category_counts.true_tag_count_general OR + posts.tag_count_artist != tag_category_counts.true_tag_count_artist OR + posts.tag_count_copyright != tag_category_counts.true_tag_count_copyright OR + posts.tag_count_character != tag_category_counts.true_tag_count_character OR + posts.tag_count_meta != tag_category_counts.true_tag_count_meta OR + posts.tag_count != tag_category_counts.true_tag_count + ) + RETURNING posts.* + SQL + + puts "Fixing #{posts.size} records" +end diff --git a/test/unit/post_version_test.rb b/test/unit/post_version_test.rb index d89664753..5545770bb 100644 --- a/test/unit/post_version_test.rb +++ b/test/unit/post_version_test.rb @@ -97,7 +97,7 @@ class PostVersionTest < ActiveSupport::TestCase end should "not create a version if updating the post fails" do - @post.stubs(:set_tag_counts).raises(NotImplementedError) + @post.stubs(:update_tag_category_counts).raises(NotImplementedError) assert_equal(2, @post.versions.size) assert_raise(NotImplementedError) { @post.update(rating: "s") }