require 'open-uri' require 'nokogiri' class PostsController < ApplicationController # GET /posts def index posts = filtered_posts render json: posts.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }) end def random post = filtered_posts.order('RAND()').first viewed = current_user&.viewed?(post) || false render json: (post .as_json(include: { tags: { only: [:id, :name, :category] } }) .merge(viewed: viewed)) end # GET /posts/1 def show post = Post.includes(:tags).find(params[:id]) viewed = current_user&.viewed?(post) render json: (post .as_json(include: { tags: { only: [:id, :name, :category] } }) .merge(viewed: viewed)) end # POST /posts def create return head :unauthorized unless current_user return head :forbidden unless ['admin', 'member'].include?(current_user.role) # TODO: URL が正規のものがチェック,不正ならエラー title = params[:title] post = Post.new(title: title, url: params[:url], thumbnail_base: '', uploaded_user: current_user) post.thumbnail.attach(params[:thumbnail]) if post.save post.resized_thumbnail! if params[:tags].present? tag_ids = JSON.parse(params[:tags]) post.tags = Tag.where(id: tag_ids) end render json: post, status: :created else render json: { errors: post.errors.full_messages }, status: :unprocessable_entity end end def viewed return head :unauthorized unless current_user current_user.viewed_posts << Post.find(params[:id]) head :no_content end def unviewed return head :unauthorized unless current_user current_user.viewed_posts.delete(Post.find(params[:id])) head :no_content end # PATCH/PUT /posts/1 def update return head :unauthorized unless current_user return head :forbidden unless ['admin', 'member'].include?(current_user.role) post = Post.find(params[:id]) tag_ids = JSON.parse(params[:tags]) if post.update(title: params[:title], tags: Tag.where(id: tag_ids)) render({ json: (post .as_json(include: { tags: { only: [:id, :name, :category] } })), status: :created }) else render json: post.errors, status: :unprocessable_entity end end # DELETE /posts/1 def destroy end private def filtered_posts tag_names = params[:tags]&.split(',') match_type = params[:match] tag_names.present? ? filter_posts_by_tags(tag_names, match_type) : Post.all end def filter_posts_by_tags tag_names, match_type posts = Post.joins(:tags) if match_type == 'any' posts = posts.where(tags: { name: tag_names }).distinct else tag_names.each do |tag| posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag })) end end posts.distinct end end