画面上でのテストは完了. 移行にす早さが求められるので,準備ができたらマージする. Reviewed-on: #430 Co-authored-by: miteruzo <miteruzo@naver.com>
このコミットはプルリクエスト #430 でマージされました。
このコミットが含まれているのは:
@@ -70,7 +70,10 @@ class MaterialsController < ApplicationController
|
||||
.find_by(id: params[:id])
|
||||
return head :not_found unless material
|
||||
|
||||
wiki_page_body = material.tag&.tag_name('ja')&.wiki_page&.current_revision&.body
|
||||
wiki_page_body =
|
||||
TagDescription
|
||||
.find_by(tag_id: material.tag_id, language_code: locale.language_code)
|
||||
&.body
|
||||
|
||||
render json: MaterialRepr.base(material, host: request.base_url,
|
||||
language_code: locale.language_code).merge(wiki_page_body:)
|
||||
|
||||
@@ -26,7 +26,7 @@ class NicoTagsController < ApplicationController
|
||||
ExternalTag
|
||||
.joins("LEFT JOIN (#{ post_tag_max_sql }) post_tag_max " \
|
||||
'ON post_tag_max.external_tag_id = external_tags.id')
|
||||
.includes(linked_tags: { tag_names: :wiki_page })
|
||||
.includes(linked_tags: [:tag_names, :tag_descriptions])
|
||||
if name
|
||||
q = q.where(('external_tags.name LIKE ? ' +
|
||||
"OR CONCAT(external_tags.platform, ':', external_tags.name) LIKE ?"),
|
||||
|
||||
@@ -53,7 +53,7 @@ class PostsController < ApplicationController
|
||||
.reselect('posts.*', Arel.sql("#{ updated_at_all_sql } AS updated_at_all"))
|
||||
.preload(:external_tags, :uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_names: :wiki_page }] }])
|
||||
:tag_names, :tag_descriptions] }])
|
||||
.with_attached_thumbnail
|
||||
|
||||
q = q.where('posts.url LIKE ?', "%#{ url }%") if url
|
||||
@@ -111,7 +111,7 @@ class PostsController < ApplicationController
|
||||
filtered_posts(locale)
|
||||
.preload(:uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_names: :wiki_page }] }])
|
||||
:tag_names, :tag_descriptions] }])
|
||||
.with_attached_thumbnail
|
||||
.order('RAND()')
|
||||
.first
|
||||
@@ -198,7 +198,7 @@ class PostsController < ApplicationController
|
||||
Post
|
||||
.includes(:uploaded_user, :parents, :children,
|
||||
post_tags: [:sections, { tag: [:deerjikists, :materials,
|
||||
{ tag_names: :wiki_page }] }])
|
||||
:tag_names, :tag_descriptions] }])
|
||||
.with_attached_thumbnail
|
||||
.find_by(id: params[:id])
|
||||
return head :not_found unless post
|
||||
|
||||
@@ -51,7 +51,7 @@ class TagVersionsController < ApplicationController
|
||||
|
||||
tags_by_id =
|
||||
Tag
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.where(id: all_parent_tag_ids)
|
||||
.index_by(&:id)
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ class TagsController < ApplicationController
|
||||
tags_by_id =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.where(tag_names: { language_code: locale.language_code, primary_flg: true },
|
||||
id: tag_ids)
|
||||
.index_by(&:id)
|
||||
@@ -238,7 +238,7 @@ class TagsController < ApplicationController
|
||||
base =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.where(tag_names: { language_code: locale.language_code, primary_flg: true },
|
||||
deprecated_at: nil)
|
||||
base = base.where('tags.post_count > 0') if present_only
|
||||
@@ -282,7 +282,7 @@ class TagsController < ApplicationController
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(id: params[:id],
|
||||
tag_names: { language_code: locale.language_code, primary_flg: true })
|
||||
return render json: TagRepr.base(tag, language_code: locale.language_code) if tag
|
||||
@@ -302,7 +302,7 @@ class TagsController < ApplicationController
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
|
||||
return render json: TagRepr.base(tag, language_code: locale.language_code) if tag
|
||||
|
||||
@@ -320,7 +320,7 @@ class TagsController < ApplicationController
|
||||
|
||||
tag =
|
||||
Tag.joins(:tag_names)
|
||||
.includes(:tag_names, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(id: params[:id],
|
||||
tag_names: { language_code: locale.language_code, primary_flg: true })
|
||||
return head :not_found unless tag
|
||||
@@ -340,7 +340,7 @@ class TagsController < ApplicationController
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
|
||||
return head :not_found unless tag
|
||||
|
||||
@@ -359,7 +359,7 @@ class TagsController < ApplicationController
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(id: params[:id],
|
||||
tag_names: { language_code: locale.language_code, primary_flg: true })
|
||||
return head :not_found unless tag
|
||||
@@ -424,7 +424,7 @@ class TagsController < ApplicationController
|
||||
tag =
|
||||
Tag
|
||||
.joins(:tag_names)
|
||||
.includes(:tag_names, :materials, tag_names: :wiki_page)
|
||||
.includes(:tag_names, :materials, :tag_descriptions, parents: :tag_descriptions)
|
||||
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
|
||||
return head :not_found unless tag
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ class WikiPagesController < ApplicationController
|
||||
descriptions =
|
||||
TagDescription.where(language_code: 'ja')
|
||||
.includes(tag: :tag_names)
|
||||
pages = unmigrated_wiki_pages.includes(tag_name: :tag)
|
||||
|
||||
tag_groups = TagGroup.all
|
||||
descriptions = descriptions.order(updated_at: :desc, id: :asc)
|
||||
tag_groups = TagGroup.order(updated_at: :desc, id: :asc)
|
||||
if title.present?
|
||||
pattern = "%#{ ApplicationRecord.sanitize_sql_like(title) }%"
|
||||
descriptions =
|
||||
@@ -19,12 +19,13 @@ class WikiPagesController < ApplicationController
|
||||
.where('tag_names.name LIKE ?', pattern).limit(20)
|
||||
tag_groups = tag_groups.where(
|
||||
'CONCAT(?, name) LIKE ?', TagGroupRepr::PREFIX, pattern).limit(20)
|
||||
pages = pages.where('tag_names.name LIKE ?', pattern).limit(20)
|
||||
end
|
||||
|
||||
json = descriptions.map { |description| WikiPageRepr.tag_description(description) }
|
||||
json.concat(tag_groups.map { WikiPageRepr.tag_group(_1) })
|
||||
json.concat(WikiPageRepr.base(pages))
|
||||
json.sort_by! do |row|
|
||||
[-row['updated_at'].to_f, row.fetch('resource_type'), row.fetch('id')]
|
||||
end
|
||||
json = json.first(20) if title.present?
|
||||
render json:
|
||||
end
|
||||
@@ -37,11 +38,7 @@ class WikiPagesController < ApplicationController
|
||||
tag_group = TagGroup.find_by(id: params[:id])
|
||||
return render_tag_group tag_group if tag_group
|
||||
|
||||
page = WikiPage.joins(:tag_name)
|
||||
.includes(tag_name: :tag)
|
||||
.find_by(id: params[:id])
|
||||
|
||||
render_wiki_page_or_404 page
|
||||
render_wiki_page_or_404 nil
|
||||
end
|
||||
|
||||
def show_by_title
|
||||
@@ -58,20 +55,14 @@ class WikiPagesController < ApplicationController
|
||||
|
||||
return render_wiki_page_by_tag_description tag_description if tag_description
|
||||
|
||||
page =
|
||||
WikiPage
|
||||
.joins(:tag_name)
|
||||
.includes(tag_name: :tag)
|
||||
.find_by(tag_name: { name: title })
|
||||
|
||||
render_wiki_page_or_404 page
|
||||
render_wiki_page_or_404 nil
|
||||
end
|
||||
|
||||
def exists
|
||||
return head :no_content if TagDescription.exists?(id: params[:id])
|
||||
return head :no_content if TagGroup.exists?(id: params[:id])
|
||||
|
||||
head WikiPage.exists?(id: params[:id]) ? :no_content : :not_found
|
||||
head :not_found
|
||||
end
|
||||
|
||||
def exists_by_title
|
||||
@@ -82,8 +73,7 @@ class WikiPagesController < ApplicationController
|
||||
end
|
||||
return head :no_content if tag_description_by_title(title)
|
||||
|
||||
exists = WikiPage.joins(:tag_name).exists?(tag_names: { name: title })
|
||||
head exists ? :no_content : :not_found
|
||||
head :not_found
|
||||
end
|
||||
|
||||
def diff
|
||||
@@ -112,15 +102,7 @@ class WikiPagesController < ApplicationController
|
||||
'title' => "#{ TagGroupRepr::PREFIX }#{ tag_group.name }",
|
||||
'deprecated_at' => nil }
|
||||
else
|
||||
page = WikiPage.joins(:tag_name).includes(tag_name: :tag).find(id)
|
||||
from_rev = from && page.wiki_revisions.find(from)
|
||||
to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
|
||||
if ((from_rev && !from_rev.content?) || !to_rev&.content?)
|
||||
return render_unprocessable_entity('差分を表示できない版です.')
|
||||
end
|
||||
from_body = from_rev&.body
|
||||
to_body = to_rev.body
|
||||
resource = WikiPageRepr.base(page)
|
||||
return head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
@@ -160,26 +142,19 @@ class WikiPagesController < ApplicationController
|
||||
status: :created)
|
||||
end
|
||||
|
||||
page = if title.include?(':')
|
||||
ApplicationRecord.transaction do
|
||||
tag_name = TagName.find_or_create_by!(language_code: 'ja', name: title) do |name|
|
||||
name.script_code = 'Jpan'
|
||||
name.primary_flg = true
|
||||
name.auto_generated = false
|
||||
page =
|
||||
if title.include?(':')
|
||||
return render_unprocessable_entity field: :title
|
||||
else
|
||||
tag_name = TagName.find_by(language_code: 'ja', name: title)
|
||||
return render_unprocessable_entity field: :title unless tag_name&.tag
|
||||
|
||||
TagDescriptionOperation.create!(
|
||||
tag: tag_name.tag, body:, created_by_user: current_user, message:)
|
||||
end
|
||||
|
||||
Wiki::Commit.create_legacy_content!(
|
||||
tag_name:, body:, created_by_user: current_user, message:)
|
||||
end
|
||||
else
|
||||
tag_name = TagName.find_by(language_code: 'ja', name: title)
|
||||
return render_unprocessable_entity field: :title unless tag_name&.tag
|
||||
|
||||
TagDescriptionOperation.create!(
|
||||
tag: tag_name.tag, body:, created_by_user: current_user, message:)
|
||||
end
|
||||
|
||||
render json: WikiPageRepr.base(page), status: :created
|
||||
description = TagDescription.find_by!(tag_id: page.tag_name.tag_id, language_code: 'ja')
|
||||
render json: WikiPageRepr.tag_description(description), status: :created
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
render_validation_error e.record
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
@@ -209,44 +184,34 @@ class WikiPagesController < ApplicationController
|
||||
return head :ok
|
||||
end
|
||||
|
||||
page = WikiPage.find_by(id: params[:id])
|
||||
if legacy_group_page?(page)
|
||||
return render_unprocessable_entity field: :title if title.include?(':')
|
||||
description = TagDescription.find_by(id: params[:id])
|
||||
unless description
|
||||
return render_unprocessable_entity field: :title if group || WikiPage.exists?(id: params[:id])
|
||||
return head :not_found
|
||||
end
|
||||
tag = description.tag
|
||||
tag_name = TagDescriptionOperation.compatibility_tag_name(tag)
|
||||
if tag_name.name.include?(':') || (group && title != tag_name.name)
|
||||
return render_unprocessable_entity field: :title
|
||||
end
|
||||
if group && !legacy_update_identified?(page, title, group)
|
||||
return render_unprocessable_entity field: :title
|
||||
end
|
||||
return head :not_found unless page
|
||||
|
||||
base_revision_id = params[:base_revision_id].presence
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
page.lock!
|
||||
|
||||
old_title = page.title
|
||||
|
||||
tag = page.tag_name.tag
|
||||
|
||||
if tag && title != old_title
|
||||
tag.lock!
|
||||
old_title = tag_name.name
|
||||
if title != old_title
|
||||
TagVersioning.ensure_snapshot!(tag, created_by_user: current_user)
|
||||
end
|
||||
|
||||
page.tag_name.update!(name: title) if title != old_title
|
||||
tag_name.update!(name: title) if title != old_title
|
||||
|
||||
message = params[:message].presence
|
||||
description = TagDescription.find_by(id: page.id)
|
||||
description_page = description && (
|
||||
tag&.id == description.tag_id ||
|
||||
(tag.nil? && !old_title.include?(':')))
|
||||
if description && !description_page
|
||||
Wiki::Commit.legacy_content!(page:, body:, created_user: current_user,
|
||||
message:, base_revision_id:)
|
||||
else
|
||||
Wiki::Commit.content!(page:, body:, created_user: current_user,
|
||||
message:, base_revision_id:)
|
||||
end
|
||||
TagDescriptionOperation.update!(tag:, body:, updated_by_user: current_user,
|
||||
message:, base_revision_id:)
|
||||
|
||||
if tag && title != old_title
|
||||
if title != old_title
|
||||
tag.reload
|
||||
TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: current_user)
|
||||
end
|
||||
@@ -273,23 +238,7 @@ class WikiPagesController < ApplicationController
|
||||
return render json: tag_group_changes(TagGroupVersion.where(tag_group_id: tag_group.id))
|
||||
end
|
||||
|
||||
pages = id ? WikiPage.where(id:) : unmigrated_wiki_pages
|
||||
revisions = WikiRevision.joins(wiki_page: :tag_name)
|
||||
.where(wiki_page_id: pages.select(:id))
|
||||
.includes(:created_user, wiki_page: { tag_name: :tag })
|
||||
.order(id: :desc).limit(200)
|
||||
json = revisions.map { |rev|
|
||||
{ revision_id: rev.id,
|
||||
pred: rev.base_revision_id,
|
||||
succ: nil,
|
||||
wiki_page: { id: rev.wiki_page_id,
|
||||
title: rev.wiki_page.title,
|
||||
deprecated_at: rev.wiki_page.deprecated_at },
|
||||
user: rev.created_user && { id: rev.created_user.id, name: rev.created_user.name },
|
||||
kind: rev.kind,
|
||||
message: rev.message,
|
||||
timestamp: rev.created_at }
|
||||
}
|
||||
json = []
|
||||
unless id
|
||||
json.concat(tag_group_changes(TagGroupVersion.all))
|
||||
json.concat(description_changes(TagDescription.where(language_code: 'ja')))
|
||||
@@ -351,6 +300,7 @@ class WikiPagesController < ApplicationController
|
||||
updated_at = version.created_at
|
||||
render json: {
|
||||
'id' => version.tag_group_id,
|
||||
'resource_type' => 'tag_group',
|
||||
'title' => "#{ TagGroupRepr::PREFIX }#{ representation.fetch('name') }",
|
||||
'deprecated_at' => nil,
|
||||
'body' => body,
|
||||
@@ -453,16 +403,6 @@ class WikiPagesController < ApplicationController
|
||||
.find_by(language_code: 'ja', tag_names: { language_code: 'ja', name: title })
|
||||
end
|
||||
|
||||
def unmigrated_wiki_pages
|
||||
descriptions = TagDescription.where(language_code: 'ja')
|
||||
|
||||
WikiPage
|
||||
.joins(:tag_name)
|
||||
.where.not('tag_names.name LIKE ?', "#{ TagGroupRepr::PREFIX }%")
|
||||
.where('tag_names.tag_id IS NULL OR tag_names.tag_id NOT IN (?)',
|
||||
descriptions.select(:tag_id))
|
||||
end
|
||||
|
||||
def description_changes descriptions
|
||||
versions = TagDescriptionVersion.where(language_code: 'ja',
|
||||
tag_id: descriptions.select(:tag_id))
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class ExternalTag < ApplicationRecord
|
||||
before_create { SharedResourceIdAllocator.assign!(self) }
|
||||
|
||||
enum :platform, nico: 'nico'
|
||||
validates :platform, presence: true, inclusion: { in: ExternalTag.platforms.keys }
|
||||
|
||||
|
||||
+10
-1
@@ -2,6 +2,8 @@ require 'set'
|
||||
|
||||
|
||||
class Tag < ApplicationRecord
|
||||
before_create { SharedResourceIdAllocator.assign!(self) }
|
||||
|
||||
class NicoTagNormalisationError < ArgumentError
|
||||
;
|
||||
end
|
||||
@@ -51,6 +53,7 @@ class Tag < ApplicationRecord
|
||||
has_many :tag_versions
|
||||
|
||||
has_many :tag_names
|
||||
has_many :tag_descriptions
|
||||
|
||||
attribute :version_no, :integer, default: 1
|
||||
|
||||
@@ -96,7 +99,13 @@ class Tag < ApplicationRecord
|
||||
|
||||
def deprecated? = deprecated_at?
|
||||
|
||||
def has_wiki = wiki_page.present?
|
||||
def has_description? language_code:
|
||||
if tag_descriptions.loaded?
|
||||
tag_descriptions.any? { _1.language_code == language_code }
|
||||
else
|
||||
tag_descriptions.exists?(language_code:)
|
||||
end
|
||||
end
|
||||
|
||||
def material_id = materials.first&.id
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
class TagDescription < ApplicationRecord
|
||||
before_create { SharedResourceIdAllocator.assign!(self) }
|
||||
|
||||
belongs_to :tag
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class TagGroup < ApplicationRecord
|
||||
before_create { SharedResourceIdAllocator.assign!(self) }
|
||||
|
||||
belongs_to :created_by_user, class_name: 'User', optional: true
|
||||
belongs_to :updated_by_user, class_name: 'User', optional: true
|
||||
|
||||
|
||||
@@ -3,21 +3,28 @@
|
||||
|
||||
module TagRepr
|
||||
BASE = { only: [:id, :category, :post_count, :created_at, :updated_at, :deprecated_at],
|
||||
methods: [:has_wiki, :material_id, :has_deerjikists] }.freeze
|
||||
methods: [:material_id, :has_deerjikists] }.freeze
|
||||
|
||||
module_function
|
||||
|
||||
def base tag, language_code: 'ja'
|
||||
tag.as_json(BASE).merge(name: name_for(tag, language_code),
|
||||
tag.as_json(BASE).merge('has_wiki' => tag.has_description?(language_code:),
|
||||
name: name_for(tag, language_code),
|
||||
aliases: tag.snapshot_aliases(language_code),
|
||||
parents: tag.parents.map { inline(_1, language_code:) })
|
||||
end
|
||||
|
||||
def inline tag, language_code: 'ja'
|
||||
tag.as_json(BASE).merge(name: name_for(tag, language_code), aliases: [], parents: [])
|
||||
tag.as_json(BASE).merge('has_wiki' => tag.has_description?(language_code:),
|
||||
name: name_for(tag, language_code), aliases: [], parents: [])
|
||||
end
|
||||
|
||||
def many(tags, language_code: 'ja') = tags.map { |tag| base(tag, language_code:) }
|
||||
def many tags, language_code: 'ja'
|
||||
records = tags.to_a
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records:, associations: [:tag_descriptions, { parents: :tag_descriptions }]).call
|
||||
records.map { |tag| base(tag, language_code:) }
|
||||
end
|
||||
|
||||
def name_for tag, language_code
|
||||
tag.name(language_code) || (tag.system? ? tag.name('ja') : nil)
|
||||
|
||||
@@ -13,6 +13,7 @@ module WikiPageRepr
|
||||
def tag_description description
|
||||
tag = description.tag
|
||||
{ 'id' => description.id,
|
||||
'resource_type' => 'tag_description',
|
||||
'tag_name_id' => tag.tag_name('ja')&.id,
|
||||
'body' => description.body,
|
||||
'created_user_id' => description.created_by_user_id,
|
||||
@@ -26,7 +27,7 @@ module WikiPageRepr
|
||||
end
|
||||
|
||||
def tag_group tag_group
|
||||
TagGroupRepr.tag_group(tag_group)
|
||||
TagGroupRepr.tag_group(tag_group).merge('resource_type' => 'tag_group')
|
||||
end
|
||||
|
||||
def many wiki_pages
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
require 'digest'
|
||||
|
||||
|
||||
class SharedResourceIdAllocator
|
||||
SPACES = {
|
||||
'tags' => ['tags', 'external_tags'],
|
||||
'wiki' => ['tag_descriptions', 'tag_groups'] }.freeze
|
||||
LOCK_TIMEOUT = 10
|
||||
|
||||
def self.assign! record
|
||||
space, tables = SPACES.find { |_name, names| names.include?(record.class.table_name) }
|
||||
raise ArgumentError, 'Unknown shared ID resource' unless tables
|
||||
|
||||
connection = record.class.connection
|
||||
transaction = record.class.current_transaction
|
||||
raise ActiveRecord::ActiveRecordError, 'Shared ID requires a transaction' unless transaction.open?
|
||||
|
||||
database = connection.pool.db_config.database
|
||||
name = "btrc:ids:#{ Digest::SHA256.hexdigest(database)[0, 16] }:#{ space }"
|
||||
quoted_name = connection.quote(name)
|
||||
acquired = record.class.uncached do
|
||||
connection.select_value("SELECT GET_LOCK(#{ quoted_name }, #{ LOCK_TIMEOUT })")
|
||||
end
|
||||
unless acquired.to_i == 1
|
||||
raise ActiveRecord::LockWaitTimeout, "Shared ID lock unavailable: #{ space }"
|
||||
end
|
||||
|
||||
release = lambda do
|
||||
result = record.class.uncached do
|
||||
connection.select_value("SELECT RELEASE_LOCK(#{ quoted_name })")
|
||||
end
|
||||
unless result.to_i == 1
|
||||
raise ActiveRecord::ActiveRecordError, "Shared ID lock release failed: #{ space }"
|
||||
end
|
||||
end
|
||||
begin
|
||||
transaction.after_commit(&release)
|
||||
transaction.after_rollback(&release)
|
||||
rescue StandardError
|
||||
release.call
|
||||
raise
|
||||
end
|
||||
|
||||
return if record.id.present?
|
||||
|
||||
# Locking reads see committed maxima even after earlier repeatable reads.
|
||||
maxima = record.class.uncached do
|
||||
tables.map do |table|
|
||||
quoted_table = connection.quote_table_name(table)
|
||||
connection.select_value(
|
||||
"SELECT id FROM #{ quoted_table } ORDER BY id DESC LIMIT 1 FOR UPDATE").to_i
|
||||
end
|
||||
end
|
||||
record.id = maxima.max + 1
|
||||
end
|
||||
end
|
||||
@@ -8,9 +8,9 @@ class TagDescriptionOperation
|
||||
tag_id: tag.id, language_code: LANGUAGE_CODE)
|
||||
|
||||
page = Wiki::CompatibilityWriter.create!(
|
||||
tag_name: tag.tag_name(LANGUAGE_CODE), body:, created_by_user:, message:)
|
||||
tag_name: compatibility_tag_name(tag), body:, created_by_user:, message:)
|
||||
revision = page.wiki_revisions.order(id: :desc).first
|
||||
record_version!(tag:, revision:, body:, user: created_by_user,
|
||||
record_version!(tag:, revision:, body: revision.body, user: created_by_user,
|
||||
description: nil)
|
||||
page
|
||||
end
|
||||
@@ -22,7 +22,20 @@ class TagDescriptionOperation
|
||||
tag.lock!
|
||||
description = TagDescription.lock.find_by!(
|
||||
tag_id: tag.id, language_code: LANGUAGE_CODE)
|
||||
page = WikiPage.lock.find(description.id)
|
||||
tag_name = compatibility_tag_name(tag)
|
||||
page = WikiPage.lock.find_by(tag_name_id: tag_name.id)
|
||||
unless page
|
||||
versions = TagDescriptionVersion.where(tag_id: tag.id, language_code: LANGUAGE_CODE)
|
||||
if base_revision_id.present? && versions.maximum(:id) != base_revision_id.to_i
|
||||
raise Wiki::Commit::Conflict, '競合が発生してゐます.'
|
||||
end
|
||||
page = Wiki::CompatibilityWriter.create!(
|
||||
tag_name:, body:, created_by_user: updated_by_user, message:)
|
||||
revision = page.current_revision
|
||||
record_version!(tag:, revision:, body: revision.body,
|
||||
user: updated_by_user, description:)
|
||||
next revision
|
||||
end
|
||||
revision = Wiki::CompatibilityWriter.update!(
|
||||
page:, body:, updated_by_user:, message:,
|
||||
base_revision_id:)
|
||||
@@ -34,6 +47,11 @@ class TagDescriptionOperation
|
||||
end
|
||||
end
|
||||
|
||||
def self.compatibility_tag_name tag
|
||||
tag.tag_name(LANGUAGE_CODE) || TagName.find_by!(id: tag.tag_name_id,
|
||||
language_code: LANGUAGE_CODE)
|
||||
end
|
||||
|
||||
def self.record_version! tag:, revision:, body:, user:, description:
|
||||
version_no = description ? description.version_no + 1 : 1
|
||||
TagDescriptionVersion.create!(
|
||||
@@ -44,7 +62,7 @@ class TagDescriptionOperation
|
||||
description.update!(body:, version_no:, updated_by_user_id: user.id)
|
||||
else
|
||||
TagDescription.create!(
|
||||
id: revision.wiki_page_id, tag_id: tag.id,
|
||||
tag_id: tag.id,
|
||||
language_code: LANGUAGE_CODE, version_no:, body:,
|
||||
created_by_user_id: user.id, updated_by_user_id: user.id)
|
||||
end
|
||||
|
||||
@@ -349,7 +349,7 @@ class TagGroupOperation
|
||||
tag_name.primary_flg = true
|
||||
tag_name.auto_generated = false
|
||||
tag_name.save!
|
||||
Wiki::Commit.create_legacy_content!(tag_name:, body:, created_by_user: actor)
|
||||
Wiki::CompatibilityWriter.create!(tag_name:, body:, created_by_user: actor)
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
@@ -8,12 +8,13 @@ module Wiki
|
||||
end
|
||||
|
||||
def self.create_content! tag_name:, body:, created_by_user:, message: nil
|
||||
if tag_name.tag && tag_name.language_code == 'ja'
|
||||
if tag_name.tag && tag_name.language_code == 'ja' && !tag_name.name.include?(':')
|
||||
return TagDescriptionOperation.create!(
|
||||
tag: tag_name.tag, body:, created_by_user:, message:)
|
||||
end
|
||||
|
||||
create_legacy_content!(tag_name:, body:, created_by_user:, message:)
|
||||
tag_name.errors.add(:base, :invalid)
|
||||
raise ActiveRecord::RecordInvalid, tag_name
|
||||
end
|
||||
|
||||
def self.create_legacy_content! tag_name:, body:, created_by_user:, message: nil
|
||||
@@ -42,14 +43,17 @@ module Wiki
|
||||
end
|
||||
|
||||
def self.content! page:, body:, created_user:, message: nil, base_revision_id: nil
|
||||
description = TagDescription.find_by(id: page.id)
|
||||
if description
|
||||
description = TagDescription.find_by(tag_id: page.tag_name.tag_id, language_code: 'ja')
|
||||
description ||= TagDescription.joins(:tag).find_by(
|
||||
tags: { tag_name_id: page.tag_name_id }, language_code: 'ja')
|
||||
if description && !page.title.include?(':')
|
||||
return TagDescriptionOperation.update!(
|
||||
tag: description.tag, body:, updated_by_user: created_user,
|
||||
message:, base_revision_id:)
|
||||
end
|
||||
|
||||
legacy_content!(page:, body:, created_user:, message:, base_revision_id:)
|
||||
page.errors.add(:base, :invalid)
|
||||
raise ActiveRecord::RecordInvalid, page
|
||||
end
|
||||
|
||||
def self.legacy_content! page:, body:, created_user:, message: nil,
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
module Wiki
|
||||
class CompatibilityWriter
|
||||
def self.create! tag_name:, body:, created_by_user:, message: nil
|
||||
Commit.create_legacy_content!(
|
||||
tag_name:, body:, created_by_user:, message:)
|
||||
ApplicationRecord.transaction do
|
||||
tag_name.lock!
|
||||
page = WikiPage.lock.find_by(tag_name_id: tag_name.id)
|
||||
if page
|
||||
update!(page:, body:, updated_by_user: created_by_user, message:)
|
||||
page
|
||||
else
|
||||
Commit.create_legacy_content!(tag_name:, body:, created_by_user:, message:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.update! page:, body:, updated_by_user:, message: nil,
|
||||
@@ -23,7 +31,9 @@ module Wiki
|
||||
end
|
||||
end
|
||||
|
||||
return if Commit.normalise_body(page.body) == normalised
|
||||
if Commit.normalise_body(page.body) == normalised && page.wiki_revisions.exists?
|
||||
return
|
||||
end
|
||||
|
||||
Commit.legacy_content!(
|
||||
page:, body: normalised, created_user: updated_by_user, message:,
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする