#59 関聯投稿一覧の追加
This commit is contained in:
@@ -5,16 +5,16 @@ require 'nokogiri'
|
|||||||
class PostsController < ApplicationController
|
class PostsController < ApplicationController
|
||||||
# GET /posts
|
# GET /posts
|
||||||
def index
|
def index
|
||||||
limit = (params[:limit] || 20).to_i
|
limit = params[:limit].presence&.to_i
|
||||||
cursor = params[:cursor].presence
|
cursor = params[:cursor].presence
|
||||||
|
|
||||||
q = filtered_posts.order(created_at: :desc)
|
q = filtered_posts.order(created_at: :desc)
|
||||||
q = q.where('posts.created_at < ?', Time.iso8601(cursor)) if cursor
|
q = q.where('posts.created_at < ?', Time.iso8601(cursor)) if cursor
|
||||||
|
|
||||||
posts = q.limit(limit + 1)
|
posts = limit ? q.limit(limit + 1) : q
|
||||||
|
|
||||||
next_cursor = nil
|
next_cursor = nil
|
||||||
if posts.size > limit
|
if limit && posts.size > limit
|
||||||
next_cursor = posts.last.created_at.iso8601(6)
|
next_cursor = posts.last.created_at.iso8601(6)
|
||||||
posts = posts.first(limit)
|
posts = posts.first(limit)
|
||||||
end
|
end
|
||||||
@@ -51,7 +51,7 @@ class PostsController < ApplicationController
|
|||||||
|
|
||||||
render json: (post
|
render json: (post
|
||||||
.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } })
|
.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } })
|
||||||
.merge(viewed: viewed))
|
.merge(related: post.related(limit: 20), viewed:))
|
||||||
end
|
end
|
||||||
|
|
||||||
# POST /posts
|
# POST /posts
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ class Post < ApplicationRecord
|
|||||||
has_many :post_tags, dependent: :destroy
|
has_many :post_tags, dependent: :destroy
|
||||||
has_many :tags, through: :post_tags
|
has_many :tags, through: :post_tags
|
||||||
has_many :user_post_views, dependent: :destroy
|
has_many :user_post_views, dependent: :destroy
|
||||||
|
has_many :post_similarities_as_post,
|
||||||
|
class_name: 'PostSimilarity',
|
||||||
|
foreign_key: :post_id
|
||||||
|
has_many :post_similarities_as_target_post,
|
||||||
|
class_name: 'PostSimilarity',
|
||||||
|
foreign_key: :target_post_id
|
||||||
has_one_attached :thumbnail
|
has_one_attached :thumbnail
|
||||||
|
|
||||||
def as_json options = { }
|
def as_json options = { }
|
||||||
@@ -18,6 +24,21 @@ class Post < ApplicationRecord
|
|||||||
super(options).merge(thumbnail: nil)
|
super(options).merge(thumbnail: nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def related(limit: nil)
|
||||||
|
ids_with_cos =
|
||||||
|
post_similarities_as_post.select(:target_post_id, :cos)
|
||||||
|
.map { |ps| [ps.target_post_id, ps.cos] } +
|
||||||
|
post_similarities_as_target_post.select(:post_id, :cos)
|
||||||
|
.map { |ps| [ps.post_id, ps.cos] }
|
||||||
|
|
||||||
|
sorted = ids_with_cos.sort_by { |_, cos| -cos }
|
||||||
|
|
||||||
|
ids = sorted.map(&:first)
|
||||||
|
ids = ids.first(limit) if limit
|
||||||
|
|
||||||
|
Post.where(id: ids)
|
||||||
|
end
|
||||||
|
|
||||||
def resized_thumbnail!
|
def resized_thumbnail!
|
||||||
return unless thumbnail.attached?
|
return unless thumbnail.attached?
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
|
|||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
|
|
||||||
|
import PostList from '@/components/PostList'
|
||||||
import TagDetailSidebar from '@/components/TagDetailSidebar'
|
import TagDetailSidebar from '@/components/TagDetailSidebar'
|
||||||
import NicoViewer from '@/components/NicoViewer'
|
import NicoViewer from '@/components/NicoViewer'
|
||||||
import PostEditForm from '@/components/PostEditForm'
|
import PostEditForm from '@/components/PostEditForm'
|
||||||
@@ -117,6 +118,9 @@ export default ({ user }: Props) => {
|
|||||||
{post.viewed ? '閲覧済' : '未閲覧'}
|
{post.viewed ? '閲覧済' : '未閲覧'}
|
||||||
</Button>
|
</Button>
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
|
<Tab name="関聯">
|
||||||
|
<PostList posts={post.related} />
|
||||||
|
</Tab>
|
||||||
{(['admin', 'member'].some (r => user?.role === r) && editing) && (
|
{(['admin', 'member'].some (r => user?.role === r) && editing) && (
|
||||||
<Tab name="編輯">
|
<Tab name="編輯">
|
||||||
<PostEditForm post={post}
|
<PostEditForm post={post}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ export type Post = {
|
|||||||
thumbnail: string
|
thumbnail: string
|
||||||
thumbnailBase: string
|
thumbnailBase: string
|
||||||
tags: Tag[]
|
tags: Tag[]
|
||||||
viewed: boolean }
|
viewed: boolean
|
||||||
|
related: Post[] }
|
||||||
|
|
||||||
export type SubMenuItem = {
|
export type SubMenuItem = {
|
||||||
component: React.ReactNode
|
component: React.ReactNode
|
||||||
|
|||||||
Reference in New Issue
Block a user