105 行
3.5 KiB
Ruby
105 行
3.5 KiB
Ruby
class PostCreator
|
|
class VideoMsParseError < ArgumentError; end
|
|
|
|
attr_reader :field_warnings
|
|
|
|
def initialize actor:, attributes:
|
|
@actor = actor
|
|
@attributes = attributes.symbolize_keys
|
|
@field_warnings = { }
|
|
end
|
|
|
|
def create!
|
|
thumbnail_attachment = prepare_thumbnail_attachment
|
|
post = Post.new(title: @attributes[:title].presence,
|
|
url: @attributes[:url],
|
|
thumbnail_base: @attributes[:thumbnail_base].presence,
|
|
uploaded_user: @actor,
|
|
original_created_from: @attributes[:original_created_from].presence,
|
|
original_created_before: @attributes[:original_created_before].presence)
|
|
|
|
ApplicationRecord.transaction do
|
|
post.save!
|
|
post.thumbnail.attach(thumbnail_attachment) if thumbnail_attachment.present?
|
|
tags = planned_tags
|
|
sections = planned_sections
|
|
TagVersioning.record_tag_snapshots!(tags, created_by_user: @actor)
|
|
post.video_ms = planned_video_ms
|
|
post.save!
|
|
sync_post_tags!(post, tags, sections)
|
|
sync_parent_posts!(post, planned_parent_post_ids)
|
|
PostVersionRecorder.record!(post:, event_type: :create, created_by_user: @actor)
|
|
end
|
|
post
|
|
rescue StandardError
|
|
post&.thumbnail&.purge if post&.thumbnail&.attached?
|
|
raise
|
|
end
|
|
|
|
private
|
|
|
|
def prepare_thumbnail_attachment
|
|
PostThumbnailAttachmentBuilder.build(
|
|
thumbnail: @attributes[:thumbnail],
|
|
thumbnail_base: @attributes[:thumbnail_base].presence)
|
|
end
|
|
|
|
def planned_tags = planned_create_attributes[:normalised_tags]
|
|
|
|
def planned_sections = planned_create_attributes[:tag_sections]
|
|
|
|
def planned_parent_post_ids = planned_create_attributes[:normalised_parent_post_ids]
|
|
|
|
def planned_video_ms
|
|
planned_create_attributes[:video_ms]
|
|
end
|
|
|
|
def planned_create_attributes
|
|
@planned_create_attributes ||= begin
|
|
if @attributes.key?(:normalised_tags)
|
|
{
|
|
normalised_tags: @attributes[:normalised_tags],
|
|
tag_sections: @attributes[:tag_sections] || { },
|
|
normalised_parent_post_ids: @attributes[:normalised_parent_post_ids] || [],
|
|
video_ms: @attributes[:video_ms] }
|
|
else
|
|
PostCreatePlan.new(attributes: @attributes).build!
|
|
end
|
|
end
|
|
end
|
|
|
|
def sync_post_tags! post, desired_tags, sections
|
|
desired_ids = desired_tags.map(&:id).to_set
|
|
current_ids = post.tags.pluck(:id).to_set
|
|
Tag.where(id: desired_ids - current_ids).find_each do |tag|
|
|
PostTag.create_or_find_by!(post:, tag:, created_user: @actor)
|
|
end
|
|
PostTagSection.where(post_id: post.id).destroy_all
|
|
sections.each do |tag_id, ranges|
|
|
ranges.each do |begin_ms, end_ms|
|
|
PostTagSection.create!(post_id: post.id,
|
|
tag_id:,
|
|
begin_ms:,
|
|
end_ms:)
|
|
end
|
|
end
|
|
PostTag.where(post_id: post.id,
|
|
tag_id: (current_ids - desired_ids).to_a).kept.find_each do |post_tag|
|
|
post_tag.discard_by!(@actor)
|
|
end
|
|
end
|
|
|
|
def sync_parent_posts! post, ids
|
|
if ids.include?(post.id)
|
|
post.errors.add :parent_post_ids, '自分自身を親投稿にはできません.'
|
|
raise ActiveRecord::RecordInvalid, post
|
|
end
|
|
missing = ids - Post.where(id: ids).pluck(:id)
|
|
if missing.present?
|
|
post.errors.add :parent_post_ids, "存在しない親投稿 Id. があります: #{ missing.join(' ') }"
|
|
raise ActiveRecord::RecordInvalid, post
|
|
end
|
|
ids.each { |parent_post_id| PostImplication.create_or_find_by!(post:, parent_post_id:) }
|
|
end
|
|
end
|