このコミットが含まれているのは:
2026-11-01 00:20:32 +09:00
コミット 74c5242828
22個のファイルの変更、202行の追加、232行の削除
+35 -49
ファイルの表示
@@ -409,52 +409,40 @@ class PostsController < ApplicationController
target = Locale.find_by(code:, deprecated_at: nil)
return head :not_found unless target
literals = params[:tags].to_s.split
references = tag_filter_references(literals)
names = literals.each_with_index.map do |literal, index|
reference = references&.[](index)
(reference && reference['negative'] == false) ? literal : literal.sub(/\Anot:/i, '')
end
internal = references ? {} : TagName.where(
language_code: source.language_code, name: names).pluck(:name, :tag_id).to_h
canonical = references ? {} : TagName.where(
language_code: source.language_code, primary_flg: true,
tag_id: internal.values).pluck(:tag_id, :name).to_h
external_names = names.map { canonical[internal[_1]] || _1 }
external = references ? {} : ExternalTag.where(
"CONCAT(platform, ':', name) IN (?)", external_names).pluck(
Arel.sql("CONCAT(platform, ':', name)"), :id).to_h
ids = references ? references.filter_map { _1['tag_id'] } : internal.values
translated = TagName.where(language_code: target.language_code,
primary_flg: true, tag_id: ids).pluck(:tag_id, :name).to_h
tokens = params[:tags].to_s.split
literals = PostTagSearch.literals(source, tokens.join(' '))
source_ids = PostTagSearch.references_for(source, literals)
ids = source_ids.values.flat_map(&:first).uniq
names = TagName.where(language_code: target.language_code,
primary_flg: true, tag_id: ids).pluck(:tag_id, :name).to_h
filters = literals.map do |literal|
internal, = source_ids.fetch(literal[:name])
name = internal.empty? ? literal[:name] : names[internal.first]
return head :unprocessable_entity unless name && internal.length <= 1
filters = literals.each_with_index.map do |literal, index|
name = names[index]
reference = if references
references[index].except('name')
else
matches = {}
matches['tag_id'] = internal[name] if internal[name]
external_id = external[external_names[index]]
matches['external_tag_id'] = external_id if external_id
matches.empty? ? { 'missing' => true } : matches
end
name = translated[reference['tag_id']] || name
negative = reference.fetch('negative', literal.downcase.start_with?('not:'))
prefix = negative ? literal[/\Anot:/i] || 'not:' : ''
reference.merge('name' => "#{ prefix }#{ name }", 'negative' => negative)
literal[:negative] ? "not:#{ name }" : name
end
render json: { references: filters }
translated = PostTagSearch.literals(target, filters.join(' '))
target_ids = PostTagSearch.references_for(target, translated)
literals.zip(translated).each do |literal, translation|
unless (source_ids.fetch(literal[:name]).map(&:sort) ==
target_ids.fetch(translation[:name]).map(&:sort))
return head :unprocessable_entity
end
end
index = 0
filters = tokens.map do |token|
next token if token.downcase == 'type:or'
value = filters[index]
index += 1
value
end
render json: { tags: filters.join(' ') }
end
private
def tag_filter_references literals
PostTagSearch.parse_references(params.to_unsafe_h, literals)
rescue ArgumentError, JSON::ParserError, TypeError
raise ActionController::BadRequest
end
def filtered_posts locale
tag_names = params[:tags].to_s.split
match_type = params[:match]
@@ -466,19 +454,17 @@ class PostsController < ApplicationController
end
def filter_posts_by_tags locale, tag_names, match_type
references = tag_filter_references(tag_names)
literals = PostTagSearch.literals(locale, tag_names.join(' '), references:)
literals = PostTagSearch.literals(locale, tag_names.join(' '))
return Post.all if literals.empty?
if match_type == 'any'
literals.reduce(Post.none) do |posts, literal|
posts.or(tag_literal_relation(locale, literal[:name], negative: literal[:negative],
reference: literal[:reference]))
posts.or(tag_literal_relation(locale, literal[:name], negative: literal[:negative]))
end
else
literals.reduce(Post.all) do |posts, literal|
ids = tagged_post_ids_for(locale, literal[:name], reference: literal[:reference])
ids = tagged_post_ids_for(locale, literal[:name])
if literal[:negative]
posts.where.not(id: ids)
else
@@ -488,8 +474,8 @@ class PostsController < ApplicationController
end
end
def tag_literal_relation locale, name, negative:, reference: nil
ids = tagged_post_ids_for(locale, name, reference:)
def tag_literal_relation locale, name, negative:
ids = tagged_post_ids_for(locale, name)
if negative
Post.where.not(id: ids)
else
@@ -497,8 +483,8 @@ class PostsController < ApplicationController
end
end
def tagged_post_ids_for locale, name, reference: nil
internal, external = PostTagSearch.references(locale, { name:, reference: })
def tagged_post_ids_for locale, name
internal, external = PostTagSearch.references(locale, { name: })
Post.where(id: PostTag.where(tag_id: Array(internal)).select(:post_id))
.or(Post.where(id: PostExternalTag.where(external_tag_id: Array(external))
.select(:post_id))).select(:id)