feat: タグ名を別管理に変更(#215) (#219)

Merge branch 'main' into feature/215

#215 ニコニコ同期テスト

#215 テスト・ケース追加

#215 テスト・ケース追加

#215 テスト・ケース追加

#215 テスト・ケース追加

Merge remote-tracking branch 'origin/main' into feature/215

Merge branch 'main' into feature/215

#215

#215

Merge remote-tracking branch 'origin/main' into feature/215

#215

Co-authored-by: miteruzo <miteruzo@naver.com>
Reviewed-on: #219
This commit was merged in pull request #219.
This commit is contained in:
2026-01-15 12:40:41 +09:00
parent 74141f2a84
commit fa2030f9a5
34 changed files with 1268 additions and 119 deletions
+22 -21
View File
@@ -1,7 +1,6 @@
class PostsController < ApplicationController
Event = Struct.new(:post, :tag, :user, :change_type, :timestamp, keyword_init: true)
# GET /posts
def index
page = (params[:page].presence || 1).to_i
limit = (params[:limit].presence || 20).to_i
@@ -18,7 +17,7 @@ class PostsController < ApplicationController
'posts.created_at)'
q =
filtered_posts
.preload(:tags)
.preload(tags: :tag_name)
.with_attached_thumbnail
.select("posts.*, #{ sort_sql } AS sort_ts")
.order(Arel.sql("#{ sort_sql } DESC"))
@@ -36,7 +35,8 @@ class PostsController < ApplicationController
end
render json: { posts: posts.map { |post|
post.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }).tap do |json|
post.as_json(include: { tags: { only: [:id, :category, :post_count],
methods: [:name] } }).tap do |json|
json['thumbnail'] =
if post.thumbnail.attached?
rails_storage_proxy_url(post.thumbnail, only_path: false)
@@ -48,19 +48,19 @@ class PostsController < ApplicationController
end
def random
post = filtered_posts.order('RAND()').first
post = filtered_posts.preload(tags: :tag_name).order('RAND()').first
return head :not_found unless post
viewed = current_user&.viewed?(post) || false
render json: (post
.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } })
.as_json(include: { tags: { only: [:id, :category, :post_count],
methods: [:name] } })
.merge(viewed:))
end
# GET /posts/1
def show
post = Post.includes(:tags).find(params[:id])
post = Post.includes(tags: :tag_name).find(params[:id])
return head :not_found unless post
viewed = current_user&.viewed?(post) || false
@@ -73,7 +73,6 @@ class PostsController < ApplicationController
render json:
end
# POST /posts
def create
return head :unauthorized unless current_user
return head :forbidden unless current_user.member?
@@ -96,7 +95,8 @@ class PostsController < ApplicationController
tags = Tag.normalise_tags(tag_names)
tags = Tag.expand_parent_tags(tags)
sync_post_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, :category, :post_count],
methods: [:name] } }),
status: :created
else
render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
@@ -117,7 +117,6 @@ class PostsController < ApplicationController
head :no_content
end
# PATCH/PUT /posts/1
def update
return head :unauthorized unless current_user
return head :forbidden unless current_user.member?
@@ -153,13 +152,13 @@ class PostsController < ApplicationController
pts = PostTag.with_discarded
pts = pts.where(post_id: id) if id.present?
pts = pts.includes(:post, :tag, :created_user, :deleted_user)
pts = pts.includes(:post, { tag: :tag_name }, :created_user, :deleted_user)
events = []
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)
@@ -167,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)
@@ -192,15 +191,15 @@ class PostsController < ApplicationController
end
def filter_posts_by_tags tag_names, match_type
posts = Post.joins(:tags)
posts = Post.joins(tags: :tag_name)
if match_type == 'any'
posts = posts.where(tags: { name: tag_names }).distinct
posts.where(tag_names: { name: tag_names }).distinct
else
tag_names.each do |tag|
posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag }))
end
posts.where(tag_names: { name: tag_names })
.group('posts.id')
.having('COUNT(DISTINCT tag_names.id) = ?', tag_names.uniq.size)
end
posts.distinct
end
def sync_post_tags! post, desired_tags
@@ -251,7 +250,8 @@ class PostsController < ApplicationController
return nil unless tag
if path.include?(tag_id)
return tag.as_json(only: [:id, :name, :category, :post_count]).merge(children: [])
return tag.as_json(only: [:id, :category, :post_count],
methods: [:name]).merge(children: [])
end
if memo.key?(tag_id)
@@ -263,7 +263,8 @@ class PostsController < ApplicationController
children = child_ids.filter_map { |cid| build_node.(cid, new_path) }
memo[tag_id] = tag.as_json(only: [:id, :name, :category, :post_count]).merge(children:)
memo[tag_id] = tag.as_json(only: [:id, :category, :post_count],
methods: [:name]).merge(children:)
end
root_ids.filter_map { |id| build_node.call(id, []) }