diff --git a/backend/app/controllers/tag_descriptions_controller.rb b/backend/app/controllers/tag_descriptions_controller.rb index e69de29..de2685d 100644 --- a/backend/app/controllers/tag_descriptions_controller.rb +++ b/backend/app/controllers/tag_descriptions_controller.rb @@ -0,0 +1,74 @@ +class TagDescriptionsController < ApplicationController + def show + description = TagDescription.find_by(tag_id: params[:id], language_code: 'ja') + return head :not_found unless description + + render json: representation(description) + end + + def show_by_title + tag_name = TagName.find_by(language_code: 'ja', name: params[:name].to_s.strip) + description = tag_name&.tag && TagDescription.find_by(tag: tag_name.tag, language_code: 'ja') + return head :not_found unless description + + render json: representation(description) + end + + def create + return head :unauthorized unless current_user + return head :forbidden unless current_user.gte_member? + + body = params[:body].to_s + return render_unprocessable_entity('本文は必須です.', field: :body) if body.blank? + + tag = Tag.find_by(id: params[:id]) + return head :not_found unless tag + + if TagDescription.exists?(tag:, language_code: 'ja') + return render_unprocessable_entity('説明はすでに存在します.') + end + + TagDescriptionOperation.create!(tag:, body:, created_by_user: current_user) + description = TagDescription.find_by!(tag:, language_code: 'ja') + + render json: representation(description), status: :created + rescue ActiveRecord::RecordInvalid => e + render_validation_error e.record + rescue ActiveRecord::RecordNotUnique + render_record_not_unique + end + + def update + return head :unauthorized unless current_user + return head :forbidden unless current_user.gte_member? + + body = params[:body].to_s + return render_unprocessable_entity('本文は必須です.', field: :body) if body.blank? + + description = TagDescription.find_by(tag_id: params[:id], language_code: 'ja') + return head :not_found unless description + + page = WikiPage.find(description.id) + TagDescriptionOperation.update!( + description:, page:, body:, updated_by_user: current_user) + description.reload + + render json: representation(description) + rescue ActiveRecord::RecordInvalid => e + render_validation_error e.record + end + + private + + def representation description + description.as_json(only: [ + :tag_id, + :language_code, + :body, + :version_no, + :created_by_user_id, + :updated_by_user_id, + :created_at, + :updated_at]) + end +end diff --git a/backend/app/services/tag_description_operation.rb b/backend/app/services/tag_description_operation.rb new file mode 100644 index 0000000..342cefb --- /dev/null +++ b/backend/app/services/tag_description_operation.rb @@ -0,0 +1,51 @@ +class TagDescriptionOperation + LANGUAGE_CODE = 'ja' + + def self.create!(tag:, body:, created_by_user:, message: nil) + ApplicationRecord.transaction do + tag.lock! + raise ActiveRecord::RecordNotUnique if TagDescription.exists?( + tag_id: tag.id, language_code: LANGUAGE_CODE) + + page = Wiki::Commit.create_legacy_content!( + tag_name: tag.tag_name(LANGUAGE_CODE), body:, created_by_user:, message:) + revision = page.wiki_revisions.order(id: :desc).first + record_version!(tag:, revision:, body:, user: created_by_user, + description: nil) + page + end + end + + def self.update!(description:, page:, body:, updated_by_user:, message: nil, + base_revision_id: nil) + ApplicationRecord.transaction do + description&.lock! + page.lock! + revision = Wiki::Commit.legacy_content!( + page:, body:, created_user: updated_by_user, message:, + base_revision_id:) + record_version!(tag: page.tag_name.tag, revision:, body: revision.body, + user: updated_by_user, description:) + description || TagDescription.find_by!( + tag_id: page.tag_name.tag_id, language_code: LANGUAGE_CODE) + end + end + + def self.record_version! tag:, revision:, body:, user:, description: + version_no = description ? description.version_no + 1 : 1 + TagDescriptionVersion.create!( + id: revision.id, tag_id: tag.id, language_code: LANGUAGE_CODE, + version_no:, event_type: description ? 'update' : 'create', body:, + created_by_user_id: user.id, created_at: revision.created_at) + if description + description.update!(body:, version_no:, updated_by_user_id: user.id) + else + TagDescription.create!( + id: revision.wiki_page_id, tag_id: tag.id, + language_code: LANGUAGE_CODE, version_no:, body:, + created_by_user_id: user.id, updated_by_user_id: user.id) + end + end + + private_class_method :record_version! +end diff --git a/backend/app/services/wiki/commit.rb b/backend/app/services/wiki/commit.rb index 14afa7b..80913f1 100644 --- a/backend/app/services/wiki/commit.rb +++ b/backend/app/services/wiki/commit.rb @@ -8,6 +8,15 @@ module Wiki end def self.create_content! tag_name:, body:, created_by_user:, message: nil + if tag_name.tag && tag_name.language_code == 'ja' + return TagDescriptionOperation.create!( + tag: tag_name.tag, body:, created_by_user:, message:) + end + + create_legacy_content!(tag_name:, body:, created_by_user:, message:) + end + + def self.create_legacy_content! tag_name:, body:, created_by_user:, message: nil normalised = normalise_body(body) page = WikiPage.new(tag_name:, @@ -33,6 +42,20 @@ module Wiki end def self.content! page:, body:, created_user:, message: nil, base_revision_id: nil + tag = page.tag_name.tag + description = tag && page.tag_name.language_code == 'ja' && + TagDescription.find_by(tag_id: tag.id, language_code: 'ja') + if tag && page.tag_name.language_code == 'ja' + return TagDescriptionOperation.update!( + description:, page:, body:, updated_by_user: created_user, + message:, base_revision_id:) + end + + legacy_content!(page:, body:, created_user:, message:, base_revision_id:) + end + + def self.legacy_content! page:, body:, created_user:, message: nil, + base_revision_id: nil new(page:, created_user:).content!(body:, message:, base_revision_id:) end @@ -93,8 +116,6 @@ module Wiki { wiki_revision_id: rev.id, wiki_line_id: line_id, position: pos } end WikiRevisionLine.insert_all!(rows) if rows.any? - record_description!(rev, normalised) - rev end end @@ -110,26 +131,6 @@ module Wiki private - def record_description! revision, body - tag = @page.tag_name.tag - return unless tag && @page.tag_name.language_code == 'ja' - - tag.lock! - description = TagDescription.lock.find_by(tag_id: tag.id, language_code: 'ja') - version_no = description ? description.version_no + 1 : 1 - TagDescriptionVersion.create!( - id: revision.id, tag_id: tag.id, language_code: 'ja', version_no:, - event_type: description ? 'update' : 'create', body:, - created_by_user_id: @created_user.id, created_at: revision.created_at) - if description - description.update!(body:, version_no:, updated_by_user_id: @created_user.id) - else - TagDescription.create!( - id: @page.id, tag_id: tag.id, language_code: 'ja', version_no:, body:, - created_by_user_id: @created_user.id, updated_by_user_id: @created_user.id) - end - end - def split_lines(body) = body.split("\n") def upsert_lines! lines, line_shas diff --git a/backend/config/routes.rb b/backend/config/routes.rb index e109460..c6664bc 100644 --- a/backend/config/routes.rb +++ b/backend/config/routes.rb @@ -1,4 +1,12 @@ Rails.application.routes.draw do + get 'tags/name/:name/description', to: 'tag_descriptions#show_by_title' + + scope 'tags/:id/description', controller: :tag_descriptions do + get '', action: :show + post '', action: :create + put '', action: :update + end + resources :nico_tags, path: 'tags/nico', only: [:index, :show, :update] scope 'tags/:parent_id/children', controller: :tag_children do