From 60c8c63353bf702e9756f12bc59e6aef882277ea Mon Sep 17 00:00:00 2001 From: miteruzo Date: Thu, 12 Mar 2026 21:41:28 +0900 Subject: [PATCH] #281 --- .../app/controllers/wiki_pages_controller.rb | 2 +- backend/app/models/my_discard.rb | 20 +++++++++++++++++++ backend/app/models/tag.rb | 6 +++--- backend/app/models/tag_name.rb | 8 ++------ backend/app/models/wiki_page.rb | 2 +- backend/spec/requests/posts_spec.rb | 10 ++++++---- backend/spec/tasks/nico_sync_spec.rb | 4 ++-- 7 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 backend/app/models/my_discard.rb diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb index 749cf19..dc6c47f 100644 --- a/backend/app/controllers/wiki_pages_controller.rb +++ b/backend/app/controllers/wiki_pages_controller.rb @@ -90,7 +90,7 @@ class WikiPagesController < ApplicationController return head :unprocessable_entity if name.blank? || body.blank? - tag_name = TagName.find_or_create_by!(name:) + tag_name = TagName.find_undiscard_or_create_by!(name:) page = WikiPage.new(tag_name:, created_user: current_user, updated_user: current_user) if page.save message = params[:message].presence diff --git a/backend/app/models/my_discard.rb b/backend/app/models/my_discard.rb new file mode 100644 index 0000000..dc4a98d --- /dev/null +++ b/backend/app/models/my_discard.rb @@ -0,0 +1,20 @@ +module MyDiscard + extend ActiveSupport::Concern + + included { include Discard::Model } + + class_methods do + def find_undiscard_or_create_by! attrs, &block + record = with_discarded.find_by(attrs) + + if record&.discarded? + record.undiscard! + record.update_columns(created_at: record.reload.updated_at) + end + + record or create!(attrs, &block) + rescue ActiveRecord::RecordNotUnique + retry + end + end +end diff --git a/backend/app/models/tag.rb b/backend/app/models/tag.rb index 9f480cd..a8926c2 100644 --- a/backend/app/models/tag.rb +++ b/backend/app/models/tag.rb @@ -1,5 +1,5 @@ class Tag < ApplicationRecord - include Discard::Model + include MyDiscard class NicoTagNormalisationError < ArgumentError ; @@ -134,10 +134,10 @@ class Tag < ApplicationRecord end def self.find_or_create_by_tag_name! name, category: - tn = TagName.find_or_create_by!(name: name.to_s.strip) + tn = TagName.find_undiscard_or_create_by!(name: name.to_s.strip) tn = tn.canonical if tn.canonical_id? - Tag.find_or_create_by!(tag_name_id: tn.id) do |t| + Tag.find_undiscard_or_create_by!(tag_name_id: tn.id) do |t| t.category = category end rescue ActiveRecord::RecordNotUnique diff --git a/backend/app/models/tag_name.rb b/backend/app/models/tag_name.rb index c353d2f..b118300 100644 --- a/backend/app/models/tag_name.rb +++ b/backend/app/models/tag_name.rb @@ -1,5 +1,5 @@ class TagName < ApplicationRecord - include Discard::Model + include MyDiscard default_scope -> { kept } @@ -27,10 +27,6 @@ class TagName < ApplicationRecord private - def sanitise_name - self.name = TagNameSanitisationRule.sanitise(name) - end - def canonical_must_be_canonical if canonical&.canonical_id? errors.add :canonical, 'canonical は実体を示す必要があります.' @@ -50,7 +46,7 @@ class TagName < ApplicationRecord end def name_must_be_sanitised - if name != TagNameSanitisationRule.sanitise(name) + if name? && name != TagNameSanitisationRule.sanitise(name) errors.add :name, '名前に使用できない文字が含まれてゐます.' end end diff --git a/backend/app/models/wiki_page.rb b/backend/app/models/wiki_page.rb index b1d1b02..1573127 100644 --- a/backend/app/models/wiki_page.rb +++ b/backend/app/models/wiki_page.rb @@ -2,7 +2,7 @@ require 'set' class WikiPage < ApplicationRecord - include Discard::Model + include MyDiscard default_scope -> { kept } diff --git a/backend/spec/requests/posts_spec.rb b/backend/spec/requests/posts_spec.rb index b2f3e54..ee4fcc5 100644 --- a/backend/spec/requests/posts_spec.rb +++ b/backend/spec/requests/posts_spec.rb @@ -525,8 +525,9 @@ RSpec.describe 'Posts API', type: :request do context "when nico tag already exists in tags" do before do - Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), - category: :nico) + Tag.find_undiscard_or_create_by!( + tag_name: TagName.find_undiscard_or_create_by!(name: 'nico:nico_tag'), + category: :nico) end it 'return 400' do @@ -610,8 +611,9 @@ RSpec.describe 'Posts API', type: :request do context "when nico tag already exists in tags" do before do - Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), - category: :nico) + Tag.find_undiscard_or_create_by!( + tag_name: TagName.find_undiscard_or_create_by!(name: 'nico:nico_tag'), + category: :nico) end it 'return 400' do diff --git a/backend/spec/tasks/nico_sync_spec.rb b/backend/spec/tasks/nico_sync_spec.rb index daa243e..d4f0e09 100644 --- a/backend/spec/tasks/nico_sync_spec.rb +++ b/backend/spec/tasks/nico_sync_spec.rb @@ -8,8 +8,8 @@ RSpec.describe "nico:sync" do end def create_tag!(name, category:) - tn = TagName.find_or_create_by!(name: name.to_s.strip) - Tag.find_or_create_by!(tag_name_id: tn.id) { |t| t.category = category } + tn = TagName.find_undiscard_or_create_by!(name: name.to_s.strip) + Tag.find_undiscard_or_create_by!(tag_name_id: tn.id) { |t| t.category = category } end def link_nico_to_tag!(nico_tag, tag)