This commit is contained in:
@@ -44,7 +44,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(tags: [:materials, { tag_name: :wiki_page }])
|
||||
.preload(tags: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
.with_attached_thumbnail
|
||||
|
||||
q = q.where('posts.url LIKE ?', "%#{ url }%") if url
|
||||
@@ -95,7 +95,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def random
|
||||
post = filtered_posts.preload(tags: [:materials, { tag_name: :wiki_page }])
|
||||
post = filtered_posts.preload(tags: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
.order('RAND()')
|
||||
.first
|
||||
return head :not_found unless post
|
||||
@@ -104,7 +104,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
post = Post.includes(tags: [:materials, { tag_name: :wiki_page }]).find_by(id: params[:id])
|
||||
post = Post.includes(tags: [:deerjikists, :materials, { tag_name: :wiki_page }]).find_by(id: params[:id])
|
||||
return head :not_found unless post
|
||||
|
||||
render json: PostRepr.base(post, current_user)
|
||||
@@ -173,8 +173,12 @@ class PostsController < ApplicationController
|
||||
return head :unauthorized unless current_user
|
||||
return head :forbidden unless current_user.gte_member?
|
||||
|
||||
base_version_no = parse_base_version_no
|
||||
force = truthy_param?(params[:force])
|
||||
merge = truthy_param?(params[:merge])
|
||||
return head :bad_request if force && merge
|
||||
|
||||
base_version_no = nil
|
||||
base_version_no = parse_base_version_no unless force
|
||||
|
||||
title = params[:title].presence
|
||||
tag_names = params[:tags].to_s.split
|
||||
@@ -186,12 +190,17 @@ class PostsController < ApplicationController
|
||||
conflict_json = nil
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
post = Post.find(params[:id].to_i)
|
||||
post = Post.lock.find(params[:id].to_i)
|
||||
|
||||
base_version = post.post_versions.find_by!(version_no: base_version_no)
|
||||
base_version = nil
|
||||
base_snapshot = nil
|
||||
current_snapshot = nil
|
||||
unless force
|
||||
base_version = post.post_versions.find_by!(version_no: base_version_no)
|
||||
|
||||
base_snapshot = post_snapshot_from_version(base_version)
|
||||
current_snapshot = post_snapshot_from_record(post)
|
||||
base_snapshot = post_snapshot_from_version(base_version)
|
||||
current_snapshot = post_snapshot_from_record(post)
|
||||
end
|
||||
incoming_snapshot = post_incoming_snapshot(post,
|
||||
title:,
|
||||
original_created_from:,
|
||||
@@ -199,29 +208,28 @@ class PostsController < ApplicationController
|
||||
tag_names:,
|
||||
parent_post_ids:)
|
||||
|
||||
if !(force) && post.version_no != base_version_no
|
||||
conflict_json = post_conflict_json(post:,
|
||||
base_version_no:,
|
||||
base_snapshot:,
|
||||
current_snapshot:,
|
||||
incoming_snapshot:)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
snapshot_to_apply =
|
||||
if post.version_no == base_version_no || force
|
||||
incoming_snapshot
|
||||
else
|
||||
changes = post_snapshot_changes(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
conflicts = changes.select { |change| change[:conflict] }
|
||||
|
||||
PostVersionRecorder.ensure_snapshot!(post, created_by_user: current_user)
|
||||
if merge && conflicts.empty?
|
||||
merge_post_snapshots(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
else
|
||||
conflict_json = post_conflict_json(post:,
|
||||
base_version_no:,
|
||||
base_snapshot:,
|
||||
current_snapshot:,
|
||||
incoming_snapshot:,
|
||||
changes:,
|
||||
conflicts:)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
post.update!(title:, original_created_from:, original_created_before:)
|
||||
|
||||
normalised_tags = Tag.normalise_tags!(tag_names, with_tagme: false)
|
||||
TagVersioning.record_tag_snapshots!(normalised_tags, created_by_user: current_user)
|
||||
|
||||
tags = post.tags.nico.to_a + normalised_tags
|
||||
tags = Tag.expand_parent_tags(tags)
|
||||
sync_post_tags!(post, tags)
|
||||
|
||||
sync_parent_posts!(post, parent_post_ids)
|
||||
|
||||
PostVersionRecorder.record!(post:, event_type: :update, created_by_user: current_user)
|
||||
apply_post_snapshot!(post, snapshot_to_apply)
|
||||
end
|
||||
|
||||
return render json: conflict_json, status: :conflict if conflict_json
|
||||
@@ -253,7 +261,7 @@ class PostsController < ApplicationController
|
||||
pts = pts.where(post_id: id) if id.present?
|
||||
pts = pts.where(tag_id:) if tag_id.present?
|
||||
pts = pts.includes(:post, :created_user, :deleted_user,
|
||||
tag: [:materials, { tag_name: :wiki_page }])
|
||||
tag: [:deerjikists, :materials, { tag_name: :wiki_page }])
|
||||
|
||||
events = []
|
||||
pts.each do |pt|
|
||||
@@ -446,11 +454,11 @@ class PostsController < ApplicationController
|
||||
{ title: version.title,
|
||||
original_created_from: snapshot_time(version.original_created_from),
|
||||
original_created_before: snapshot_time(version.original_created_before),
|
||||
tag_names: version.tags.to_s.split.sort,
|
||||
tag_names: version.tags.to_s.split.filter { !(_1.start_with?('nico:')) }.sort,
|
||||
parent_post_ids: snapshot_parent_post_ids_from_version(version) }
|
||||
end
|
||||
|
||||
def post_snapshot_form_record post
|
||||
def post_snapshot_from_record post
|
||||
{ title: post.title,
|
||||
original_created_from: snapshot_time(post.original_created_from),
|
||||
original_created_before: snapshot_time(post.original_created_before),
|
||||
@@ -460,7 +468,7 @@ class PostsController < ApplicationController
|
||||
|
||||
def post_incoming_snapshot post, title:, original_created_from:, original_created_before:,
|
||||
tag_names:, parent_post_ids:
|
||||
{ title:
|
||||
{ title:,
|
||||
original_created_from: snapshot_time(original_created_from),
|
||||
original_created_before: snapshot_time(original_created_before),
|
||||
tag_names: incoming_tag_names_for_snapshot(post, tag_names),
|
||||
@@ -488,17 +496,16 @@ class PostsController < ApplicationController
|
||||
|
||||
def incoming_tag_names_for_snapshot post, raw_tag_names
|
||||
manual_names = normalised_manual_tag_names_for_snapshot(raw_tag_names)
|
||||
nico_names = post.tags.nico.joins(:tag_name).pluck('tag_names.name')
|
||||
|
||||
existing_tags =
|
||||
Tag
|
||||
.joins(:tag_name)
|
||||
.where(tag_names: { name: manual_names + nico_names })
|
||||
.where(tag_names: { name: manual_names })
|
||||
.to_a
|
||||
|
||||
expanded_names = Tag.expand_parent_tags(existing_tags).map(&:name)
|
||||
|
||||
(manual_names + nico_names + expanded_names).uniq.sort
|
||||
(manual_names + expanded_names).uniq.sort
|
||||
end
|
||||
|
||||
def normalised_manual_tag_names_for_snapshot raw_tag_names
|
||||
@@ -528,10 +535,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def post_conflict_json post:, base_version_no:, base_snapshot:,
|
||||
current_snapshot:, incoming_snapshot:
|
||||
changes = post_snapshot_changes(base_snapshot, current_snapshot, incoming_snapshot)
|
||||
conflicts = changes.select { |change| change[:conflict] }
|
||||
|
||||
current_snapshot:, incoming_snapshot:, changes:, conflicts:
|
||||
{ error: 'conflict',
|
||||
message: '競合が発生しました.',
|
||||
post_id: post.id,
|
||||
@@ -548,9 +552,9 @@ class PostsController < ApplicationController
|
||||
def post_snapshot_changes base_snapshot, current_snapshot, incoming_snapshot
|
||||
[scalar_snapshot_change(:title, 'タイトル',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
scalar_snapshot_change(:original_created_from, '元コンテンツ作成日時(開始)',
|
||||
scalar_snapshot_change(:original_created_from, 'オリジナルの作成日時(以降)',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
scalar_snapshot_change(:original_created_before, '元コンテンツ作成日時(終了)',
|
||||
scalar_snapshot_change(:original_created_before, 'オリジナルの作成日時(より前)',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
set_snapshot_change(:tag_names, 'タグ',
|
||||
base_snapshot, current_snapshot, incoming_snapshot),
|
||||
@@ -606,4 +610,37 @@ class PostsController < ApplicationController
|
||||
added_by_me:, removed_by_me:
|
||||
(added_by_current & removed_by_me).present? || (removed_by_current & added_by_me).present?
|
||||
end
|
||||
|
||||
def apply_post_snapshot! post, snapshot
|
||||
PostVersionRecorder.ensure_snapshot!(post, created_by_user: current_user)
|
||||
|
||||
post.update!(title: snapshot[:title],
|
||||
original_created_from: snapshot[:original_created_from],
|
||||
original_created_before: snapshot[:original_created_before])
|
||||
|
||||
tags = Tag.normalise_tags!(snapshot[:tag_names], with_tagme: false)
|
||||
TagVersioning.record_tag_snapshots!(tags, created_by_user: current_user)
|
||||
|
||||
tags = Tag.expand_parent_tags(tags)
|
||||
sync_post_tags!(post, tags)
|
||||
|
||||
sync_parent_posts!(post, snapshot[:parent_post_ids])
|
||||
|
||||
PostVersionRecorder.record!(post:, event_type: :update, created_by_user: current_user)
|
||||
end
|
||||
|
||||
def merge_post_snapshots base_snapshot, current_snapshot, incoming_snapshot
|
||||
[:title, :original_created_from, :original_created_before, :tag_names, :parent_post_ids].map {
|
||||
[_1, merge_scaler_snapshot_value(base_snapshot[_1],
|
||||
current_snapshot[_1],
|
||||
incoming_snapshot[_1])]
|
||||
}.to_h
|
||||
end
|
||||
|
||||
def merge_scaler_snapshot_value base, current, mine
|
||||
return mine if current == base
|
||||
return current if mine == base || current == mine
|
||||
|
||||
raise ArgumentError, '競合してゐる項目はマージできません.'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -136,6 +136,7 @@ class Tag < ApplicationRecord
|
||||
tn = tn.canonical if tn.canonical_id?
|
||||
|
||||
Tag.find_undiscard_or_create_by!(tag_name_id: tn.id) do |t|
|
||||
t.version_no = TagVersion.where(tag_id: t.id).order(version_no: :desc).first || 1
|
||||
t.category = category
|
||||
end
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
|
||||
Reference in New Issue
Block a user