コミットを比較
7
コミット
| 作成者 | SHA1 | 日付 | |
|---|---|---|---|
|
|
115a14205b | ||
|
|
1b1130ccd9 | ||
|
|
f6d3dd1c10 | ||
|
|
b0df11c500 | ||
|
|
886128a7a8 | ||
|
|
6d1a8f0444 | ||
|
|
6f0442d633 |
@@ -92,4 +92,6 @@ class ApplicationController < ActionController::API
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
def resolve_locale! = Locale.find_by(code: params[:locale]) || Locale.nipponese
|
||||
end
|
||||
|
||||
@@ -72,6 +72,7 @@ class MaterialsController < ApplicationController
|
||||
return head :unauthorized unless current_user
|
||||
return head :forbidden unless current_user.gte_member?
|
||||
|
||||
locale = resolve_locale!
|
||||
tag_name_raw = params[:tag].to_s.strip
|
||||
file = params[:file]
|
||||
file_sha256 = MaterialFileSha256.from_upload(file)
|
||||
@@ -89,7 +90,7 @@ class MaterialsController < ApplicationController
|
||||
|
||||
begin
|
||||
Material.transaction do
|
||||
tag = resolve_material_tag!(tag_name_raw)
|
||||
tag = resolve_material_tag!(locale, tag_name_raw)
|
||||
material = Material.new(tag:, url:,
|
||||
created_by_user: current_user,
|
||||
updated_by_user: current_user)
|
||||
@@ -236,10 +237,8 @@ class MaterialsController < ApplicationController
|
||||
nil
|
||||
end
|
||||
|
||||
def resolve_material_tag! tag_name_raw
|
||||
tag_name = TagName.find_or_create_by!(name: tag_name_raw)
|
||||
tag = tag_name.tag
|
||||
tag || Tag.create!(tag_name:, category: :material)
|
||||
def resolve_material_tag! locale, tag_name_raw
|
||||
Tag.find_or_create_by_tag_name!(locale, tag_name_raw, category: :material)
|
||||
end
|
||||
|
||||
def material_index_needs_tag_name? filters
|
||||
|
||||
@@ -70,6 +70,8 @@ class NicoTagsController < ApplicationController
|
||||
return head :unauthorized unless current_user
|
||||
return head :forbidden unless current_user.gte_member?
|
||||
|
||||
locale = resolve_locale!
|
||||
|
||||
id = params[:id].to_i
|
||||
|
||||
tag = Tag.find(id)
|
||||
@@ -79,8 +81,9 @@ class NicoTagsController < ApplicationController
|
||||
linked_tags = nil
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
linked_tags = Tag.normalise_tags!(linked_tag_names, with_tagme: false,
|
||||
with_no_deerjikist: false)
|
||||
linked_tags = Tag.normalise_tags!(locale, linked_tag_names,
|
||||
with_tagme: false,
|
||||
with_no_deerjikist: false)
|
||||
if linked_tags.any? { |t| t.nico? }
|
||||
raise Tag::NicoTagNormalisationError
|
||||
end
|
||||
|
||||
@@ -308,6 +308,7 @@ class PostsController < ApplicationController
|
||||
base_version_no = parse_base_version_no
|
||||
return render_bad_request('base_version_no は必須です.') if !(force) && !(base_version_no)
|
||||
|
||||
locale = Locale.find_by(code: params[:locale].presence) || Locale.nipponese
|
||||
title = params[:title].presence
|
||||
tag_names = params[:tags].to_s.split
|
||||
original_created_from = params[:original_created_from]
|
||||
@@ -329,7 +330,8 @@ class PostsController < ApplicationController
|
||||
base_snapshot = post_snapshot_from_version(base_version)
|
||||
current_snapshot = post_snapshot_from_record(post)
|
||||
end
|
||||
incoming_snapshot = post_incoming_snapshot(title:,
|
||||
incoming_snapshot = post_incoming_snapshot(locale:,
|
||||
title:,
|
||||
original_created_from:,
|
||||
original_created_before:,
|
||||
tag_names:,
|
||||
@@ -358,7 +360,7 @@ class PostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
apply_post_snapshot!(post, snapshot_to_apply)
|
||||
apply_post_snapshot!(locale, post, snapshot_to_apply)
|
||||
end
|
||||
|
||||
return render json: conflict_json, status: :conflict if conflict_json
|
||||
@@ -685,12 +687,13 @@ class PostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def post_incoming_snapshot title:, original_created_from:, original_created_before:,
|
||||
def post_incoming_snapshot locale:, title:, original_created_from:, original_created_before:,
|
||||
tag_names:, video_ms_param:, duration_param:, parent_post_ids:
|
||||
validate_original_created_values!(original_created_from, original_created_before)
|
||||
Tag.normalise_tags!(tag_names, with_tagme: false, deny_deprecated: true,
|
||||
with_sections: true) =>
|
||||
{ tags:, sections: }
|
||||
Tag.normalise_tags!(locale, tag_names,
|
||||
with_tagme: false,
|
||||
deny_deprecated: true,
|
||||
with_sections: true) => { tags:, sections: }
|
||||
|
||||
tags = Tag.expand_parent_tags(tags).reject(&:deprecated?)
|
||||
video_ms = normalise_video_ms(tags, video_ms_param:, duration_param:)
|
||||
@@ -825,7 +828,7 @@ class PostsController < ApplicationController
|
||||
(added_by_current & removed_by_me).present? || (removed_by_current & added_by_me).present?
|
||||
end
|
||||
|
||||
def apply_post_snapshot! post, snapshot
|
||||
def apply_post_snapshot! locale, post, snapshot
|
||||
PostVersionRecorder.ensure_snapshot!(post, created_by_user: current_user)
|
||||
|
||||
post.update!(title: snapshot[:title],
|
||||
@@ -833,10 +836,10 @@ class PostsController < ApplicationController
|
||||
original_created_from: snapshot[:original_created_from],
|
||||
original_created_before: snapshot[:original_created_before])
|
||||
|
||||
Tag.normalise_tags!(snapshot[:tag_names], with_tagme: false,
|
||||
deny_deprecated: true,
|
||||
with_sections: true) =>
|
||||
{ tags: editable_tags, sections: }
|
||||
Tag.normalise_tags!(locale, snapshot[:tag_names],
|
||||
with_tagme: false,
|
||||
deny_deprecated: true,
|
||||
with_sections: true) => { tags: editable_tags, sections: }
|
||||
TagVersioning.record_tag_snapshots!(editable_tags, created_by_user: current_user)
|
||||
|
||||
readonly_tags = post.tags.nico.to_a
|
||||
|
||||
@@ -278,6 +278,8 @@ class TagsController < ApplicationController
|
||||
|
||||
return unless validate_tag_rename(tag, name)
|
||||
|
||||
locale = resolve_locale!
|
||||
|
||||
alias_names = params[:aliases].to_s.split.uniq
|
||||
parent_names = params[:parent_tags].to_s.split.uniq
|
||||
deprecated = bool?(:deprecated)
|
||||
@@ -308,7 +310,7 @@ class TagsController < ApplicationController
|
||||
alias_names.delete(name)
|
||||
|
||||
update_aliases!(tag, alias_names)
|
||||
update_parent_tags!(tag, parent_names)
|
||||
update_parent_tags!(locale, tag, parent_names)
|
||||
|
||||
tag.reload
|
||||
|
||||
@@ -659,10 +661,11 @@ class TagsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def update_parent_tags! tag, parent_names
|
||||
parent_tags = Tag.normalise_tags!(parent_names, with_tagme: false,
|
||||
with_no_deerjikist: false,
|
||||
deny_nico: true)
|
||||
def update_parent_tags! locale, tag, parent_names
|
||||
parent_tags = Tag.normalise_tags!(locale, parent_names,
|
||||
with_tagme: false,
|
||||
with_no_deerjikist: false,
|
||||
deny_nico: true)
|
||||
|
||||
old_parent_tags = tag.parents.to_a
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class Language < ApplicationRecord
|
||||
has_many :languages, class_name: 'Locale', foreign_key: :language_code
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
class Locale < ApplicationRecord
|
||||
after_create_commit :generate_tag_names!
|
||||
|
||||
belongs_to :language, foreign_key: :language_code, primary_key: :code
|
||||
belongs_to :script, foreign_key: :script_code, primary_key: :code
|
||||
|
||||
def self.nipponese = Locale.find('ja')
|
||||
|
||||
private
|
||||
|
||||
def generate_tag_names!
|
||||
tag_ids = TagName.where(language_code:, primary_flg: true).pluck(:tag_id)
|
||||
Tag.where.not(id: tag_ids).find_each do
|
||||
TagName.create!(tag_id: _1.id,
|
||||
language_code:,
|
||||
name: TagName.generate_name(self, _1, _1.name),
|
||||
script_code:,
|
||||
primary_flg: true,
|
||||
# TODO: 公証実装したら書く.
|
||||
# auto_generated: true,
|
||||
canonical_id: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
class Script < ApplicationRecord
|
||||
;
|
||||
end
|
||||
+32
-17
@@ -52,6 +52,7 @@ class Tag < ApplicationRecord
|
||||
has_many :tag_versions
|
||||
has_many :nico_tag_versions
|
||||
|
||||
has_many :tag_names
|
||||
belongs_to :tag_name
|
||||
delegate :wiki_page, to: :tag_name
|
||||
|
||||
@@ -101,18 +102,20 @@ class Tag < ApplicationRecord
|
||||
|
||||
def has_deerjikists = deerjikists.loaded? ? deerjikists.any? : deerjikists.exists?
|
||||
|
||||
def self.tagme = find_or_create_by_tag_name!('タグ希望', category: :meta)
|
||||
def self.bot = find_or_create_by_tag_name!('bot操作', category: :meta)
|
||||
def self.no_deerjikist = find_or_create_by_tag_name!('ニジラー情報不詳', category: :meta)
|
||||
def self.video = find_or_create_by_tag_name!('動画', category: :meta)
|
||||
def self.niconico = find_or_create_by_tag_name!('ニコニコ', category: :meta)
|
||||
def self.youtube = find_or_create_by_tag_name!('YouTube', category: :meta)
|
||||
def self.tagme = find_or_create_by_tag_name!(Locale.nipponese, 'タグ希望', category: :meta)
|
||||
def self.bot = find_or_create_by_tag_name!(Locale.nipponese, 'bot操作', category: :meta)
|
||||
def self.no_deerjikist =
|
||||
find_or_create_by_tag_name!(Locale.nipponese, 'ニジラー情報不詳', category: :meta)
|
||||
def self.video = find_or_create_by_tag_name!(Locale.nipponese, '動画', category: :meta)
|
||||
def self.niconico = find_or_create_by_tag_name!(Locale.nipponese, 'ニコニコ', category: :meta)
|
||||
def self.youtube = find_or_create_by_tag_name!(Locale.nipponese, 'YouTube', category: :meta)
|
||||
|
||||
def self.normalise_tags! tag_names, with_tagme: true,
|
||||
with_no_deerjikist: true,
|
||||
deny_nico: true,
|
||||
deny_deprecated: false,
|
||||
with_sections: false
|
||||
def self.normalise_tags! locale, tag_names,
|
||||
with_tagme: true,
|
||||
with_no_deerjikist: true,
|
||||
deny_nico: true,
|
||||
deny_deprecated: false,
|
||||
with_sections: false
|
||||
if deny_nico && tag_names.any? { |n| n.downcase.start_with?('nico:') }
|
||||
raise NicoTagNormalisationError
|
||||
end
|
||||
@@ -141,7 +144,7 @@ class Tag < ApplicationRecord
|
||||
|
||||
name = TagName.canonicalise(name).first
|
||||
|
||||
find_or_create_by_tag_name!(name, category: (cat || :general)).tap do |tag|
|
||||
find_or_create_by_tag_name!(locale, name, category: (cat || :general)).tap do |tag|
|
||||
if deny_deprecated && tag.deprecated?
|
||||
raise DeprecatedTagNormalisationError, [tag.name]
|
||||
end
|
||||
@@ -229,13 +232,25 @@ class Tag < ApplicationRecord
|
||||
[left_end_ms, right_end_ms].max
|
||||
end
|
||||
|
||||
def self.find_or_create_by_tag_name! name, category:
|
||||
tn = TagName.find_or_create_by!(name: name.to_s.strip)
|
||||
tn = tn.canonical if tn.canonical_id?
|
||||
def self.find_or_create_by_tag_name! locale, name, category:
|
||||
language_code = locale.language_code
|
||||
name = name.to_s.strip
|
||||
|
||||
Tag.find_or_create_by!(tag_name_id: tn.id) do |t|
|
||||
t.category = category
|
||||
tn = TagName.find_or_create_by!(language_code:, name:) do
|
||||
_1.script_code = locale.script_code
|
||||
_1.primary_flg = true
|
||||
end
|
||||
|
||||
tag = tn.tag
|
||||
if tag
|
||||
tag.update!(tag_name_id: tn.id) if tag.tag_name_id != tn.id
|
||||
return tag
|
||||
end
|
||||
|
||||
tag = Tag.create!(tag_name: tn, category:)
|
||||
tn.update!(tag:)
|
||||
|
||||
tag
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
retry
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class TagName < ApplicationRecord
|
||||
has_one :tag
|
||||
belongs_to :tag, optional: true
|
||||
has_one :wiki_page
|
||||
|
||||
belongs_to :canonical, class_name: 'TagName', optional: true
|
||||
@@ -21,6 +21,12 @@ class TagName < ApplicationRecord
|
||||
names.map { |name| tns[name]&.canonical&.name || name }.uniq
|
||||
end
|
||||
|
||||
def self.generate_name locale, tag, name
|
||||
# TODO: 言語ごとの自動命名ロジック完成したら書く.
|
||||
|
||||
"Tag_##{ tag.id }"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def canonical_must_be_canonical
|
||||
|
||||
@@ -9,7 +9,7 @@ class PostCreator
|
||||
@field_warnings = { }
|
||||
end
|
||||
|
||||
def create!
|
||||
def create!(locale)
|
||||
thumbnail_attachment = prepare_thumbnail_attachment
|
||||
post = Post.new(title: @attributes[:title].presence,
|
||||
url: @attributes[:url],
|
||||
@@ -25,7 +25,7 @@ class PostCreator
|
||||
post_tags = planned_post_tags
|
||||
sections = planned_sections
|
||||
TagVersioning.record_tag_snapshots!(snapshot_tags, created_by_user: @actor)
|
||||
post.video_ms = planned_video_ms
|
||||
post.video_ms = planned_video_ms(locale)
|
||||
post.save!
|
||||
sync_post_tags!(post, post_tags, sections)
|
||||
sync_parent_posts!(post, planned_parent_post_ids)
|
||||
@@ -53,15 +53,15 @@ class PostCreator
|
||||
|
||||
def planned_parent_post_ids = planned_create_attributes[:normalised_parent_post_ids]
|
||||
|
||||
def planned_video_ms
|
||||
planned_create_attributes[:video_ms]
|
||||
def planned_video_ms locale
|
||||
planned_create_attributes(locale)[:video_ms]
|
||||
end
|
||||
|
||||
def planned_create_attributes
|
||||
def planned_create_attributes locale
|
||||
@planned_create_attributes ||= begin
|
||||
if @attributes.key?(:snapshot_tag_specs)
|
||||
snapshot_tags = materialise_tags(@attributes[:snapshot_tag_specs] || [])
|
||||
post_tags = materialise_tags(@attributes[:post_tag_specs] || [])
|
||||
snapshot_tags = materialise_tags(locale, @attributes[:snapshot_tag_specs] || [])
|
||||
post_tags = materialise_tags(locale, @attributes[:post_tag_specs] || [])
|
||||
{
|
||||
snapshot_tags: snapshot_tags,
|
||||
post_tags: post_tags,
|
||||
@@ -92,13 +92,13 @@ class PostCreator
|
||||
video_ms: plan[:video_ms] }
|
||||
end
|
||||
|
||||
def materialise_tags specs
|
||||
def materialise_tags locale, specs
|
||||
Array(specs).each_with_object({ }) do |spec, tags|
|
||||
name = spec[:name] || spec['name']
|
||||
category = spec[:category] || spec['category']
|
||||
next if name.blank? || category.blank?
|
||||
|
||||
tag = Tag.find_or_create_by_tag_name!(name, category:)
|
||||
tag = Tag.find_or_create_by_tag_name!(locale, name, category:)
|
||||
tag.update!(category:) if tag.category.to_sym != category.to_sym
|
||||
tags[name] ||= tag
|
||||
end.values
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class CreateLanguages < ActiveRecord::Migration[8.0]
|
||||
def up
|
||||
create_table :languages, id: { type: :string, limit: 16 }, primary_key: :code do |t|
|
||||
t.string :name, null: false
|
||||
t.datetime :deprecated_at, index: true
|
||||
t.datetime :created_at, null: false
|
||||
end
|
||||
|
||||
execute <<~SQL
|
||||
INSERT INTO
|
||||
languages(code, name, created_at)
|
||||
VALUES
|
||||
('ja', '日本語', #{ connection.quote Time.current })
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :languages
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
class CreateScripts < ActiveRecord::Migration[8.0]
|
||||
def up
|
||||
create_table :scripts, id: { type: 'CHAR(4)' }, primary_key: :code do |t|
|
||||
t.string :name, null: false
|
||||
t.datetime :deprecated_at, index: true
|
||||
t.datetime :created_at, null: false
|
||||
end
|
||||
|
||||
execute <<~SQL
|
||||
INSERT INTO
|
||||
scripts(code, name, created_at)
|
||||
VALUES
|
||||
('Jpan', '漢字および仮名文字', #{ connection.quote Time.current })
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :scripts
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
class CreateLocales < ActiveRecord::Migration[8.0]
|
||||
def up
|
||||
create_table :locales, id: { type: :string, limit: 32 }, primary_key: :code do |t|
|
||||
t.string :language_code, limit: 16, null: false, index: true
|
||||
t.column :script_code, 'CHAR(4)', null: false
|
||||
t.string :name, null: false
|
||||
t.datetime :deprecated_at, index: true
|
||||
t.datetime :created_at, null: false
|
||||
|
||||
t.foreign_key :languages, column: :language_code, primary_key: :code
|
||||
t.foreign_key :scripts, column: :script_code, primary_key: :code
|
||||
end
|
||||
|
||||
execute <<~SQL
|
||||
INSERT INTO
|
||||
locales(code, language_code, script_code, name, created_at)
|
||||
VALUES
|
||||
('ja', 'ja', 'Jpan', '日本語', #{ connection.quote Time.current })
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :locales
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
class AddColumnsToTagNames < ActiveRecord::Migration[8.0]
|
||||
def up
|
||||
add_reference :tag_names, :tag, after: :id, foreign_key: true
|
||||
add_column :tag_names, :language_code, :string,
|
||||
limit: 16, null: false, after: :tag_id, default: 'ja'
|
||||
add_column :tag_names, :script_code, 'CHAR(4)',
|
||||
null: false, after: :name, default: 'Jpan'
|
||||
add_column :tag_names, :primary_flg, :boolean,
|
||||
null: false, after: :script_code, default: true
|
||||
|
||||
add_foreign_key :tag_names, :languages, column: :language_code, primary_key: :code
|
||||
add_foreign_key :tag_names, :scripts, column: :script_code, primary_key: :code
|
||||
|
||||
remove_index :tag_names, :name
|
||||
add_index :tag_names, [:language_code, :name], unique: true
|
||||
|
||||
change_column_default :tag_names, :language_code, from: 'ja', to: nil
|
||||
change_column_default :tag_names, :script_code, from: 'Jpan', to: nil
|
||||
|
||||
execute <<~SQL
|
||||
UPDATE
|
||||
tag_names tn
|
||||
LEFT JOIN
|
||||
tags AS t
|
||||
ON
|
||||
t.tag_name_id = COALESCE(tn.canonical_id, tn.id)
|
||||
SET
|
||||
tn.tag_id = t.id
|
||||
, tn.primary_flg = CASE
|
||||
WHEN tn.canonical_id IS NULL THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END
|
||||
SQL
|
||||
|
||||
change_column_default :tag_names, :primary_flg, from: true, to: nil
|
||||
|
||||
add_column :tag_names, :primary_tag_id, :bigint,
|
||||
as: 'CASE WHEN primary_flg THEN tag_id ELSE NULL END'
|
||||
add_index :tag_names, [:primary_tag_id, :language_code], unique: true
|
||||
end
|
||||
|
||||
def down
|
||||
remove_index :tag_names, [:primary_tag_id, :language_code]
|
||||
remove_column :tag_names, :primary_tag_id
|
||||
|
||||
remove_foreign_key :tag_names, column: :language_code
|
||||
remove_foreign_key :tag_names, column: :script_code
|
||||
|
||||
remove_index :tag_names, [:language_code, :name]
|
||||
add_index :tag_names, :name, unique: true
|
||||
|
||||
remove_column :tag_names, :primary_flg
|
||||
remove_column :tag_names, :script_code
|
||||
remove_column :tag_names, :language_code
|
||||
remove_reference :tag_names, :tag, foreign_key: true
|
||||
end
|
||||
end
|
||||
@@ -124,7 +124,7 @@ namespace :nico do
|
||||
|
||||
datum['tags'].each do |raw|
|
||||
name = TagNameSanitisationRule.sanitise("nico:#{ raw }")
|
||||
tag = Tag.find_or_create_by_tag_name!(name, category: :nico)
|
||||
tag = Tag.find_or_create_by_tag_name!(Locale.nipponese, name, category: :nico)
|
||||
|
||||
event_type = tag.nico_tag_versions.exists? ? :update : :create
|
||||
NicoTagVersionRecorder.record!(tag:, event_type:, created_by_user: nil)
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする