diff --git a/app/models/artist.rb b/app/models/artist.rb index ef6e6e2f1..2a063dcd1 100644 --- a/app/models/artist.rb +++ b/app/models/artist.rb @@ -13,7 +13,7 @@ class Artist < ApplicationRecord normalize :other_names, :normalize_other_names array_attribute :other_names # XXX must come after `normalize :other_names` - validate :validate_tag_category + validate :validate_artist_name validates :name, tag_name: true, uniqueness: true before_save :update_tag_category @@ -23,8 +23,8 @@ class Artist < ApplicationRecord has_many :members, :class_name => "Artist", :foreign_key => "group_name", :primary_key => "name" has_many :urls, :dependent => :destroy, :class_name => "ArtistUrl", :autosave => true has_many :versions, -> {order("artist_versions.id ASC")}, :class_name => "ArtistVersion" - has_one :wiki_page, :foreign_key => "title", :primary_key => "name" - has_one :tag_alias, :foreign_key => "antecedent_name", :primary_key => "name" + has_one :wiki_page, -> { active }, foreign_key: "title", primary_key: "name" + has_one :tag_alias, -> { active }, foreign_key: "antecedent_name", primary_key: "name" belongs_to :tag, foreign_key: "name", primary_key: "name", default: -> { Tag.new(name: name, category: Tag.categories.artist) } scope :banned, -> { where(is_banned: true) } @@ -155,12 +155,16 @@ class Artist < ApplicationRecord end module TagMethods - def validate_tag_category - return unless !is_deleted? && name_changed? && tag.present? + def validate_artist_name + return unless !is_deleted? && name_changed? - if tag.category_name != "Artist" && !tag.empty? + if tag.present? && tag.category_name != "Artist" && !tag.empty? errors.add(:name, "'#{name}' is a #{tag.category_name.downcase} tag; artist entries can only be created for artist tags") end + + if tag_alias.present? + errors.add(:name, "'#{name}' is aliased to '#{tag_alias.consequent_name}'") + end end def update_tag_category diff --git a/script/fixes/098_fix_aliased_artists.rb b/script/fixes/098_fix_aliased_artists.rb new file mode 100755 index 000000000..f383a9daf --- /dev/null +++ b/script/fixes/098_fix_aliased_artists.rb @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby + +require_relative "base" + +# Fix artist entries where the tag was aliased but the URLs weren't moved to +# the new artist entry. +with_confirmation do + CurrentUser.scoped(User.system, "127.0.0.1") do + aliased_artists = Artist.joins(:tag_alias).where.associated(:urls).distinct + + aliased_artists.each do |artist| + next if artist.tag.category_name != "Artist" + next if artist.tag_alias.consequent_tag.category_name != "Artist" + + old_name = artist.name + new_name = artist.tag_alias.consequent_name + + artist.update_attribute(:is_deleted, false) # undelete first so the tag move works + TagMover.new(old_name, new_name).move_artist! + added_urls = (artist.urls - Artist.find_by_name(new_name).urls).map(&:url) + + puts({ + old_name: old_name, + new_name: new_name, + added_urls: added_urls, + }.to_json) + end + end +end diff --git a/test/unit/artist_test.rb b/test/unit/artist_test.rb index 398667aa9..91a528f05 100644 --- a/test/unit/artist_test.rb +++ b/test/unit/artist_test.rb @@ -517,6 +517,14 @@ class ArtistTest < ActiveSupport::TestCase assert(artist.invalid?) assert_match(/'touhou' is a copyright tag/, artist.errors.full_messages.join) end + + should "not allow creating artist entries for aliased tags" do + tag_alias = create(:tag_alias, antecedent_name: "foo", consequent_name: "bar") + artist = build(:artist, name: "foo") + + assert_equal(true, artist.invalid?) + assert_match(/'foo' is aliased to 'bar'/, artist.errors.full_messages.join) + end end context "when renaming" do