このコミットが含まれているのは:
@@ -200,14 +200,45 @@ class TagsController < ApplicationController
|
|||||||
.find_by(id: params[:id])
|
.find_by(id: params[:id])
|
||||||
return head :not_found unless tag
|
return head :not_found unless tag
|
||||||
|
|
||||||
|
rows = normalise_deerjikist_rows(tag)
|
||||||
|
return if performed?
|
||||||
|
|
||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
tag.deerjikists = []
|
tag.lock!
|
||||||
params[:_json].each.with_index do |item, i|
|
|
||||||
platform = item[:platform]
|
requested_keys = rows.map { |row| [row[:platform], row[:code]] }.uniq
|
||||||
code = normalise_deerjikist_code(platform, item[:code])
|
row_indexes_by_key = rows_by_key(rows)
|
||||||
deerjikist = Deerjikist.find_or_initialize_by(platform:, code:)
|
locked_deerjikists = lock_deerjikists_for_tag_update(tag.id, requested_keys)
|
||||||
deerjikist.tag = tag
|
current_deerjikists = locked_deerjikists.filter { |deerjikist|
|
||||||
render_deerjikist_form_record_invalid(deerjikist, i) unless deerjikist.save
|
deerjikist.tag_id == tag.id
|
||||||
|
}
|
||||||
|
requested_deerjikists = locked_deerjikists.filter { |deerjikist|
|
||||||
|
row_indexes_by_key.key?([deerjikist.platform, deerjikist.code])
|
||||||
|
}
|
||||||
|
|
||||||
|
render_deerjikist_conflicts(requested_deerjikists, row_indexes_by_key, tag)
|
||||||
|
raise ActiveRecord::Rollback if performed?
|
||||||
|
|
||||||
|
requested_keys_set = requested_keys.to_set
|
||||||
|
current_deerjikists.each do |deerjikist|
|
||||||
|
key = [deerjikist.platform, deerjikist.code]
|
||||||
|
deerjikist.destroy! unless requested_keys_set.include?(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
existing_keys = requested_deerjikists.to_h { |deerjikist|
|
||||||
|
[[deerjikist.platform, deerjikist.code], true]
|
||||||
|
}
|
||||||
|
requested_keys.each do |platform, code|
|
||||||
|
next if existing_keys[[platform, code]]
|
||||||
|
|
||||||
|
deerjikist = Deerjikist.new(platform:, code:, tag:)
|
||||||
|
row_index = row_indexes_by_key[[platform, code]].first
|
||||||
|
begin
|
||||||
|
render_deerjikist_form_record_invalid(deerjikist, row_index) unless deerjikist.save
|
||||||
|
rescue ActiveRecord::RecordNotUnique
|
||||||
|
conflicts = lock_deerjikists_for_tag_update(tag.id, [[platform, code]])
|
||||||
|
render_deerjikist_conflicts(conflicts, row_indexes_by_key, tag)
|
||||||
|
end
|
||||||
raise ActiveRecord::Rollback if performed?
|
raise ActiveRecord::Rollback if performed?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -653,6 +684,7 @@ class TagsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def normalise_deerjikist_code platform, code
|
def normalise_deerjikist_code platform, code
|
||||||
|
code = code.to_s
|
||||||
return code if platform != 'youtube' || code[0] != '@'
|
return code if platform != 'youtube' || code[0] != '@'
|
||||||
|
|
||||||
url = "https://www.youtube.com/#{ code }"
|
url = "https://www.youtube.com/#{ code }"
|
||||||
@@ -669,6 +701,82 @@ class TagsController < ApplicationController
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalise_deerjikist_rows tag
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
params[:_json].each.with_index do |item, index|
|
||||||
|
platform = item[:platform]
|
||||||
|
unless Deerjikist.platforms.key?(platform)
|
||||||
|
render_deerjikist_platform_invalid(index)
|
||||||
|
return rows
|
||||||
|
end
|
||||||
|
|
||||||
|
code = normalise_deerjikist_code(platform, item[:code])
|
||||||
|
deerjikist = Deerjikist.new(platform:, code:, tag:)
|
||||||
|
unless deerjikist.valid?
|
||||||
|
render_deerjikist_form_record_invalid(deerjikist, index)
|
||||||
|
return rows
|
||||||
|
end
|
||||||
|
|
||||||
|
rows << { index:, platform:, code: }
|
||||||
|
end
|
||||||
|
|
||||||
|
rows
|
||||||
|
end
|
||||||
|
|
||||||
|
def lock_deerjikists_for_tag_update tag_id, keys
|
||||||
|
clauses = ['tag_id = ?']
|
||||||
|
values = [tag_id]
|
||||||
|
|
||||||
|
keys.each do |platform, code|
|
||||||
|
clauses << '(platform = ? AND code = ?)'
|
||||||
|
values << platform << code
|
||||||
|
end
|
||||||
|
|
||||||
|
Deerjikist
|
||||||
|
.where(clauses.join(' OR '), *values)
|
||||||
|
.order(:platform, :code)
|
||||||
|
.lock
|
||||||
|
.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_deerjikist_conflicts deerjikists, row_indexes_by_key, tag
|
||||||
|
conflicts = deerjikists.filter { |deerjikist| deerjikist.tag_id != tag.id }
|
||||||
|
return if conflicts.empty?
|
||||||
|
|
||||||
|
tag_names_by_id = Tag
|
||||||
|
.joins(:tag_name)
|
||||||
|
.where(id: conflicts.map(&:tag_id).uniq)
|
||||||
|
.pluck('tags.id', 'tag_names.name')
|
||||||
|
.to_h
|
||||||
|
fields = { }
|
||||||
|
|
||||||
|
conflicts.each do |deerjikist|
|
||||||
|
message = "この情報は既に「#{ tag_names_by_id[deerjikist.tag_id] }」に紐づいてゐます."
|
||||||
|
row_indexes_by_key[[deerjikist.platform, deerjikist.code]].each do |index|
|
||||||
|
field = :"deerjikists.#{ index }.code"
|
||||||
|
fields[field] ||= []
|
||||||
|
fields[field] << message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
render_validation_error fields:
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_deerjikist_platform_invalid index
|
||||||
|
render_validation_error fields: {
|
||||||
|
:"deerjikists.#{ index }.platform" => ['値が不正です.'],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def rows_by_key rows
|
||||||
|
rows.each_with_object({ }) do |row, result|
|
||||||
|
key = [row[:platform], row[:code]]
|
||||||
|
result[key] ||= []
|
||||||
|
result[key] << row[:index]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def render_deerjikist_form_record_invalid deerjikist, index
|
def render_deerjikist_form_record_invalid deerjikist, index
|
||||||
fields = { }
|
fields = { }
|
||||||
|
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする