From 02451e4caa4e39700d93e65b4d10f856c9f91a8f Mon Sep 17 00:00:00 2001 From: miteruzo Date: Sun, 11 Oct 2026 01:32:46 +0900 Subject: [PATCH] #425 --- .../app/controllers/wiki_pages_controller.rb | 11 +++-- backend/app/services/tag_group_operation.rb | 45 +++++++++++++++++++ backend/spec/tasks/nico_export_spec.rb | 8 ++-- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb index d993dc3..a9245bf 100644 --- a/backend/app/controllers/wiki_pages_controller.rb +++ b/backend/app/controllers/wiki_pages_controller.rb @@ -11,7 +11,8 @@ class WikiPagesController < ApplicationController tag_groups = TagGroup.all if title.present? pattern = "%#{ ApplicationRecord.sanitize_sql_like(title) }%" - descriptions = descriptions.joins(tag: :tag_names) + descriptions = + descriptions.joins(tag: :tag_names) .where(tag_names: { language_code: 'ja', primary_flg: true }) .where('tag_names.name LIKE ?', pattern).limit(20) tag_groups = tag_groups.where( @@ -55,9 +56,11 @@ class WikiPagesController < ApplicationController return render_wiki_page_by_tag_description tag_description if tag_description - page = WikiPage.joins(:tag_name) - .includes(tag_name: :tag) - .find_by(tag_name: { name: title }) + page = + WikiPage + .joins(:tag_name) + .includes(tag_name: :tag) + .find_by(tag_name: { name: title }) render_wiki_page_or_404 page end diff --git a/backend/app/services/tag_group_operation.rb b/backend/app/services/tag_group_operation.rb index cd26c5c..905773b 100644 --- a/backend/app/services/tag_group_operation.rb +++ b/backend/app/services/tag_group_operation.rb @@ -27,6 +27,8 @@ class TagGroupOperation group.lock! old_name = group.name attributes = prepare!(group:, name:, description:, members:, placements:) + next [group, nil] if unchanged?(group, attributes) + group.update!(name: attributes.fetch(:name), description: attributes.fetch(:description), version_no: group.version_no + 1, @@ -66,6 +68,49 @@ class TagGroupOperation end private_class_method :prepare! + def self.unchanged?(group, attributes) + unless (group.name_in_database == attributes.fetch(:name) && + group.description_in_database == attributes.fetch(:description)) + return false + end + + members = TagGroupTag.where(tag_group_id: group.id).pluck(:tag_id) + .map { { 'tag_id' => _1 } } + members.concat(TagGroupGroup.where(tag_group_id: group.id) + .pluck(:child_tag_group_id).map { { 'tag_group_id' => _1 } }) + requested_members = attributes.fetch(:members).map do |member| + member.except('version_no') + end + return false unless members.to_set == requested_members.to_set + + rows = TagGroupPlacement.where(tag_group_id: group.id).order(:position) + .group_by(&:parent_position) + build = lambda do |parent_position| + rows.fetch(parent_position, []).map do |row| + node = if row.tag_id + { 'tag_id' => row.tag_id } + elsif row.child_tag_group_id + { 'tag_group_id' => row.child_tag_group_id } + else + { 'section_name' => row.section_name, 'description' => row.description } + end + node.merge('children' => build.call(row.position)) + end + end + build.call(nil) == comparable_placements(attributes.fetch(:placements)) + end + private_class_method :unchanged? + + def self.comparable_placements(nodes) + nodes.map do |node| + result = node.dup + result['description'] = node['description'] if node.key?('section_name') + result['children'] = comparable_placements(node.fetch('children')) + result + end + end + private_class_method :comparable_placements + def self.normalize_members(record, members) invalid!(record, :members, 'members は配列で指定してください.') unless members.is_a?(Array) diff --git a/backend/spec/tasks/nico_export_spec.rb b/backend/spec/tasks/nico_export_spec.rb index 0221f99..93aa770 100644 --- a/backend/spec/tasks/nico_export_spec.rb +++ b/backend/spec/tasks/nico_export_spec.rb @@ -18,8 +18,8 @@ RSpec.describe 'nico:export' do before do task.reenable - allow(ENV).to receive(:fetch).with('MYSQL_USER').and_return('mysql-user') - allow(ENV).to receive(:fetch).with('MYSQL_PASS').and_return('mysql-pass') + allow(ENV).to receive(:fetch).with('NIZIKA_NICO_MYSQL_USER').and_return('mysql-user') + allow(ENV).to receive(:fetch).with('NIZIKA_NICO_MYSQL_PASS').and_return('mysql-pass') allow(ENV).to receive(:fetch).with('NIZIKA_NICO_PATH').and_return('/srv/nizika-nico') end @@ -33,8 +33,8 @@ RSpec.describe 'nico:export' do expect(Open3).to receive(:capture3) do |env, *args, **kwargs| expect(env).to eq( { - 'MYSQL_USER' => 'mysql-user', - 'MYSQL_PASS' => 'mysql-pass', + 'NIZIKA_NICO_MYSQL_USER' => 'mysql-user', + 'NIZIKA_NICO_MYSQL_PASS' => 'mysql-pass', }, )