Files
danbooru/app/models/bulk_update_request.rb
evazion 3114ef3daf searchable: standardize the <field>_matches operator for text fields.
Standardize it so that all fields of type `text` are searchable with
`search[<field>_matches]`.

Before, the `<field>_matches` param was handled manually and some fields
were left out or handled inconsistently. Now it applies to all columns
of type `text`.

This does a full-text search on the field, so for example, searching
`/artist_commentaries?search[translated_description_matches]=smiling`
will match translated commentaries containing either the word "smiling",
"smiles", "smiled", or "smile".

Note that this only applies to columns defined as type `text`, not to
columns defined as `character varying`. The difference is that `text` is
used for fields containing free-form natural language, such as comments,
notes, forum posts, wiki pages, pool descriptions, etc, while `character
varying` is used for short strings not containing free-form language,
such as tag names, wiki page titles, urls, status fields, etc.

API changes:

* Add the `search[original_title_matches]`, `search[original_description_matches]`,
  `search[translated_title_matches]`, `search[translated_description_matches]` params
  to /artist_commentaries and /artist_commentary_versions.
* Remove the `search[name_matches]` and `search[group_name_matches]` params from /artist_versions.
* Remove the `search[title_matches]` param from /wiki_page_versions.
* Change the `search[name_matches]` param on /pools, /favorite_groups, and /pool_versions
  to do a full-text search instead of a substring match.
2022-09-22 01:52:13 -05:00

131 lines
3.8 KiB
Ruby

# frozen_string_literal: true
class BulkUpdateRequest < ApplicationRecord
STATUSES = %w[pending approved rejected processing failed]
attr_accessor :title, :reason
belongs_to :user
belongs_to :forum_topic, optional: true
belongs_to :forum_post, optional: true
belongs_to :approver, optional: true, class_name: "User"
validates :reason, presence: true, on: :create
validates :script, presence: true
validates :title, presence: true, if: ->(rec) { rec.forum_topic_id.blank? }
validates :forum_topic, presence: true, if: ->(rec) { rec.forum_topic_id.present? }
validates :status, inclusion: { in: STATUSES }
validate :validate_script, if: :script_changed?
before_save :update_tags, if: :script_changed?
after_create :create_forum_topic
scope :pending_first, -> { order(Arel.sql("(case status when 'processing' then 0 when 'pending' then 1 when 'approved' then 2 when 'rejected' then 3 when 'failed' then 4 else 5 end)")) }
scope :pending, -> {where(status: "pending")}
scope :approved, -> { where(status: "approved") }
scope :rejected, -> { where(status: "rejected") }
scope :processing, -> { where(status: "processing") }
scope :failed, -> { where(status: "failed") }
scope :has_topic, -> { where.not(forum_topic: nil) }
module SearchMethods
def search(params = {})
q = search_attributes(params, :id, :created_at, :updated_at, :script, :tags, :user, :forum_topic, :forum_post, :approver)
if params[:status].present?
q = q.where(status: params[:status].split(","))
end
params[:order] ||= "status_desc"
case params[:order]
when "id_desc"
q = q.order(id: :desc)
when "id_asc"
q = q.order(id: :asc)
when "updated_at_desc"
q = q.order(updated_at: :desc)
when "updated_at_asc"
q = q.order(updated_at: :asc)
else
q = q.apply_default_order(params)
end
q
end
end
module ApprovalMethods
def forum_updater
@forum_updater ||= ForumUpdater.new(forum_topic)
end
def approve!(approver)
transaction do
CurrentUser.scoped(approver) do
processor.validate!(:approval)
update!(status: "processing", approver: approver)
processor.process_later!
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has been approved by @#{approver.name}.")
end
end
end
def create_forum_topic
CurrentUser.scoped(user) do
body = "[bur:#{id}]\n\n#{reason}"
self.forum_topic = ForumTopic.create(title: title, category_id: 1, creator: user) unless forum_topic.present?
self.forum_post = forum_topic.forum_posts.create(body: body, creator: user) unless forum_post.present?
save
end
end
def reject!(rejector = User.system)
transaction do
update!(status: "rejected")
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has been rejected by @#{rejector.name}.")
end
end
def bulk_update_request_link
%{"bulk update request ##{id}":#{Routes.bulk_update_requests_path(search: { id: id })}}
end
end
def validate_script
if processor.invalid?(:request)
errors.add(:base, processor.errors.full_messages.join("; "))
end
end
extend SearchMethods
include ApprovalMethods
def update_tags
self.tags = processor.affected_tags
end
def processor
@processor ||= BulkUpdateRequestProcessor.new(self)
end
def is_tag_move_allowed?
processor.is_tag_move_allowed?
end
def is_pending?
status == "pending"
end
def is_approved?
status.in?(%w[approved processing])
end
def is_rejected?
status == "rejected"
end
def self.available_includes
[:user, :forum_topic, :forum_post, :approver]
end
end