tags: track tag histories.
Track the history of the tag `category` and `is_deprecated` fields in the `tag_versions` table. Adds generic Versionable and VersionFor concerns that encapsulate most of the history tracking logic. These concerns are designed to make it easy to add history to any model. There are a couple notable differences between tag versions and other versions: * There is no 1 hour edit merge window. All changes to the `category` and `is_deprecated` fields produce a new version in the tag history. * New versions aren't created when a tag is created. Versions are only created when a tag is edited for the first time. The tag's initial version isn't created until *after* the tag is edited for the first time. For example, if you change the category of a tag that was last updated 10 years ago, that will create an initial version of the tag backdated to 10 years ago, plus a new version for your edit. This is for a few reasons: * So that we don't have to create new tag versions every time a new tag is created. This would be wasteful because most tags never have their category or deprecation status change. * So that if you make a typo tag, your name isn't recorded in the tag's history forever. * So that we can create new tags in various places without having to know who created the tag (which may be unknown if the current user isn't set). * Because we don't know the full history of most tags, so we have to deal with incomplete histories anyway. This has a few important consequences: * Most tags won't have any tag versions. They only gain tag versions if they're edited. * You can't track /tag_versions to see newly created tags. It only shows changes to already existing tags. * Tag version IDs won't be in strict chronological order. Higher IDs may have created_at timestamps before lower IDs. For example, if you change the category of a tag that is 10 years old, that will create an initial version with a high ID, but with a created_at timestamp dated to 10 years ago. Fixes #4402: Track tag category changes
This commit is contained in:
@@ -187,7 +187,7 @@ class Artist < ApplicationRecord
|
||||
return unless !is_deleted? && name_changed? && tag.present?
|
||||
|
||||
if tag.category_name != "Artist" && tag.empty?
|
||||
tag.update!(category: Tag.categories.artist)
|
||||
tag.update!(category: Tag.categories.artist, updater: CurrentUser.user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Tag < ApplicationRecord
|
||||
include Versionable
|
||||
|
||||
ABBREVIATION_REGEXP = /([a-z0-9])[a-z0-9']*($|[^a-z0-9']+)/
|
||||
|
||||
# Tags that are permitted to have unbalanced parentheses, as a special exception to the normal rule that parentheses in tags must balanced.
|
||||
PERMITTED_UNBALANCED_TAGS = %w[:) :( ;) ;( >:) >:(]
|
||||
|
||||
attr_accessor :updater
|
||||
|
||||
has_one :wiki_page, :foreign_key => "title", :primary_key => "name"
|
||||
has_one :artist, :foreign_key => "name", :primary_key => "name"
|
||||
has_one :antecedent_alias, -> {active}, :class_name => "TagAlias", :foreign_key => "antecedent_name", :primary_key => "name"
|
||||
@@ -25,6 +29,8 @@ class Tag < ApplicationRecord
|
||||
after_save :update_category_cache, if: :saved_change_to_category?
|
||||
after_save :update_category_post_counts, if: :saved_change_to_category?
|
||||
|
||||
versionable :name, :category, :is_deprecated, merge_window: nil, delay_first_version: true
|
||||
|
||||
scope :empty, -> { where("tags.post_count <= 0") }
|
||||
scope :nonempty, -> { where("tags.post_count > 0") }
|
||||
scope :deprecated, -> { where(is_deprecated: true) }
|
||||
@@ -194,10 +200,11 @@ class Tag < ApplicationRecord
|
||||
end
|
||||
|
||||
def find_or_create_by_name(name, category: nil, current_user: nil)
|
||||
tag = find_or_create_by(name: normalize_name(name))
|
||||
cat_id = categories.value_for(category)
|
||||
tag = create_with(category: cat_id).find_or_create_by(name: normalize_name(name))
|
||||
|
||||
if category.present? && current_user.present? && Pundit.policy!(current_user, tag).can_change_category?
|
||||
tag.update(category: categories.value_for(category))
|
||||
if category.present? && current_user.present? && cat_id != tag.category && Pundit.policy!(current_user, tag).can_change_category?
|
||||
tag.update(category: cat_id, updater: current_user)
|
||||
end
|
||||
|
||||
tag
|
||||
|
||||
7
app/models/tag_version.rb
Normal file
7
app/models/tag_version.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagVersion < ApplicationRecord
|
||||
include VersionFor
|
||||
|
||||
version_for :tag
|
||||
end
|
||||
Reference in New Issue
Block a user