このコミットが含まれているのは:
@@ -31,9 +31,9 @@ class PostVersionsController < ApplicationController
|
||||
q = q.where('post_versions.post_id = ?', post_id) if post_id
|
||||
if external_tag_id || (tag_id && !(Tag.exists?(id: tag_id)))
|
||||
q = q.where('JSON_CONTAINS(post_versions.tags_json,' +
|
||||
"JSON_OBJECT('external_tag_id', #{ external_tag_id })) " +
|
||||
"JSON_OBJECT('external_tag_id', #{ external_tag_id || tag_id })) " +
|
||||
'OR JSON_CONTAINS(prev.tags_json,' +
|
||||
"JSON_OBJECT('external_tag_id', #{ external_tag_id }))")
|
||||
"JSON_OBJECT('external_tag_id', #{ external_tag_id || tag_id }))")
|
||||
elsif tag_id
|
||||
q = q.where("JSON_CONTAINS(post_versions.tags_json, JSON_OBJECT('tag_id', #{ tag_id })) " +
|
||||
"OR JSON_CONTAINS(prev.tags_json, JSON_OBJECT('tag_id', #{ tag_id }))")
|
||||
|
||||
@@ -49,7 +49,7 @@ class PostsController < ApplicationController
|
||||
filtered_posts
|
||||
.joins("LEFT JOIN (#{ pt_max_sql }) pt_max ON pt_max.post_id = posts.id")
|
||||
.reselect('posts.*', Arel.sql("#{ updated_at_all_sql } AS updated_at_all"))
|
||||
.preload(:uploaded_user, :parents, :children,
|
||||
.preload(:external_tags, :uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_name: :wiki_page }] }])
|
||||
.with_attached_thumbnail
|
||||
@@ -102,12 +102,14 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def random
|
||||
post = filtered_posts.preload(:uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_name: :wiki_page }] }])
|
||||
.with_attached_thumbnail
|
||||
.order('RAND()')
|
||||
.first
|
||||
post =
|
||||
filtered_posts
|
||||
.preload(:uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_name: :wiki_page }] }])
|
||||
.with_attached_thumbnail
|
||||
.order('RAND()')
|
||||
.first
|
||||
return head :not_found unless post
|
||||
|
||||
render json: PostRepr.base(post, current_user)
|
||||
@@ -426,8 +428,20 @@ class PostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def tagged_post_ids_for(name) =
|
||||
Post.joins(tags: :tag_name).where(tag_names: { name: }).select(:id)
|
||||
def tagged_post_ids_for(name)
|
||||
posts_by_internal_tags =
|
||||
Post
|
||||
.joins(tags: :tag_name)
|
||||
.where(tag_names: { name: })
|
||||
.select(:id)
|
||||
|
||||
posts_by_external_tags =
|
||||
Post
|
||||
.joins(:external_tags)
|
||||
.where("CONCAT(external_tags.platform, ':', external_tags.name) = ?", name)
|
||||
|
||||
(posts_by_internal_tags + posts_by_external_tags).uniq(&:id)
|
||||
end
|
||||
|
||||
def sync_post_tags! post, desired_tags, sections
|
||||
desired_tags.each do |t|
|
||||
|
||||
@@ -34,49 +34,155 @@ class TagsController < ApplicationController
|
||||
|
||||
offset = (page - 1) * limit
|
||||
|
||||
q =
|
||||
tags =
|
||||
if post_id.present?
|
||||
Tag.joins(:posts, :tag_name)
|
||||
Tag.joins(:posts, :tag_name).where(posts: { id: post_id })
|
||||
else
|
||||
Tag.joins(:tag_name)
|
||||
end
|
||||
.includes(:tag_name, :materials, tag_name: :wiki_page)
|
||||
q = q.where(posts: { id: post_id }) if post_id.present?
|
||||
|
||||
q = q.where('tag_names.name LIKE ?', "%#{ name }%") if name
|
||||
q = q.where(category:) if category
|
||||
q = q.where('tags.post_count >= ?', post_count_between[0]) if post_count_between[0]
|
||||
q = q.where('tags.post_count <= ?', post_count_between[1]) if post_count_between[1]
|
||||
q = q.where('tags.created_at >= ?', created_between[0]) if created_between[0]
|
||||
q = q.where('tags.created_at <= ?', created_between[1]) if created_between[1]
|
||||
q = q.where('tags.updated_at >= ?', updated_between[0]) if updated_between[0]
|
||||
q = q.where('tags.updated_at <= ?', updated_between[1]) if updated_between[1]
|
||||
if deprecated_given
|
||||
q = deprecated ? q.where.not(deprecated_at: nil) : q.where(deprecated_at: nil)
|
||||
external_tags =
|
||||
if post_id.present?
|
||||
ExternalTag.joins(:posts).where(posts: { id: post_id })
|
||||
else
|
||||
ExternalTag.all
|
||||
end
|
||||
|
||||
if name
|
||||
tags = tags.where('tag_names.name LIKE ?', "%#{ name }%")
|
||||
external_tags =
|
||||
external_tags.where("CONCAT(external_tags.platform, ':', external_tags.name) LIKE ?",
|
||||
"%#{ name }%")
|
||||
end
|
||||
|
||||
if category == 'nico'
|
||||
tags = tags.none
|
||||
elsif category
|
||||
tags = tags.where(category:)
|
||||
external_tags = external_tags.none
|
||||
end
|
||||
|
||||
if post_count_between[0]
|
||||
tags = tags.where('tags.post_count >= ?', post_count_between[0])
|
||||
external_tags = external_tags.where('external_tags.post_count >= ?', post_count_between[0])
|
||||
end
|
||||
|
||||
if post_count_between[1]
|
||||
tags = tags.where('tags.post_count <= ?', post_count_between[1])
|
||||
external_tags = external_tags.where('external_tags.post_count <= ?', post_count_between[1])
|
||||
end
|
||||
|
||||
if created_between[0]
|
||||
tags = tags.where('tags.created_at >= ?', created_between[0])
|
||||
external_tags = external_tags.where('external_tags.created_at >= ?', created_between[0])
|
||||
end
|
||||
|
||||
if created_between[1]
|
||||
tags = tags.where('tags.created_at <= ?', created_between[1])
|
||||
external_tags = external_tags.where('external_tags.created_at <= ?', created_between[1])
|
||||
end
|
||||
|
||||
if updated_between[0]
|
||||
tags = tags.where('tags.updated_at >= ?', updated_between[0])
|
||||
external_tags = external_tags.where('external_tags.created_at >= ?', updated_between[0])
|
||||
end
|
||||
|
||||
if updated_between[1]
|
||||
tags = tags.where('tags.updated_at <= ?', updated_between[1])
|
||||
external_tags = external_tags.where('external_tags.created_at <= ?', updated_between[1])
|
||||
end
|
||||
|
||||
if deprecated_given
|
||||
if deprecated
|
||||
tags = tags.where.not(deprecated_at: nil)
|
||||
external_tags = external_tags.none
|
||||
else
|
||||
tags = tags.where(deprecated_at: nil)
|
||||
end
|
||||
end
|
||||
|
||||
tag_sql = tags.select("'tag' AS source",
|
||||
'tags.id',
|
||||
'tag_names.name',
|
||||
'tags.category',
|
||||
'tags.post_count',
|
||||
'tags.created_at',
|
||||
'tags.updated_at',
|
||||
'tags.deprecated_at').to_sql
|
||||
|
||||
external_tag_sql = external_tags.select(
|
||||
"'external_tag' AS source",
|
||||
'external_tags.id',
|
||||
"CONCAT(external_tags.platform, ':', external_tags.name) AS name",
|
||||
"'nico' AS category",
|
||||
'external_tags.post_count',
|
||||
'external_tags.created_at',
|
||||
'external_tags.created_at AS updated_at',
|
||||
'NULL AS deprecated_at').to_sql
|
||||
|
||||
union_sql = "#{ tag_sql } UNION ALL #{ external_tag_sql }"
|
||||
|
||||
sort_sql =
|
||||
case order[0]
|
||||
when 'name'
|
||||
'tag_names.name'
|
||||
when 'category'
|
||||
'CASE tags.category ' +
|
||||
if order[0] == 'category'
|
||||
'CASE category ' +
|
||||
"WHEN 'deerjikist' THEN 0 " +
|
||||
"WHEN 'meme' THEN 1 " +
|
||||
"WHEN 'character' THEN 2 " +
|
||||
"WHEN 'general' THEN 3 " +
|
||||
"WHEN 'material' THEN 4 " +
|
||||
"WHEN 'meta' THEN 5 " +
|
||||
"WHEN 'nico' THEN 6 END"
|
||||
"WHEN 'nico' THEN 6 " +
|
||||
'END'
|
||||
else
|
||||
"tags.#{ order[0] }"
|
||||
order[0]
|
||||
end
|
||||
tags = q.order(Arel.sql("#{ sort_sql } #{ order[1] }, tags.id #{ order[1] }"))
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.to_a
|
||||
|
||||
render json: { tags: TagRepr.many(tags), count: q.size }
|
||||
connection = ApplicationRecord.connection
|
||||
|
||||
count = connection.select_value(<<~SQL)
|
||||
SELECT
|
||||
COUNT(0)
|
||||
FROM
|
||||
(#{ union_sql }) legacy_tags
|
||||
SQL
|
||||
|
||||
rows = connection.select_all(<<~SQL).to_a
|
||||
SELECT
|
||||
source
|
||||
, id
|
||||
FROM
|
||||
(#{ union_sql }) legacy_tags
|
||||
ORDER BY
|
||||
#{ sort_sql } #{ order[1] }
|
||||
, id #{ order[1] }
|
||||
, source #{ order[1] }
|
||||
LIMIT
|
||||
#{ limit }
|
||||
OFFSET
|
||||
#{ offset }
|
||||
SQL
|
||||
|
||||
tag_ids = rows.filter { _1['source'] == 'tag' }.map { _1['id'] }
|
||||
external_tag_ids = rows.filter { _1['source'] == 'external_tag' }.map { _1['id'] }
|
||||
|
||||
tags_by_id =
|
||||
Tag
|
||||
.joins(:tag_name)
|
||||
.includes(:tag_name, :materials, tag_name: :wiki_page)
|
||||
.where(id: tag_ids)
|
||||
.index_by(&:id)
|
||||
external_tags_by_id =
|
||||
ExternalTag
|
||||
.where(id: external_tag_ids)
|
||||
.index_by(&:id)
|
||||
|
||||
render json: { tags: rows.map { |row|
|
||||
if row['source'] == 'tag'
|
||||
TagRepr.base(tags_by_id.fetch(row['id']))
|
||||
else
|
||||
external_tag_json(external_tags_by_id.fetch(row['id']))
|
||||
end
|
||||
}, count: }
|
||||
end
|
||||
|
||||
def with_depth
|
||||
@@ -128,12 +234,7 @@ class TagsController < ApplicationController
|
||||
|
||||
canonical_hit = base.where('tag_names.name LIKE ?', prefix)
|
||||
|
||||
internal_tags =
|
||||
if with_nico
|
||||
canonical_hit.or(base.where(tag_name_id: canonical_ids.uniq))
|
||||
else
|
||||
canonical_hit
|
||||
end
|
||||
internal_tags = canonical_hit.or(base.where(tag_name_id: canonical_ids.uniq))
|
||||
|
||||
internal_rows =
|
||||
internal_tags
|
||||
@@ -153,16 +254,7 @@ class TagsController < ApplicationController
|
||||
.where("CONCAT(platform, ':', name) LIKE ? OR name LIKE ?", prefix, prefix)
|
||||
.order(post_count: :desc, name: :asc)
|
||||
.limit(20)
|
||||
.map { |tag|
|
||||
{ 'id' => tag.id,
|
||||
'name' => "#{ tag.platform }:#{ tag.name }",
|
||||
'category' => 'nico',
|
||||
'deprecated_at' => nil,
|
||||
'created_at' => tag.created_at,
|
||||
'updated_at' => tag.created_at,
|
||||
'post_count' => tag.post_count,
|
||||
'matched_alias' => nil }
|
||||
}
|
||||
.map { external_tag_json(_1) }
|
||||
|
||||
rows =
|
||||
(internal_rows + external_rows)
|
||||
@@ -187,14 +279,20 @@ class TagsController < ApplicationController
|
||||
name = params[:name].to_s.strip
|
||||
return render_bad_request('name は必須です.') if name.blank?
|
||||
|
||||
tag = Tag.joins(:tag_name)
|
||||
.includes(:tag_name, :materials, tag_name: :wiki_page)
|
||||
.find_by(tag_names: { name: })
|
||||
if tag
|
||||
render json: TagRepr.base(tag)
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_name)
|
||||
.includes(:tag_name, :materials, tag_name: :wiki_page)
|
||||
.find_by(tag_names: { name: })
|
||||
return render json: TagRepr.base(tag) if tag
|
||||
|
||||
platform, external_name = name.split(':', 2)
|
||||
return head :not_found unless external_name
|
||||
|
||||
external_tag = ExternalTag.find_by(platform:, name: external_name)
|
||||
return head :not_found unless external_tag
|
||||
|
||||
render json: ExternalTagRepr.base(external_tag)
|
||||
end
|
||||
|
||||
def deerjikists
|
||||
@@ -805,4 +903,20 @@ class TagsController < ApplicationController
|
||||
|
||||
render_validation_error fields:
|
||||
end
|
||||
|
||||
def external_tag_json tag
|
||||
{ 'id' => tag.id,
|
||||
'name' => "#{ tag.platform }:#{ tag.name }",
|
||||
'category' => 'nico',
|
||||
'deprecated_at' => nil,
|
||||
'created_at' => tag.created_at,
|
||||
'updated_at' => tag.created_at,
|
||||
'post_count' => tag.post_count,
|
||||
'matched_alias' => nil,
|
||||
'aliases' => [],
|
||||
'parents' => [],
|
||||
'has_wiki' => false,
|
||||
'material_id' => nil,
|
||||
'has_deerjikists' => false }
|
||||
end
|
||||
end
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする