Author | SHA1 | Message | Date |
---|---|---|---|
|
915ebcc7cf | #64 バックエンドぼちぼち | 4 days ago |
@@ -78,6 +78,7 @@ class PostsController < ApplicationController | |||||
if post.save | if post.save | ||||
post.resized_thumbnail! | post.resized_thumbnail! | ||||
post.tags = Tag.normalise_tags(tag_names) | post.tags = Tag.normalise_tags(tag_names) | ||||
post.tags = Tag.expand_parent_tags(post.tags) | |||||
render json: post.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }), | render json: post.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }), | ||||
status: :created | status: :created | ||||
else | else | ||||
@@ -111,6 +112,7 @@ class PostsController < ApplicationController | |||||
post = Post.find(params[:id].to_i) | post = Post.find(params[:id].to_i) | ||||
tags = post.tags.where(category: 'nico').to_a + Tag.normalise_tags(tag_names) | tags = post.tags.where(category: 'nico').to_a + Tag.normalise_tags(tag_names) | ||||
tags = Tag.expand_parent_tags(tags) | |||||
if post.update(title:, tags:, original_created_from:, original_created_before:) | if post.update(title:, tags:, original_created_from:, original_created_before:) | ||||
render json: post.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }), | render json: post.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }), | ||||
status: :ok | status: :ok | ||||
@@ -11,6 +11,14 @@ class Tag < ApplicationRecord | |||||
dependent: :destroy | dependent: :destroy | ||||
has_many :linked_nico_tags, through: :reversed_nico_tag_relations, source: :nico_tag | has_many :linked_nico_tags, through: :reversed_nico_tag_relations, source: :nico_tag | ||||
has_many :tag_implications, foreign_key: :parent_tag_id, dependent: :destroy | |||||
has_many :children, through: :tag_implications, source: :tag | |||||
has_many :reversed_tag_implications, class_name: 'TagImplication', | |||||
foreign_key: :tag_id, | |||||
dependent: :destroy | |||||
has_many :parents, through: :reversed_tag_implications, source: :parent_tag | |||||
enum :category, { deerjikist: 'deerjikist', | enum :category, { deerjikist: 'deerjikist', | ||||
meme: 'meme', | meme: 'meme', | ||||
character: 'character', | character: 'character', | ||||
@@ -61,6 +69,29 @@ class Tag < ApplicationRecord | |||||
tags.uniq | tags.uniq | ||||
end | end | ||||
def self.expand_parent_tags tags | |||||
return [] if tags.blank? | |||||
seen = Set.new | |||||
result = [] | |||||
stack = tags.compact.dup | |||||
until stack.empty? | |||||
tag = stack.pop | |||||
next unless tag | |||||
tag.parents.each do |parent| | |||||
next if seen.include?(parent.id) | |||||
seen << parent.id | |||||
result << parent | |||||
stack << parent | |||||
end | |||||
end | |||||
(result + tags).uniq { |t| t.id } | |||||
end | |||||
private | private | ||||
def nico_tag_name_must_start_with_nico | def nico_tag_name_must_start_with_nico | ||||
@@ -0,0 +1,17 @@ | |||||
class TagImplication < ApplicationRecord | |||||
belongs_to :tag, class_name: 'Tag' | |||||
belongs_to :parent_tag, class_name: 'Tag' | |||||
validates :tag_id, presence: true | |||||
validates :parent_tag_id, presence: true | |||||
validate :parent_tag_mustnt_be_itself | |||||
private | |||||
def parent_tag_mustnt_be_itself | |||||
if parent_tag == tag | |||||
errors.add :parent_tag_id, '親タグは子タグと同一であってはなりません.' | |||||
end | |||||
end | |||||
end |
@@ -0,0 +1,9 @@ | |||||
class CreateTagImplications < ActiveRecord::Migration[8.0] | |||||
def change | |||||
create_table :tag_implications do |t| | |||||
t.references :tag, null: false, foreign_key: { to_table: :tags } | |||||
t.references :parent_tag, null: false, foreign_key: { to_table: :tags } | |||||
t.timestamps | |||||
end | |||||
end | |||||
end |
@@ -10,7 +10,7 @@ | |||||
# | # | ||||
# It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||
ActiveRecord::Schema[8.0].define(version: 2025_09_09_075500) do | |||||
ActiveRecord::Schema[8.0].define(version: 2025_10_09_222200) do | |||||
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | ||||
t.string "name", null: false | t.string "name", null: false | ||||
t.string "record_type", null: false | t.string "record_type", null: false | ||||
@@ -107,6 +107,15 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_09_075500) do | |||||
t.index ["tag_id"], name: "index_tag_aliases_on_tag_id" | t.index ["tag_id"], name: "index_tag_aliases_on_tag_id" | ||||
end | 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 | |||||
t.datetime "created_at", null: false | |||||
t.datetime "updated_at", null: false | |||||
t.index ["parent_tag_id"], name: "index_tag_implications_on_parent_tag_id" | |||||
t.index ["tag_id"], name: "index_tag_implications_on_tag_id" | |||||
end | |||||
create_table "tag_similarities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | create_table "tag_similarities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| | ||||
t.bigint "tag_id", null: false | t.bigint "tag_id", null: false | ||||
t.bigint "target_tag_id", null: false | t.bigint "target_tag_id", null: false | ||||
@@ -176,6 +185,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_09_075500) do | |||||
add_foreign_key "posts", "users", column: "uploaded_user_id" | add_foreign_key "posts", "users", column: "uploaded_user_id" | ||||
add_foreign_key "settings", "users" | add_foreign_key "settings", "users" | ||||
add_foreign_key "tag_aliases", "tags" | 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_similarities", "tags" | add_foreign_key "tag_similarities", "tags" | ||||
add_foreign_key "tag_similarities", "tags", column: "target_tag_id" | add_foreign_key "tag_similarities", "tags", column: "target_tag_id" | ||||
add_foreign_key "user_ips", "ip_addresses" | add_foreign_key "user_ips", "ip_addresses" | ||||