pools: add ability to search for pools linking to given tag.

Add ability to search for pools linking to a given tag in the pool
description. Example:

    https://danbooru.donmai.us/pools?search[linked_to]=touhou

(This isn't actually exposed in the UI to avoid cluttering the pool
search form with rarely used options.)

Pools with broken links can be found here:

    https://danbooru.donmai.us/dtext_links?search[has_linked_tag]=No&search[has_linked_wiki]=No&search[model_type]=Pool

Lays the groundwork for fixing #4629.
This commit is contained in:
evazion
2022-01-15 20:16:06 -06:00
parent c3c4f5a2a7
commit 33103f6dc4
10 changed files with 72 additions and 42 deletions

View File

@@ -7,6 +7,7 @@ class ApplicationRecord < ActiveRecord::Base
include Mentionable
include Normalizable
include ArrayAttribute
include HasDtextLinks
extend HasBitFlags
extend Searchable

View File

@@ -12,15 +12,16 @@ class DtextLink < ApplicationRecord
scope :wiki_page, -> { where(model_type: "WikiPage") }
scope :forum_post, -> { where(model_type: "ForumPost") }
scope :pool, -> { where(model_type: "Pool") }
def self.visible(user)
# XXX the double negation is to prevent postgres from choosing a bad query
# plan (it doesn't know that most forum posts aren't mod-only posts).
wiki_page.or(forum_post.where.not(model_id: ForumPost.not_visible(user)))
wiki_page.or(forum_post.where.not(model_id: ForumPost.not_visible(user))).or(pool)
end
def self.model_types
%w[WikiPage ForumPost]
%w[WikiPage ForumPost Pool]
end
def self.new_from_dtext(dtext)

View File

@@ -7,7 +7,6 @@ class ForumPost < ApplicationRecord
belongs_to_updater
belongs_to :topic, class_name: "ForumTopic", inverse_of: :forum_posts
has_many :dtext_links, as: :model, dependent: :destroy
has_many :moderation_reports, as: :model
has_many :votes, class_name: "ForumPostVote"
has_one :tag_alias
@@ -16,7 +15,6 @@ class ForumPost < ApplicationRecord
validates :body, presence: true, length: { maximum: 200_000 }, if: :body_changed?
before_save :update_dtext_links, if: :dtext_links_changed?
before_create :autoreport_spam
after_create :update_topic_updated_at_on_create
after_update :update_topic_updated_at_on_update_for_original_posts
@@ -31,6 +29,7 @@ class ForumPost < ApplicationRecord
after_create_commit :async_send_discord_notification
deletable
has_dtext_links :body
mentionable(
message_field: :body,
title: ->(_user_name) {%{#{creator.name} mentioned you in topic ##{topic_id} (#{topic.title})}},
@@ -112,14 +111,6 @@ class ForumPost < ApplicationRecord
update_topic_updated_at_on_undelete
end
def dtext_links_changed?
body_changed? && DText.dtext_links_differ?(body, body_was)
end
def update_dtext_links
self.dtext_links = DtextLink.new_from_dtext(body)
end
def update_topic_updated_at_on_delete
max = ForumPost.where(:topic_id => topic.id, :is_deleted => false).order("updated_at desc").first
if max

View File

@@ -15,6 +15,7 @@ class Pool < ApplicationRecord
after_save :create_version
deletable
has_dtext_links :description
scope :series, -> { where(category: "series") }
scope :collection, -> { where(category: "collection") }
@@ -37,7 +38,7 @@ class Pool < ApplicationRecord
end
def search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :is_deleted, :name, :description, :post_ids)
q = search_attributes(params, :id, :created_at, :updated_at, :is_deleted, :name, :description, :post_ids, :dtext_links)
q = q.text_attribute_matches(:description, params[:description_matches])
if params[:post_tags_match]
@@ -48,6 +49,14 @@ class Pool < ApplicationRecord
q = q.name_matches(params[:name_matches])
end
if params[:linked_to].present?
q = q.linked_to(params[:linked_to])
end
if params[:not_linked_to].present?
q = q.not_linked_to(params[:not_linked_to])
end
case params[:category]
when "series"
q = q.series

View File

@@ -5,7 +5,6 @@ class WikiPage < ApplicationRecord
META_WIKIS = ["list_of_", "tag_group:", "pool_group:", "howto:", "about:", "help:", "template:"]
before_save :update_dtext_links, if: :dtext_links_changed?
after_save :create_version
normalize :title, :normalize_title
@@ -22,9 +21,9 @@ class WikiPage < ApplicationRecord
has_one :tag, :foreign_key => "name", :primary_key => "title"
has_one :artist, -> { active }, foreign_key: "name", primary_key: "title"
has_many :versions, -> {order("wiki_page_versions.id ASC")}, :class_name => "WikiPageVersion", :dependent => :destroy
has_many :dtext_links, as: :model, dependent: :destroy
deletable
has_dtext_links :body
module SearchMethods
def find_by_id_or_title(id)
@@ -58,14 +57,6 @@ class WikiPage < ApplicationRecord
end
end
def linked_to(title)
where(dtext_links: DtextLink.wiki_page.wiki_link.where(link_target: normalize_title(title)))
end
def not_linked_to(title)
where.not(dtext_links: DtextLink.wiki_page.wiki_link.where(link_target: normalize_title(title)))
end
def default_order
order(updated_at: :desc)
end
@@ -213,14 +204,6 @@ class WikiPage < ApplicationRecord
end
end
def dtext_links_changed?
body_changed? && DText.dtext_links_differ?(body, body_was)
end
def update_dtext_links
self.dtext_links = DtextLink.new_from_dtext(body)
end
def tags
titles = DText.parse_wiki_titles(body).uniq
tags = Tag.nonempty.where(name: titles).pluck(:name)