| @@ -1,9 +1,13 @@ | |||
| class NicoTagsController < ApplicationController | |||
| TAG_JSON = { only: [:id, :category, :post_count], methods: [:name, :has_wiki] }.freeze | |||
| def index | |||
| limit = (params[:limit] || 20).to_i | |||
| cursor = params[:cursor].presence | |||
| q = Tag.nico_tags.includes(:linked_tags).order(updated_at: :desc) | |||
| q = Tag.nico_tags | |||
| .includes(:tag_name, linked_tags: :tag_name) | |||
| .order(updated_at: :desc) | |||
| q = q.where('tags.updated_at < ?', Time.iso8601(cursor)) if cursor | |||
| tags = q.limit(limit + 1) | |||
| @@ -15,7 +19,9 @@ class NicoTagsController < ApplicationController | |||
| end | |||
| render json: { tags: tags.map { |tag| | |||
| tag.as_json(include: :linked_tags) | |||
| tag.as_json(TAG_JSON).merge(linked_tags: tag.linked_tags.map { |lt| | |||
| lt.as_json(TAG_JSON) | |||
| }) | |||
| }, next_cursor: } | |||
| end | |||
| @@ -30,12 +36,11 @@ class NicoTagsController < ApplicationController | |||
| linked_tag_names = params[:tags].to_s.split(' ') | |||
| linked_tags = Tag.normalise_tags(linked_tag_names, with_tagme: false) | |||
| return head :bad_request if linked_tags.filter { |t| t.category == 'nico' }.present? | |||
| return head :bad_request if linked_tags.any? { |t| t.category == 'nico' } | |||
| tag.linked_tags = linked_tags | |||
| tag.updated_at = Time.now | |||
| tag.save! | |||
| render json: tag.linked_tags, status: :ok | |||
| render json: tag.linked_tags.map { |t| t.as_json(TAG_JSON) }, status: :ok | |||
| end | |||
| end | |||
| @@ -158,7 +158,7 @@ class PostsController < ApplicationController | |||
| pts.each do |pt| | |||
| events << Event.new( | |||
| post: pt.post, | |||
| tag: pt.tag, | |||
| tag: pt.tag.as_json(only: [:id, :category], methods: [:name]), | |||
| user: pt.created_user && { id: pt.created_user.id, name: pt.created_user.name }, | |||
| change_type: 'add', | |||
| timestamp: pt.created_at) | |||
| @@ -166,7 +166,7 @@ class PostsController < ApplicationController | |||
| if pt.discarded_at | |||
| events << Event.new( | |||
| post: pt.post, | |||
| tag: pt.tag, | |||
| tag: pt.tag.as_json(only: [:id, :category], methods: [:name]), | |||
| user: pt.deleted_user && { id: pt.deleted_user.id, name: pt.deleted_user.name }, | |||
| change_type: 'remove', | |||
| timestamp: pt.discarded_at) | |||
| @@ -9,7 +9,7 @@ class TagsController < ApplicationController | |||
| Tag.all | |||
| end | |||
| render json: tags.includes(:tag_name) | |||
| render json: tags.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki]) | |||
| end | |||
| def autocomplete | |||
| @@ -21,12 +21,12 @@ class TagsController < ApplicationController | |||
| 'nico', "nico:#{ q }%", "#{ q }%") | |||
| .order(Arel.sql('post_count DESC, tag_names.name ASC')) | |||
| .limit(20)) | |||
| render json: tags | |||
| render json: tags.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki]) | |||
| end | |||
| def show | |||
| tag = Tag.find_by(id: params[:id]) | |||
| render json: tag | |||
| render json: tag.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki]) | |||
| end | |||
| def show_by_name | |||
| @@ -35,7 +35,7 @@ class TagsController < ApplicationController | |||
| tag = Tag.joins(:tag_name).includes(:tag_name).find_by(tag_names: { name: }) | |||
| if tag | |||
| render json: tag | |||
| render json: tag.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki]) | |||
| else | |||
| head :not_found | |||
| end | |||
| @@ -2,11 +2,13 @@ class WikiPagesController < ApplicationController | |||
| rescue_from Wiki::Commit::Conflict, with: :render_wiki_conflict | |||
| def index | |||
| render json: WikiPage.all | |||
| pages = WikiPage.all | |||
| render json: pages.as_json(methods: [:title]) | |||
| end | |||
| def show | |||
| render_wiki_page_or_404 WikiPage.includes(:tag_name).find_by(id: params[:id]) | |||
| page = WikiPage.find_by(id: params[:id]) | |||
| render_wiki_page_or_404 page | |||
| end | |||
| def show_by_title | |||
| @@ -86,7 +88,7 @@ class WikiPagesController < ApplicationController | |||
| message = params[:message].presence | |||
| Wiki::Commit.content!(page:, body:, created_user: current_user, message:) | |||
| render json: page, status: :created | |||
| render json: page.as_json(methods: [:title]), status: :created | |||
| else | |||
| render json: { errors: page.errors.full_messages }, | |||
| status: :unprocessable_entity | |||
| @@ -127,7 +129,7 @@ class WikiPagesController < ApplicationController | |||
| q = q.where('tag_names.name LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%") | |||
| end | |||
| render json: q.limit(20) | |||
| render json: q.limit(20).as_json(methods: [:title]) | |||
| end | |||
| def changes | |||
| @@ -167,12 +169,14 @@ class WikiPagesController < ApplicationController | |||
| pred = page.pred_revision_id(revision_id) | |||
| succ = page.succ_revision_id(revision_id) | |||
| return render json: page.as_json.merge(body:, revision_id:, pred:, succ:) | |||
| return render json: page.as_json(methods: [:title]) | |||
| .merge(body:, revision_id:, pred:, succ:) | |||
| end | |||
| rev = page.current_revision | |||
| unless rev | |||
| return render json: page.as_json.merge(body: nil, revision_id: nil, pred: nil, succ: nil) | |||
| return render json: page.as_json(methods: [:title]) | |||
| .merge(body: nil, revision_id: nil, pred: nil, succ: nil) | |||
| end | |||
| if rev.redirect? | |||
| @@ -186,7 +190,7 @@ class WikiPagesController < ApplicationController | |||
| pred = page.pred_revision_id(revision_id) | |||
| succ = page.succ_revision_id(revision_id) | |||
| render json: page.as_json.merge(body:, revision_id:, pred:, succ:) | |||
| render json: page.as_json(methods: [:title]).merge(body:, revision_id:, pred:, succ:) | |||
| end | |||
| def render_wiki_conflict err | |||
| @@ -22,7 +22,7 @@ class Tag < ApplicationRecord | |||
| has_many :parents, through: :reversed_tag_implications, source: :parent_tag | |||
| belongs_to :tag_name | |||
| delegate :name, to: :tag_name | |||
| delegate :name, to: :tag_name, allow_nil: true | |||
| validates :tag_name, presence: true | |||
| enum :category, { deerjikist: 'deerjikist', | |||
| @@ -51,6 +51,10 @@ class Tag < ApplicationRecord | |||
| (self.tag_name ||= build_tag_name).name = val | |||
| end | |||
| def has_wiki | |||
| tag_name&.wiki_page.present? | |||
| end | |||
| def self.tagme | |||
| @tagme ||= find_or_create_by_tag_name!('タグ希望', category: 'meta') | |||
| end | |||
| @@ -107,8 +111,9 @@ class Tag < ApplicationRecord | |||
| private | |||
| def nico_tag_name_must_start_with_nico | |||
| if ((category == 'nico' && !(name.start_with?('nico:'))) || | |||
| (category != 'nico' && name.start_with?('nico:'))) | |||
| n = name.to_s | |||
| if ((category == 'nico' && !(n.start_with?('nico:'))) || | |||
| (category != 'nico' && n.start_with?('nico:'))) | |||
| errors.add :name, 'ニコニコ・タグの命名規則に反してゐます.' | |||
| end | |||
| end | |||
| @@ -0,0 +1,9 @@ | |||
| class DropTagAliases < ActiveRecord::Migration[7.0] | |||
| def up | |||
| drop_table :tag_aliases | |||
| end | |||
| def down | |||
| raise ActiveRecord::IrreversibleMigration, '戻せません.' | |||
| end | |||
| end | |||
| @@ -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_11_204400) do | |||
| ActiveRecord::Schema[8.0].define(version: 2026_01_12_111800) 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 | |||
| @@ -106,14 +106,6 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_11_204400) do | |||
| t.index ["user_id"], name: "index_settings_on_user_id" | |||
| end | |||
| create_table "tag_aliases", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | |||
| t.bigint "tag_id", null: false | |||
| t.string "name", null: false | |||
| t.datetime "created_at", null: false | |||
| t.datetime "updated_at", null: false | |||
| t.index ["tag_id"], name: "index_tag_aliases_on_tag_id" | |||
| end | |||
| create_table "tag_implications", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | |||
| t.bigint "tag_id", null: false | |||
| t.bigint "parent_tag_id", null: false | |||
| @@ -239,7 +231,6 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_11_204400) do | |||
| add_foreign_key "posts", "posts", column: "parent_id" | |||
| add_foreign_key "posts", "users", column: "uploaded_user_id" | |||
| add_foreign_key "settings", "users" | |||
| add_foreign_key "tag_aliases", "tags" | |||
| add_foreign_key "tag_implications", "tags" | |||
| add_foreign_key "tag_implications", "tags", column: "parent_tag_id" | |||
| add_foreign_key "tag_names", "tag_names", column: "canonical_id" | |||