#236 feat: 投稿にニコタグ追加できてしまふバグ修正(#125)

Merged
みてるぞ merged 2 commits from feature/125 into main 2 weeks ago
  1. +4
    -2
      backend/app/controllers/posts_controller.rb
  2. +13
    -3
      backend/app/models/tag.rb
  3. +40
    -5
      backend/spec/requests/posts_spec.rb

+ 4
- 2
backend/app/controllers/posts_controller.rb View File

@@ -81,8 +81,6 @@ class PostsController < ApplicationController
return head :unauthorized unless current_user return head :unauthorized unless current_user
return head :forbidden unless current_user.member? return head :forbidden unless current_user.member?


# TODO: URL が正規のものがチェック,不正ならエラー
# TODO: URL は必須にする(タイトルは省略可).
# TODO: サイトに応じて thumbnail_base 設定 # TODO: サイトに応じて thumbnail_base 設定
title = params[:title].presence title = params[:title].presence
url = params[:url] url = params[:url]
@@ -105,6 +103,8 @@ class PostsController < ApplicationController
else else
render json: { errors: post.errors.full_messages }, status: :unprocessable_entity render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
end end
rescue Tag::NicoTagNormalisationError
head :bad_request
end end


def viewed def viewed
@@ -142,6 +142,8 @@ class PostsController < ApplicationController
else else
render json: post.errors, status: :unprocessable_entity render json: post.errors, status: :unprocessable_entity
end end
rescue Tag::NicoTagNormalisationError
head :bad_request
end end


def changes def changes


+ 13
- 3
backend/app/models/tag.rb View File

@@ -1,4 +1,8 @@
class Tag < ApplicationRecord class Tag < ApplicationRecord
class NicoTagNormalisationError < ArgumentError
;
end

has_many :post_tags, dependent: :delete_all, inverse_of: :tag has_many :post_tags, dependent: :delete_all, inverse_of: :tag
has_many :active_post_tags, -> { kept }, class_name: 'PostTag', 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' 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') @bot ||= find_or_create_by_tag_name!('bot操作', category: 'meta')
end 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| tags = tag_names.map do |name|
pf, cat = CATEGORY_PREFIXES.find { |p, _| name.start_with?(p) } || ['', nil] 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| find_or_create_by_tag_name!(name, category: (cat || 'general')).tap do |tag|
if cat && tag.category != cat if cat && tag.category != cat
tag.update!(category: cat) tag.update!(category: cat)
@@ -101,11 +109,13 @@ class Tag < ApplicationRecord
(result + tags).uniq { |t| t.id } (result + tags).uniq { |t| t.id }
end 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) tn = TagName.find_or_create_by!(name: name.to_s.strip)
Tag.find_or_create_by!(tag_name_id: tn.id) do |t| Tag.find_or_create_by!(tag_name_id: tn.id) do |t|
t.category = category t.category = category
end end
rescue ActiveRecord::RecordNotUnique
retry
end end


private private


+ 40
- 5
backend/spec/requests/posts_spec.rb View File

@@ -167,16 +167,34 @@ RSpec.describe 'Posts API', type: :request do
expect(json['tags'][0]).to have_key('name') expect(json['tags'][0]).to have_key('name')
end 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 context 'when url is blank' do
it 'returns 422' do it 'returns 422' do
sign_in_as(member) sign_in_as(member)


post '/posts', params: { 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) expect(response).to have_http_status(:unprocessable_entity)
end end
@@ -233,6 +251,23 @@ RSpec.describe 'Posts API', type: :request do
names = json['tags'].map { |n| n['name'] } names = json['tags'].map { |n| n['name'] }
expect(names).to include('spec_tag_2') expect(names).to include('spec_tag_2')
end 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 end


describe 'GET /posts/random' do describe 'GET /posts/random' do


Loading…
Cancel
Save