feat: 別名を検索に展開(#20) (#243)

#20

#20 テスト・ケースのみ追記

#20

Co-authored-by: miteruzo <miteruzo@naver.com>
Reviewed-on: #243
This commit was merged in pull request #243.
This commit is contained in:
2026-01-28 23:47:56 +09:00
parent effde89b07
commit 200d457d22
8 changed files with 168 additions and 39 deletions
@@ -97,6 +97,8 @@ class PostsController < ApplicationController
tags = Tag.normalise_tags(tag_names)
tags = Tag.expand_parent_tags(tags)
sync_post_tags!(post, tags)
post.reload
render json: post.as_json(include: { tags: { only: [:id, :category, :post_count],
methods: [:name, :has_wiki] } }),
status: :created
@@ -136,6 +138,8 @@ class PostsController < ApplicationController
Tag.normalise_tags(tag_names, with_tagme: false)
tags = Tag.expand_parent_tags(tags)
sync_post_tags!(post, tags)
post.reload
json = post.as_json
json['tags'] = build_tag_tree_for(post.tags)
render json:, status: :ok
@@ -197,6 +201,8 @@ class PostsController < ApplicationController
end
def filter_posts_by_tags tag_names, match_type
tag_names = TagName.canonicalise(tag_names)
posts = Post.joins(tags: :tag_name)
if match_type == 'any'
+37 -6
View File
@@ -16,12 +16,43 @@ class TagsController < ApplicationController
q = params[:q].to_s.strip
return render json: [] if q.blank?
tags = (Tag.joins(:tag_name).includes(:tag_name)
.where('(tags.category = ? AND tag_names.name LIKE ?) OR tag_names.name LIKE ?',
'nico', "nico:#{ q }%", "#{ q }%")
.order(Arel.sql('post_count DESC, tag_names.name ASC'))
.limit(20))
render json: tags.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki])
with_nico = !(params[:nico].to_s.strip.downcase.in?(['0', 'false', 'off', 'no']))
alias_rows =
TagName
.where('name LIKE ?', "#{ q }%")
.where.not(canonical_id: nil)
.pluck(:canonical_id, :name)
matched_alias_by_tag_name_id = { }
canonical_ids = []
alias_rows.each do |canonical_id, alias_name|
canonical_ids << canonical_id
matched_alias_by_tag_name_id[canonical_id] ||= alias_name
end
base = Tag.joins(:tag_name).includes(:tag_name)
canonical_hit =
base
.where(((with_nico ? '(tags.category = ? AND tag_names.name LIKE ?) OR ' : '') +
'tag_names.name LIKE ?'),
*(with_nico ? ['nico', "nico:#{ q }%"] : []), "#{ q }%")
tags =
if canonical_ids.present?
canonical_hit.or(base.where(tag_name_id: canonical_ids.uniq))
else
canonical_hit
end
tags = tags.order(Arel.sql('post_count DESC, tag_names.name')).limit(20).to_a
render json: tags.map { |tag|
tag.as_json(only: [:id, :category, :post_count], methods: [:name, :has_wiki])
.merge(matched_alias: matched_alias_by_tag_name_id[tag.tag_name_id])
}
end
def show