#125 #125 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: https://git.miteruzo.com/miteruzo/btrc-hub/pulls/236pull/237/head
| @@ -81,8 +81,6 @@ class PostsController < ApplicationController | |||
| return head :unauthorized unless current_user | |||
| return head :forbidden unless current_user.member? | |||
| # TODO: URL が正規のものがチェック,不正ならエラー | |||
| # TODO: URL は必須にする(タイトルは省略可). | |||
| # TODO: サイトに応じて thumbnail_base 設定 | |||
| title = params[:title].presence | |||
| url = params[:url] | |||
| @@ -105,6 +103,8 @@ class PostsController < ApplicationController | |||
| else | |||
| render json: { errors: post.errors.full_messages }, status: :unprocessable_entity | |||
| end | |||
| rescue Tag::NicoTagNormalisationError | |||
| head :bad_request | |||
| end | |||
| def viewed | |||
| @@ -142,6 +142,8 @@ class PostsController < ApplicationController | |||
| else | |||
| render json: post.errors, status: :unprocessable_entity | |||
| end | |||
| rescue Tag::NicoTagNormalisationError | |||
| head :bad_request | |||
| end | |||
| def changes | |||
| @@ -1,4 +1,8 @@ | |||
| class Tag < ApplicationRecord | |||
| class NicoTagNormalisationError < ArgumentError | |||
| ; | |||
| end | |||
| has_many :post_tags, dependent: :delete_all, inverse_of: :tag | |||
| has_many :active_post_tags, -> { kept }, class_name: 'PostTag', inverse_of: :tag | |||
| has_many :post_tags_with_discarded, -> { with_discarded }, class_name: 'PostTag' | |||
| @@ -63,10 +67,14 @@ class Tag < ApplicationRecord | |||
| @bot ||= find_or_create_by_tag_name!('bot操作', category: 'meta') | |||
| end | |||
| def self.normalise_tags tag_names, with_tagme: true | |||
| def self.normalise_tags tag_names, with_tagme: true, deny_nico: true | |||
| if deny_nico && tag_names.any? { |n| n.start_with?('nico:') } | |||
| raise NicoTagNormalisationError | |||
| end | |||
| tags = tag_names.map do |name| | |||
| pf, cat = CATEGORY_PREFIXES.find { |p, _| name.start_with?(p) } || ['', nil] | |||
| name.delete_prefix!(pf) | |||
| name = name.delete_prefix(pf) | |||
| find_or_create_by_tag_name!(name, category: (cat || 'general')).tap do |tag| | |||
| if cat && tag.category != cat | |||
| tag.update!(category: cat) | |||
| @@ -101,11 +109,13 @@ class Tag < ApplicationRecord | |||
| (result + tags).uniq { |t| t.id } | |||
| end | |||
| def self.find_or_create_by_tag_name!(name, category:) | |||
| def self.find_or_create_by_tag_name! name, category: | |||
| tn = TagName.find_or_create_by!(name: name.to_s.strip) | |||
| Tag.find_or_create_by!(tag_name_id: tn.id) do |t| | |||
| t.category = category | |||
| end | |||
| rescue ActiveRecord::RecordNotUnique | |||
| retry | |||
| end | |||
| private | |||
| @@ -167,16 +167,34 @@ RSpec.describe 'Posts API', type: :request do | |||
| expect(json['tags'][0]).to have_key('name') | |||
| end | |||
| context "when nico tag already exists in tags" do | |||
| before do | |||
| Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), | |||
| category: 'nico') | |||
| end | |||
| it 'return 400' do | |||
| sign_in_as(member) | |||
| post '/posts', params: { | |||
| title: 'new post', | |||
| url: 'https://example.com/nico_tag', | |||
| tags: 'nico:nico_tag', | |||
| thumbnail: dummy_upload } | |||
| expect(response).to have_http_status(:bad_request) | |||
| end | |||
| end | |||
| context 'when url is blank' do | |||
| it 'returns 422' do | |||
| sign_in_as(member) | |||
| post '/posts', params: { | |||
| title: 'new post', | |||
| url: ' ', | |||
| tags: 'spec_tag', # 既存タグ名を投げる | |||
| thumbnail: dummy_upload | |||
| } | |||
| title: 'new post', | |||
| url: ' ', | |||
| tags: 'spec_tag', # 既存タグ名を投げる | |||
| thumbnail: dummy_upload } | |||
| expect(response).to have_http_status(:unprocessable_entity) | |||
| end | |||
| @@ -233,6 +251,23 @@ RSpec.describe 'Posts API', type: :request do | |||
| names = json['tags'].map { |n| n['name'] } | |||
| expect(names).to include('spec_tag_2') | |||
| end | |||
| context "when nico tag already exists in tags" do | |||
| before do | |||
| Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), | |||
| category: 'nico') | |||
| end | |||
| it 'return 400' do | |||
| sign_in_as(member) | |||
| put "/posts/#{ post_record.id }", params: { | |||
| title: 'updated title', | |||
| tags: 'nico:nico_tag' } | |||
| expect(response).to have_http_status(:bad_request) | |||
| end | |||
| end | |||
| end | |||
| describe 'GET /posts/random' do | |||