# frozen_string_literal: true # == Schema Information # # Table name: duplicate_reports # # id :integer not null, primary key # reason :string # state :string default("open"), not null # created_at :datetime not null # updated_at :datetime not null # duplicate_of_post_id :integer not null # modifier_id :integer # post_id :integer not null # user_id :integer # # Indexes # # index_duplicate_reports_on_created_at (created_at) # index_duplicate_reports_on_duplicate_of_post_id (duplicate_of_post_id) # index_duplicate_reports_on_modifier_id (modifier_id) # index_duplicate_reports_on_post_id (post_id) # index_duplicate_reports_on_state (state) # index_duplicate_reports_on_user_id (user_id) # # Foreign Keys # # fk_rails_... (duplicate_of_post_id => posts.id) # fk_rails_... (modifier_id => users.id) ON DELETE => nullify ON UPDATE => cascade # fk_rails_... (post_id => posts.id) # fk_rails_... (user_id => users.id) ON DELETE => nullify ON UPDATE => cascade # class DuplicateReport < ApplicationRecord include DupeTools belongs_to :user, optional: true belongs_to :post, class_name: 'Post', inverse_of: nil, optional: true belongs_to :duplicate_of_post, class_name: 'Post', inverse_of: nil, optional: true belongs_to :modifier, class_name: 'User', inverse_of: nil, optional: true resourcify validates_with DuplicateReportMergeValidator validates_with DuplicateReportCreationValidator, on: :create # Run deduplicator(s) and generate report objects def self.generate_reports(new_post) # TODO: upsert_all new_post.media.detect_duplicates.each do |dupe_post| next if dupe_post.id == new_post.id # FIXME? DuplicateReport.create! post: new_post, duplicate_of_post: dupe_post, reason: 'Automated perceptual dedupe match', user: nil end end def accept!(user) duplicate_of_post.tag_input = duplicate_of_post.tag_list + ',' + post.tag_list if duplicate_of_post.valid? && valid? post.duplicate_reports.where(state: 'open').update_all(state: 'rejected') duplicate_of_post.duplicate_reports.where(duplicate_of_post: post).update_all(state: 'rejected') update modifier: user, state: 'accepted' # DuplicateMergeLogger.log(post, duplicate_of_post, user) Notification.async_notify duplicate_of_post, "merged post ##{post_id}" ImageDuplicateMergeJob.perform_later post_id, duplicate_of_post_id, user.id true else errors[:base] << "Post to keep: #{duplicate_of_post.errors.full_messages.first}" false end end def claim!(user) update_columns modifier_id: user.id, state: 'claimed' end def reject!(user) update_columns modifier_id: user.id, state: 'rejected' post.duplication_checked = true post.duplicate_id = nil PostUnhider.new(post).save true end end