From a74696fc4352309498b0adde8a79cf2b2f2ccd61 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Wed, 4 Mar 2026 01:33:33 +0900 Subject: [PATCH] #247 --- .../app/controllers/deerjikists_controller.rb | 17 +++++++++++++++ backend/app/controllers/tags_controller.rb | 21 +++++++++++++++++++ backend/app/models/deerjikist.rb | 21 +++++++++++++++++++ backend/app/models/tag.rb | 9 ++++++++ .../app/representations/deerjikist_repr.rb | 16 ++++++++++++++ .../{WikiPageRepr.rb => wiki_page_repr.rb} | 0 backend/config/routes.rb | 18 +++++++++++++++- .../20260303122700_create_deerjikists.rb | 10 +++++++++ backend/db/schema.rb | 11 +++++++++- 9 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 backend/app/controllers/deerjikists_controller.rb create mode 100644 backend/app/models/deerjikist.rb create mode 100644 backend/app/representations/deerjikist_repr.rb rename backend/app/representations/{WikiPageRepr.rb => wiki_page_repr.rb} (100%) create mode 100644 backend/db/migrate/20260303122700_create_deerjikists.rb diff --git a/backend/app/controllers/deerjikists_controller.rb b/backend/app/controllers/deerjikists_controller.rb new file mode 100644 index 0000000..795edec --- /dev/null +++ b/backend/app/controllers/deerjikists_controller.rb @@ -0,0 +1,17 @@ +class DeerjikistsController < ApplicationController + def show + platform = params[:platform].to_s.strip + code = params[:code].to_s.strip + return head :bad_request if platform.blank? || code.blank? + + deerjikist = Deerjikist + .joins(:tag) + .includes(:tag, tag: :tag_name) + .find_by(platform:, code:) + if deerjikist + render json: DeerjikistRepr.base(deerjikist) + else + head :not_found + end + end +end diff --git a/backend/app/controllers/tags_controller.rb b/backend/app/controllers/tags_controller.rb index c4d5b0d..b68c47e 100644 --- a/backend/app/controllers/tags_controller.rb +++ b/backend/app/controllers/tags_controller.rb @@ -86,6 +86,27 @@ class TagsController < ApplicationController end end + def deerjikists + tag = Tag.joins(:tag_name) + .includes(:tag_name, tag_name: :wiki_page) + .find_by(id: params[:id]) + return head :bad_request unless tag + + render json: DeerjikistRepr.many(tag.deerjikists) + end + + def deerjikists_by_name + name = params[:name].to_s.strip + return head :bad_request if name.blank? + + tag = Tag.joins(:tag_name) + .includes(:tag_name, tag_name: :wiki_page) + .find_by(tag_names: { name: }) + return head :not_found unless tag + + render json: DeerjikistRepr.many(tag.deerjikists) + end + def update return head :unauthorized unless current_user return head :forbidden unless current_user.member? diff --git a/backend/app/models/deerjikist.rb b/backend/app/models/deerjikist.rb new file mode 100644 index 0000000..8447ef4 --- /dev/null +++ b/backend/app/models/deerjikist.rb @@ -0,0 +1,21 @@ +class Deerjikist < ApplicationRecord + self.primary_key = :platform, :code + + belongs_to :tag + + validates :platform, presence: true + validates :code, presence: true + validates :tag_id, presence: true + + validate :tag_must_be_deerjikist + + enum :platform, nico: 'nico', youtube: 'youtube' + + private + + def tag_must_be_deerjikist + if tag && !(tag.deerjikist?) + errors.add :tag, 'タグはニジラー・カテゴリである必要があります.' + end + end +end diff --git a/backend/app/models/tag.rb b/backend/app/models/tag.rb index ce064a4..14555a7 100644 --- a/backend/app/models/tag.rb +++ b/backend/app/models/tag.rb @@ -24,6 +24,8 @@ class Tag < ApplicationRecord has_many :tag_similarities, dependent: :delete_all + has_many :deerjikists, dependent: :delete_all + belongs_to :tag_name delegate :wiki_page, to: :tag_name @@ -42,6 +44,7 @@ class Tag < ApplicationRecord validate :nico_tag_name_must_start_with_nico validate :tag_name_must_be_canonical + validate :category_must_be_deerjikist_with_deerjikists scope :nico_tags, -> { where(category: :nico) } @@ -149,4 +152,10 @@ class Tag < ApplicationRecord errors.add :tag_name, 'tag_names へは実体を示す必要があります.' end end + + def category_must_be_deerjikist_with_deerjikists + if !(deerjikist?) && deerjikists.exists? + errors.add :category, 'ニジラーと紐づいてゐるタグはニジラー・カテゴリである必要があります.' + end + end end diff --git a/backend/app/representations/deerjikist_repr.rb b/backend/app/representations/deerjikist_repr.rb new file mode 100644 index 0000000..fbb73c9 --- /dev/null +++ b/backend/app/representations/deerjikist_repr.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + + +module DeerjikistRepr + BASE = { only: [:platform, :code], include: { tag: TagRepr::BASE } }.freeze + + module_function + + def base deerjikist + deerjikist.as_json(BASE) + end + + def many deerjikists + deerjikists.map { |d| base(d) } + end +end diff --git a/backend/app/representations/WikiPageRepr.rb b/backend/app/representations/wiki_page_repr.rb similarity index 100% rename from backend/app/representations/WikiPageRepr.rb rename to backend/app/representations/wiki_page_repr.rb diff --git a/backend/config/routes.rb b/backend/config/routes.rb index 0a52bf9..f7052d2 100644 --- a/backend/config/routes.rb +++ b/backend/config/routes.rb @@ -9,7 +9,15 @@ Rails.application.routes.draw do resources :tags, only: [:index, :show, :update] do collection do get :autocomplete - get 'name/:name', action: :show_by_name + + scope :name do + get ':name/deerjikists', action: :deerjikists_by_name + get ':name', action: :show_by_name + end + end + + member do + get :deerjikists end end @@ -54,4 +62,12 @@ Rails.application.routes.draw do post 'code/renew', action: :renew end end + + resources :deerjikists, only: [] do + collection do + get ':platform/:code', action: :show + put ':platfrom/:code', action: :update + delete ':platform/:code', action: :destroy + end + end end diff --git a/backend/db/migrate/20260303122700_create_deerjikists.rb b/backend/db/migrate/20260303122700_create_deerjikists.rb new file mode 100644 index 0000000..a87a963 --- /dev/null +++ b/backend/db/migrate/20260303122700_create_deerjikists.rb @@ -0,0 +1,10 @@ +class CreateDeerjikists < ActiveRecord::Migration[8.0] + def change + create_table :deerjikists, primary_key: [:platform, :code] do |t| + t.string :platform, null: false, limit: 16 + t.string :code, null: false + t.references :tag, null: false + t.timestamps + end + end +end diff --git a/backend/db/schema.rb b/backend/db/schema.rb index 7a53c81..8077fac 100644 --- a/backend/db/schema.rb +++ b/backend/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2026_01_27_005300) do +ActiveRecord::Schema[8.0].define(version: 2026_03_03_122700) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -39,6 +39,15 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_27_005300) do t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end + create_table "deerjikists", primary_key: ["platform", "code"], charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "platform", limit: 16, null: false + t.string "code", null: false + t.bigint "tag_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["tag_id"], name: "index_deerjikists_on_tag_id" + end + create_table "ip_addresses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.binary "ip_address", limit: 16, null: false t.boolean "banned", default: false, null: false